net6 things

This commit is contained in:
z__
2022-01-22 21:13:38 +07:00
parent 81d11a32fe
commit 58b9c926ae
103 changed files with 1476 additions and 2731 deletions

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<variable name="logStamp" value="${time} ${pad:padding=-8:inner=[${level:uppercase=true}]}" />
<variable name="logContent" value="${message:withException=true}"/>
<targets async="true">
<target xsi:type="Null" name="null" formatMessage="false" />
<target xsi:type="File" name="keen" layout="${var:logStamp} ${logger}: ${var:logContent}" fileName="Logs\Keen-${shortdate}.log" />
<target xsi:type="File" name="main" layout="${var:logStamp} ${logger}: ${var:logContent}" fileName="Logs\Torch-${shortdate}.log" />
<target xsi:type="File" name="chat" layout="${longdate} ${message}" fileName="Logs\Chat.log" />
<target xsi:type="ColoredConsole" name="console" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
<target xsi:type="File" name="patch" layout="${var:logContent}" fileName="Logs\patch.log"/>
<target xsi:type="FlowDocument" name="wpf" layout="${var:logStamp} ${logger:shortName=true}: ${var:logContent}" />
</targets>
<rules>
<!-- Define custom rules below. The example line will pipe all debug output to log file, in-UI console, and independent console. -->
<!--<logger name="*" minlevel="Debug" writeTo="main, console, wpf" />-->
</rules>
</nlog>

View File

@@ -4,8 +4,6 @@
<variable name="logStamp" value="${time} ${pad:padding=-8:inner=[${level:uppercase=true}]}" />
<variable name="logContent" value="${message:withException=true}"/>
<include file="NLog-user.config"/>
<targets async="true">
<target xsi:type="Null" name="null" formatMessage="false" />
<target xsi:type="File" name="keen" layout="${var:logStamp} ${logger}: ${var:logContent}" fileName="Logs\Keen-${shortdate}.log" />

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

View File

@@ -1,205 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.API</RootNamespace>
<AssemblyName>Torch.API</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<TargetFramework>net6-windows</TargetFramework>
<AssemblyTitle>Torch API</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutputPath>
<UseWpf>True</UseWpf>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(SolutionDir)\bin\x64\Release\Torch.API.xml</DocumentationFile>
<PropertyGroup Condition="$(Configuration) == 'Release'">
<DocumentationFile>$(SolutionDir)\bin\$(Platform)\$(Configuration)\Torch.API.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="4.7.13" />
</ItemGroup>
<ItemGroup>
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Dedicated">
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Library">
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="ConnectionState.cs" />
<Compile Include="InformationalVersion.cs" />
<Compile Include="ITorchConfig.cs" />
<Compile Include="Managers\DependencyManagerExtensions.cs" />
<Compile Include="Managers\DependencyProviderExtensions.cs" />
<Compile Include="Event\EventHandlerAttribute.cs" />
<Compile Include="Event\IEvent.cs" />
<Compile Include="Event\IEventHandler.cs" />
<Compile Include="Managers\IChatManagerClient.cs" />
<Compile Include="Managers\IChatManagerServer.cs" />
<Compile Include="Managers\IDependencyManager.cs" />
<Compile Include="Managers\IDependencyProvider.cs" />
<Compile Include="Event\IEventManager.cs" />
<Compile Include="Managers\IManager.cs" />
<Compile Include="Managers\IMultiplayerManagerClient.cs" />
<Compile Include="Managers\IMultiplayerManagerBase.cs" />
<Compile Include="IPlayer.cs" />
<Compile Include="Managers\IMultiplayerManagerServer.cs" />
<Compile Include="Managers\INetworkManager.cs" />
<Compile Include="Managers\IPluginManager.cs" />
<Compile Include="Plugins\ITorchPlugin.cs" />
<Compile Include="IServerControls.cs" />
<Compile Include="ITorchBase.cs" />
<Compile Include="Plugins\IWpfPlugin.cs" />
<Compile Include="ModAPI\Ingame\GridExtensions.cs" />
<Compile Include="Plugins\PluginAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerState.cs" />
<Compile Include="ModAPI\TorchAPI.cs" />
<Compile Include="Session\GameSaveResult.cs" />
<Compile Include="Session\ITorchSession.cs" />
<Compile Include="Session\ITorchSessionManager.cs" />
<Compile Include="Session\TorchSessionState.cs" />
<Compile Include="TorchGameState.cs" />
<Compile Include="UGCServiceType.cs" />
<Compile Include="Utils\ColorUtils.cs" />
<Compile Include="Utils\StringUtils.cs" />
<Compile Include="WebAPI\JenkinsQuery.cs" />
<Compile Include="WebAPI\PluginQuery.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
</Project>

View File

@@ -1,82 +1,45 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NLog;
namespace Torch.API.WebAPI
{
public class PluginQuery
{
private const string ALL_QUERY = "https://torchapi.com/api/plugins";
private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/item/{0}";
private const string ALL_QUERY = "https://torchapi.com/api/plugins/";
private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/item/{0}/";
private readonly HttpClient _client;
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
private static PluginQuery _instance;
public static PluginQuery Instance => _instance ?? (_instance = new PluginQuery());
public static PluginQuery Instance => _instance ??= new();
private PluginQuery()
{
_client = new HttpClient();
_client = new();
}
public async Task<PluginResponse> QueryAll()
public async Task<PluginsResponse> QueryAll()
{
var h = await _client.GetAsync(ALL_QUERY);
if (!h.IsSuccessStatusCode)
{
Log.Error($"Plugin query returned response {h.StatusCode}");
return null;
}
var r = await h.Content.ReadAsStringAsync();
PluginResponse response;
try
{
response = JsonConvert.DeserializeObject<PluginResponse>(r);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to deserialize plugin query response!");
return null;
}
return response;
return (PluginsResponse) await _client.GetFromJsonAsync(ALL_QUERY, typeof(PluginsResponse), CancellationToken.None);
}
public async Task<PluginFullItem> QueryOne(Guid guid)
public Task<PluginItem> QueryOne(Guid guid)
{
return await QueryOne(guid.ToString());
return QueryOne(guid.ToString());
}
public async Task<PluginFullItem> QueryOne(string guid)
public async Task<PluginItem> QueryOne(string guid)
{
var h = await _client.GetAsync(string.Format(PLUGIN_QUERY, guid));
if (!h.IsSuccessStatusCode)
{
Log.Error($"Plugin query returned response {h.StatusCode}");
return null;
}
var r = await h.Content.ReadAsStringAsync();
PluginFullItem response;
try
{
response = JsonConvert.DeserializeObject<PluginFullItem>(r);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to deserialize plugin query response!");
return null;
}
return response;
return (PluginItem) await _client.GetFromJsonAsync(string.Format(PLUGIN_QUERY, guid), typeof(PluginItem),
CancellationToken.None);
}
public async Task<bool> DownloadPlugin(Guid guid, string path = null)
@@ -91,39 +54,31 @@ namespace Torch.API.WebAPI
return await DownloadPlugin(item, path);
}
public async Task<bool> DownloadPlugin(PluginFullItem item, string path = null)
public async Task<bool> DownloadPlugin(PluginItem item, string path = null)
{
try
{
path = path ?? $"Plugins\\{item.Name}.zip";
string relpath = Path.GetDirectoryName(path);
path ??= Path.Combine(Directory.GetCurrentDirectory(), "Plugins", $"{item.Name}.zip");
Directory.CreateDirectory(relpath);
var h = await _client.GetAsync(string.Format(PLUGIN_QUERY, item.ID));
string res = await h.Content.ReadAsStringAsync();
var response = JsonConvert.DeserializeObject<PluginFullItem>(res);
var response = await QueryOne(item.Id);
if (response.Versions.Length == 0)
{
Log.Error($"Selected plugin {item.Name} does not have any versions to download!");
return false;
}
var version = response.Versions.FirstOrDefault(v => v.Version == response.LatestVersion);
if (version == null)
if (version is null)
{
Log.Error($"Could not find latest version for selected plugin {item.Name}");
return false;
}
var s = await _client.GetStreamAsync(version.URL);
var s = await _client.GetStreamAsync(version.Url);
if(File.Exists(path))
File.Delete(path);
using (var f = File.Create(path))
{
await s.CopyToAsync(f);
await f.FlushAsync();
}
await using var f = File.Create(path);
await s.CopyToAsync(f);
}
catch (Exception ex)
{
@@ -134,37 +89,15 @@ namespace Torch.API.WebAPI
}
}
public class PluginResponse
public record PluginsResponse(PluginItem[] Plugins);
public record PluginItem(Guid Id, string Name, string Author, string Description, string LatestVersion,
VersionItem[] Versions)
{
public PluginItem[] Plugins;
public int Count;
[JsonIgnore]
public bool Installed { get; set; }
}
public class PluginItem
{
public string ID;
public string Name { get; set; }
public string Author;
public string Description;
public string LatestVersion;
public bool Installed { get; set; } = false;
public override string ToString()
{
return Name;
}
}
public class PluginFullItem : PluginItem
{
public VersionItem[] Versions;
}
public class VersionItem
{
public string Version;
public string Note;
public bool IsBeta;
public string URL;
}
public record VersionItem(string Version, string Note, [property: JsonPropertyName("is_beta")] bool IsBeta,
string Url);
}

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
</packages>

View File

@@ -1,98 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{632E78C0-0DAC-4B71-B411-2F1B333CC310}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.Client.Tests</RootNamespace>
<AssemblyName>Torch.Client.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFramework>net461</TargetFramework>
<NoWarn>1591,0649</NoWarn>
<AssemblyTitle>Torch Client Tests</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin-test\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin-test\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(SolutionDir)\bin-test\x64\Release\Torch.Client.Tests.xml</DocumentationFile>
<DocumentationFile>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\Torch.Client.Tests.xml</DocumentationFile>
</PropertyGroup>
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<ItemGroup>
<PackageReference Include="Mono.TextTransform" Version="1.0.0" />
<PackageReference Include="NLog" Version="4.4.12" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.abstractions" Version="2.0.1" />
<PackageReference Include="xunit.assert" Version="2.2.0" />
<PackageReference Include="xunit.core" Version="2.2.0" />
<PackageReference Include="xunit.extensibility.core" Version="2.2.0" />
<PackageReference Include="xunit.extensibility.execution" Version="2.2.0" />
<PackageReference Include="xunit.runner.console" Version="2.2.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TorchClientReflectionTest.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
</ProjectReference>
<ProjectReference Include="..\Torch.Client\Torch.Client.csproj">
<Project>{e36df745-260b-4956-a2e8-09f08b2e7161}</Project>
<Name>Torch.Client</Name>
</ProjectReference>
<ProjectReference Include="..\Torch.Tests\Torch.Tests.csproj">
<Project>{c3c8b671-6ad1-44aa-a8da-e0c0dc0fedf5}</Project>
<Name>Torch.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Torch</Name>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
<ProjectReference Include="..\Torch.Client\Torch.Client.csproj" />
<ProjectReference Include="..\Torch.Tests\Torch.Tests.csproj" />
<ProjectReference Include="..\Torch\Torch.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<Compile Remove="obj\x64\Debug\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
<Compile Remove="obj\x64\Release\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
</Project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
<package id="xunit" version="2.2.0" targetFramework="net461" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net461" />
<package id="xunit.assert" version="2.2.0" targetFramework="net461" />
<package id="xunit.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net461" />
<package id="xunit.runner.console" version="2.2.0" targetFramework="net461" developmentDependency="true" />
</packages>

View File

@@ -1,81 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<ProjectGuid>{E36DF745-260B-4956-A2E8-09F08B2E7161}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.Client</RootNamespace>
<AssemblyName>Torch.Client</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFramework>net461</TargetFramework>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<AssemblyTitle>Torch Client</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutputPath>
<Prefer32Bit>true</Prefer32Bit>
<UseWPF>true</UseWPF>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
</PostBuildEvent>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
</PostBuildEvent>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<DocumentationFile>$(SolutionDir)\bin\x64\Release\Torch.Client.xml</DocumentationFile>
<DocumentationFile>$(SolutionDir)\bin\$(Platform)\$(Configuration)\Torch.Client.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>torchicon.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<ItemGroup>
<PackageReference Include="Mono.TextTransform" Version="1.0.0" />
<PackageReference Include="NLog" Version="4.4.12" />
</ItemGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Game">
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6108.20417, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="SpaceEngineers.Game">
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="VRage">
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
@@ -89,18 +76,18 @@
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Library">
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Render">
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
@@ -119,65 +106,17 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="Manager\MultiplayerManagerClient.cs" />
<Compile Include="Manager\MultiplayerManagerLobby.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TorchClient.cs" />
<Compile Include="TorchClientConfig.cs" />
<Compile Include="TorchConsoleScreen.cs" />
<Compile Include="TorchSettingsScreen.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="UI\TorchMainMenuScreen.cs" />
<Compile Include="UI\TorchNavScreen.cs" />
<Compile Include="UI\TorchSettingsScreen.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7E01635C-3B67-472E-BCD6-C5539564F214}</Project>
<Name>Torch</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
<ProjectReference Include="..\Torch\Torch.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="torchicon.ico" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
<Compile Remove="obj\x64\Debug\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
<Compile Remove="obj\x64\Release\.NETFramework,Version=v4.6.1.AssemblyAttributes.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<PropertyGroup>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
</packages>

View File

@@ -7,7 +7,6 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="Torch.Mod.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>

View File

@@ -1,107 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.Server.Tests</RootNamespace>
<AssemblyName>Torch.Server.Tests</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFramework>net6-windows</TargetFramework>
<NoWarn>1591,0649</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin-test\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<AssemblyTitle>Torch Server Tests</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin-test\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(SolutionDir)\bin-test\x64\Release\Torch.Server.Tests.xml</DocumentationFile>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration) == 'Release'">
<DocumentationFile>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\Torch.Server.Tests.xml</DocumentationFile>
</PropertyGroup>
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="xunit" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
</Reference>
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TorchServerReflectionTest.cs" />
<Compile Include="TorchServerSessionSettingsTest.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties\AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
</ProjectReference>
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj">
<Project>{ca50886b-7b22-4cd8-93a0-c06f38d4f77d}</Project>
<Name>Torch.Server</Name>
</ProjectReference>
<ProjectReference Include="..\Torch.Tests\Torch.Tests.csproj">
<Project>{c3c8b671-6ad1-44aa-a8da-e0c0dc0fedf5}</Project>
<Name>Torch.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Torch</Name>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
<ProjectReference Include="..\Torch.Server\Torch.Server.csproj" />
<ProjectReference Include="..\Torch.Tests\Torch.Tests.csproj" />
<ProjectReference Include="..\Torch\Torch.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
</Project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
<package id="xunit" version="2.2.0" targetFramework="net461" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net461" />
<package id="xunit.assert" version="2.2.0" targetFramework="net461" />
<package id="xunit.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net461" />
<package id="xunit.runner.console" version="2.2.0" targetFramework="net461" developmentDependency="true" />
</packages>

View File

@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressWarnings" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -229,37 +229,11 @@ quit";
}
}
private void LogException(Exception ex)
{
if (ex is AggregateException ag)
{
foreach (var e in ag.InnerExceptions)
LogException(e);
return;
}
Log.Fatal(ex);
if (ex is ReflectionTypeLoadException extl)
{
foreach (var exl in extl.LoaderExceptions)
LogException(exl);
return;
}
if (ex.InnerException != null)
{
LogException(ex.InnerException);
}
}
private void HandleException(object sender, UnhandledExceptionEventArgs e)
{
_server.FatalException = true;
var ex = (Exception)e.ExceptionObject;
LogException(ex);
Log.Fatal(ex.ToStringDemystified());
if (MyFakes.ENABLE_MINIDUMP_SENDING)
{
string path = Path.Combine(MyFileSystem.UserDataPath, "Minidump.dmp");
@@ -274,7 +248,7 @@ quit";
Console.WriteLine("Restarting in 5 seconds.");
Thread.Sleep(5000);
var exe = typeof(Program).Assembly.Location;
Config.WaitForPID = Process.GetCurrentProcess().Id.ToString();
Config.WaitForPID = Environment.ProcessId.ToString();
Process.Start(exe, Config.ToString());
}
else
@@ -282,7 +256,7 @@ quit";
MessageBox.Show("Torch encountered a fatal error and needs to close. Please check the logs for details.");
}
Process.GetCurrentProcess().Kill();
Environment.Exit(1);
}
}
}

View File

@@ -40,15 +40,7 @@ namespace Torch.Server.Managers
protected abstract EntityControlViewModel Create(EntityViewModel evm);
#pragma warning disable 649
[ReflectedGetter(Name = "Keys")]
private static readonly Func<ConditionalWeakTable<EntityViewModel, EntityControlViewModel>, ICollection<EntityViewModel>> _weakTableKeys;
#pragma warning restore 649
/// <summary>
/// Warning: Creates a giant list, avoid if possible.
/// </summary>
internal ICollection<EntityViewModel> Keys => _weakTableKeys(_models);
internal IEnumerable<EntityViewModel> Keys => _models.Select(b => b.Key);
internal EntityControlViewModel GetOrCreate(EntityViewModel evm)
{

View File

@@ -319,9 +319,6 @@ namespace Torch.Server.Managers
checkpoint.Mods = null;
checkpoint.Settings = null;
}
OnPropertyChanged(nameof(Checkpoint));
OnPropertyChanged(nameof(WorldConfiguration));
}
}
}

View File

@@ -0,0 +1,39 @@
using System.Reflection;
using NLog;
using Sandbox.Engine.Networking;
using Torch.API.Managers;
using Torch.Managers.PatchManager;
using Torch.Server.Managers;
using Torch.Utils;
using VRage.Game;
namespace Torch.Patches;
[PatchShim]
public static class CheckpointLoadPatch
{
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
[ReflectedMethodInfo(typeof(MyLocalCache), "LoadCheckpoint")]
private static MethodInfo LoadCheckpointMethod = null!;
public static void Patch(PatchContext context)
{
context.GetPattern(LoadCheckpointMethod).AddPrefix();
}
private static bool Prefix(ref MyObjectBuilder_Checkpoint __result)
{
#pragma warning disable CS0618
var world = TorchBase.Instance.Managers.GetManager<InstanceManager>().DedicatedConfig.SelectedWorld;
#pragma warning restore CS0618
if (world is null)
{
Log.Error("Selected world is null");
return false;
}
__result = world.Checkpoint;
return false;
}
}

View File

@@ -4,11 +4,12 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
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;
@@ -26,46 +27,27 @@ namespace Torch.Server
{
Target.Register<FlowDocumentTarget>("FlowDocument");
//Ensures that all the files are downloaded in the Torch directory.
var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory.ToString();
var workingDir = new FileInfo(typeof(Program).Assembly.Location).Directory!.FullName;
var binDir = Path.Combine(workingDir, "DedicatedServer64");
Directory.SetCurrentDirectory(workingDir);
//HACK for block skins update
var badDlls = new[]
{
"System.Security.Principal.Windows.dll",
"VRage.Platform.Windows.dll"
};
try
{
foreach (var file in badDlls)
if (Directory.Exists(binDir))
foreach (var file in Directory.GetFiles(binDir, "System.*.dll"))
{
if (File.Exists(file))
File.Delete(file);
File.Delete(file);
}
}
catch (Exception e)
{
var log = LogManager.GetCurrentClassLogger();
log.Error($"Error updating. Please delete the following files from the Torch root folder manually:\r\n{string.Join("\r\n", badDlls)}");
log.Error(e);
return;
}
if (!TorchLauncher.IsTorchWrapped())
{
TorchLauncher.Launch(Assembly.GetEntryAssembly().FullName, args, binDir);
return;
}
TorchLauncher.Launch(workingDir, binDir);
// Breaks on Windows Server 2019
#if TORCH_SERVICE
if (!new ComputerInfo().OSFullName.Contains("Server 2019") && !Environment.UserInteractive)
{
using (var service = new TorchService(args))
ServiceBase.Run(service);
return;
}
#endif
var initializer = new Initializer(workingDir);
if (!initializer.Initialize(args))

View File

@@ -0,0 +1,11 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"Torch.Server": {
"commandName": "Project",
"commandLineArgs": "-noupdate",
"use64Bit": true,
"hotReloadEnabled": false
}
}
}

View File

@@ -4,11 +4,9 @@
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.AnimatedSingleRowTabControl.xaml" />
<!-- AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Dark.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.Tabcontrol.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Hyperlink" x:Name="LegalshtuffLink">

View File

@@ -5,10 +5,9 @@
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<!-- AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Dark.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.Tabcontrol.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TabControl">

View File

@@ -6,11 +6,9 @@
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.AnimatedSingleRowTabControl.xaml" />
<!-- AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.Tabcontrol.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Hyperlink" x:Name="LegalshtuffLink">

View File

@@ -5,10 +5,9 @@
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<!-- AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.Tabcontrol.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TabControl">

View File

@@ -1,21 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.Server</RootNamespace>
<AssemblyName>Torch.Server</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFramework>net6-windows</TargetFramework>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>7.3</LangVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -31,27 +19,20 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<AssemblyTitle>Torch Server</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutputPath>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<DocumentationFile>$(SolutionDir)\bin\x64\Release\Torch.Server.xml</DocumentationFile>
<PropertyGroup Condition="$(Configuration) == 'Release'">
<DocumentationFile>$(SolutionDir)\bin\$(Platform)\$(Configuration)\Torch.Server.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<StartupObject>Torch.Server.Program</StartupObject>
@@ -59,479 +40,140 @@
<PropertyGroup>
<ApplicationIcon>torchicon.ico</ApplicationIcon>
</PropertyGroup>
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
<ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<PackageReference Include="ControlzEx" Version="5.0.1" />
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="MdXaml" Version="1.12.0" />
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.0.226801" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Management" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll</HintPath>
</Reference>
<Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MahApps.Metro, Version=1.6.1.4, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.1.6.1\lib\net45\MahApps.Metro.dll</HintPath>
</Reference>
<Reference Include="Markdown.Xaml, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Markdown.Xaml.1.0.0\lib\net45\Markdown.Xaml.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Microsoft.Win32.Registry, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.4.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51">
<HintPath>..\GameBinaries\netstandard.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="protobuf-net, Version=2.4.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
<HintPath>..\packages\protobuf-net.2.4.0\lib\net40\protobuf-net.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Game, Version=0.1.6305.30774, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Game.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6305.30761, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Sandbox.Graphics.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Steamworks.NET">
<HintPath>..\GameBinaries\Steamworks.NET.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\System.ComponentModel.Annotations.4.5.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.AccessControl, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.4.4.0\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.4.4.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="VRage, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Audio.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Dedicated, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Dedicated.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Library.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Math.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Platform.Windows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<Reference Include="VRage.Platform.Windows, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Render11.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\VRage.Scripting.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="VRage.Steam">
<HintPath>..\GameBinaries\VRage.Steam.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="Commands\WhitelistCommands.cs" />
<Compile Include="FlowDocumentTarget.cs" />
<Compile Include="ListBoxExtensions.cs" />
<Compile Include="Managers\EntityControlManager.cs" />
<Compile Include="Managers\MultiplayerManagerDedicated.cs" />
<Compile Include="Managers\InstanceManager.cs" />
<Compile Include="Managers\MultiplayerManagerDedicatedEventShim.cs" />
<Compile Include="Managers\MultiplayerManagerDedicatedPatchShim.cs" />
<Compile Include="Managers\RemoteAPIManager.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="Initializer.cs" />
<Compile Include="Patches\PromotePatch.cs" />
<Compile Include="Patches\ServerResponsePatch.cs" />
<Compile Include="Patches\WorldLoadExceptionPatch.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TorchConfig.cs" />
<Compile Include="TorchService.cs">
<Compile Update="TorchService.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="TorchServiceInstaller.cs">
<Compile Update="TorchServiceInstaller.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ViewModels\BlockLimitViewModel.cs" />
<Compile Include="ViewModels\CheckpointViewModel.cs" />
<Compile Include="ViewModels\Entities\Blocks\BlockViewModel.cs" />
<Compile Include="ViewModels\Entities\Blocks\BlockViewModelGenerator.cs" />
<Compile Include="ViewModels\Entities\Blocks\PropertyViewModel.cs" />
<Compile Include="ViewModels\Entities\CharacterViewModel.cs" />
<Compile Include="ViewModels\ConfigDedicatedViewModel.cs" />
<Compile Include="ViewModels\Entities\EntityControlViewModel.cs" />
<Compile Include="ViewModels\ModItemInfo.cs" />
<Compile Include="ViewModels\SessionSettingsViewModel.cs" />
<Compile Include="ViewModels\WorldConfigurationViewModel.cs" />
<Compile Include="Views\Converters\DefinitionToIdConverter.cs" />
<Compile Include="Views\Converters\BooleanAndConverter.cs" />
<Compile Include="Views\Converters\ListConverter.cs" />
<Compile Include="MultiTextWriter.cs" />
<Compile Include="RichTextBoxWriter.cs" />
<Compile Include="Views\Converters\ListConverterWorkshopId.cs" />
<Compile Include="Views\Converters\ModToIdConverter.cs" />
<Compile Include="Views\Entities\CharacterView.xaml.cs">
<DependentUpon>CharacterView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Extensions.cs" />
<Compile Include="Views\ModListControl.xaml.cs">
<DependentUpon>ModListControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PluginBrowser.xaml.cs">
<DependentUpon>PluginBrowser.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PluginDownloader.xaml.cs">
<DependentUpon>PluginDownloader.xaml</DependentUpon>
</Compile>
<Compile Include="Views\RoleEditor.xaml.cs">
<DependentUpon>RoleEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ThemeControl.xaml.cs">
<DependentUpon>ThemeControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ValidationRules\ListConverterValidationRule.cs" />
<Compile Include="Views\Entities\EntityControlHost.xaml.cs">
<DependentUpon>EntityControlHost.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Entities\EntityControlsView.xaml.cs">
<DependentUpon>EntityControlsView.xaml</DependentUpon>
</Compile>
<Compile Include="ViewModels\EntityTreeViewModel.cs" />
<Compile Include="ViewModels\Entities\EntityViewModel.cs" />
<Compile Include="ViewModels\Entities\FloatingObjectViewModel.cs" />
<Compile Include="ViewModels\Entities\GridViewModel.cs" />
<Compile Include="ViewModels\ILazyLoad.cs" />
<Compile Include="ViewModels\PluginManagerViewModel.cs" />
<Compile Include="ViewModels\PluginViewModel.cs" />
<Compile Include="ViewModels\Entities\VoxelMapViewModel.cs" />
<Compile Include="ViewModels\SteamUserViewModel.cs" />
<Compile Include="Views\AddWorkshopItemsDialog.xaml.cs">
<DependentUpon>AddWorkshopItemsDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Converters\InverseBooleanConverter.cs" />
<Compile Include="Views\Converters\Vector3DConverter.cs" />
<Compile Include="Views\Entities\Blocks\BlockView.xaml.cs">
<DependentUpon>BlockView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Entities\Blocks\PropertyView.xaml.cs">
<DependentUpon>PropertyView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ChatControl.xaml.cs">
<DependentUpon>ChatControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ConfigControl.xaml.cs">
<DependentUpon>ConfigControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\EntitiesControl.xaml.cs">
<DependentUpon>EntitiesControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Converters\StringBuilderConverter.cs" />
<Compile Include="Views\Converters\StringIdConverter.cs" />
<Compile Include="Views\Entities\GridView.xaml.cs">
<DependentUpon>GridView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Entities\VoxelMapView.xaml.cs">
<DependentUpon>VoxelMapView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ModsControl.xaml.cs">
<DependentUpon>ModsControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PluginsControl.xaml.cs">
<DependentUpon>PluginsControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SessionSettingsView.xaml.cs">
<DependentUpon>SessionSettingsView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\TorchUI.xaml.cs">
<DependentUpon>TorchUI.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PlayerListControl.xaml.cs">
<DependentUpon>PlayerListControl.xaml</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="TorchServer.cs" />
<Compile Include="Views\ValidationRules\NumberValidationRule.cs" />
<Compile Include="Views\WorldGeneratorDialog.xaml.cs">
<DependentUpon>WorldGeneratorDialog.xaml</DependentUpon>
</Compile>
<Compile Remove="ServerManager.cs" />
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
<Compile Remove="Views\WorldSelectControl.xaml.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Torch</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="Themes\Dark Theme Animated.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Dark Theme.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Light Theme Animated.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Light Theme.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Entities\EntityControlHost.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Entities\EntityControlsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\AddWorkshopItemsDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Entities\Blocks\BlockView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Entities\Blocks\PropertyView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ChatControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ConfigControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\EntitiesControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Entities\CharacterView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\Entities\GridView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ModListControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\PluginBrowser.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\PluginDownloader.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\PluginsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Entities\VoxelMapView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ModsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Resources.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\RoleEditor.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SessionSettingsView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ThemeControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\TorchUI.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\PlayerListControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\WorldGeneratorDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
<ProjectReference Include="..\Torch\Torch.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="torchicon.ico" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
<Page Remove="Views\WorldSelectControl.xaml" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
<PropertyGroup>
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)" &amp; copy "$(SolutionDir)NLog-user.config" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<Target Name="CopyLoggingConfig" AfterTargets="Build">
<Copy SourceFiles="$(SolutionDir)NLog.config" DestinationFolder="$(TargetDir)" />
</Target>
</Project>

View File

@@ -41,6 +41,7 @@ namespace Torch.Server
private bool _enableAsserts = false;
private int _fontSize = 16;
private UGCServiceType _ugcServiceType = UGCServiceType.Steam;
private bool _entityManagerEnabled = true;
/// <inheritdoc />
@@ -162,6 +163,14 @@ namespace Torch.Server
[Display(Name = "Enable Asserts", Description = "Enable Keen's assert logging.", GroupName = "Server")]
public bool EnableAsserts { get => _enableAsserts; set => Set(value, ref _enableAsserts); }
[Display(Name = "Enable Entity Manager", Description = "Enable Entity Manager tab. (can affect performance)",
GroupName = "Server")]
public bool EntityManagerEnabled
{
get => _entityManagerEnabled;
set => Set(value, ref _entityManagerEnabled);
}
public event PropertyChangedEventHandler PropertyChanged;
public TorchConfig() { }

View File

@@ -3,15 +3,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Diagnostics.Runtime;
using NLog;
using Sandbox;
using Sandbox.Engine.Networking;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.World;
using Torch.API;
@@ -21,15 +20,11 @@ using Torch.Commands;
using Torch.Managers.PatchManager;
using Torch.Mod;
using Torch.Mod.Messages;
using Torch.Patches;
using Torch.Server.Commands;
using Torch.Server.Managers;
using Torch.Utils;
using VRage;
using VRage.Dedicated;
using VRage.Dedicated.RemoteAPI;
using VRage.GameServices;
using VRage.Scripting;
using VRage.Steam;
using Timer = System.Threading.Timer;
#endregion
@@ -62,7 +57,8 @@ namespace Torch.Server
{
DedicatedInstance = new InstanceManager(this);
AddManager(DedicatedInstance);
AddManager(new EntityControlManager(this));
if (config.EntityManagerEnabled)
AddManager(new EntityControlManager(this));
AddManager(new RemoteAPIManager(this));
var sessionManager = Managers.GetManager<ITorchSessionManager>();
@@ -299,7 +295,7 @@ namespace Torch.Server
var totalSize = 0;
for (var i = 0; i < traces; i++)
{
string dump = DumpStack(thread).ToString();
string dump = DumpStack(thread);
totalSize += dump.Length;
stacks.Add(dump);
Thread.Sleep(pause);
@@ -322,28 +318,71 @@ namespace Torch.Server
return result.ToString();
}
private static StackTrace DumpStack(Thread thread)
private static string DumpStack(Thread thread)
{
try
{
thread.Suspend();
}
catch
{
// ignored
}
// Deprecated in .NET Core and later
// try
// {
// thread.Suspend();
// }
// catch
// {
// // ignored
// }
//
// var stack = new StackTrace(thread, true);
// try
// {
// thread.Resume();
// }
// catch
// {
// // ignored
// }
//
// return stack.ToString();
var stack = new StackTrace(thread, true);
try
// Modified from https://www.examplefiles.net/cs/579311
using (var target = DataTarget.CreateSnapshotAndAttach(Environment.ProcessId))
{
thread.Resume();
}
catch
{
// ignored
}
var runtime = target.ClrVersions[0].CreateRuntime();
return stack;
var clrThread = runtime.Threads.First(b => b.ManagedThreadId == thread.ManagedThreadId);
var sb = new StringBuilder();
sb.AppendFormat(
"ManagedThreadId: {0}, Name: {1}, OSThreadId: {2}, Thread: IsAlive: {3}, IsBackground: {4}, IsThreadPool: {5}",
thread.ManagedThreadId,
thread.Name,
clrThread.OSThreadId,
thread.IsAlive,
thread.IsBackground,
thread.IsThreadPoolThread)
.AppendLine();
sb.AppendLine("Stack trace:");
foreach (var frame in clrThread.EnumerateStackTrace())
{
sb.Append('\t');
switch (frame.Kind)
{
case ClrStackFrameKind.Unknown:
sb.AppendLine("[Unknown]");
break;
case ClrStackFrameKind.ManagedMethod:
sb.AppendLine(frame.Method?.Signature ?? "[Unable to get method signature]");
break;
case ClrStackFrameKind.Runtime:
sb.AppendLine("[CLR Runtime]");
break;
default:
throw new ArgumentOutOfRangeException(nameof(frame.Kind), frame.Kind, "Incorrect value in EnumerateStackTrace");
}
}
return sb.ToString();
}
}
#endregion

View File

@@ -1,4 +1,5 @@
using System;
#if TORCH_SERVICE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -51,3 +52,4 @@ namespace Torch.Server
}
}
}
#endif

View File

@@ -1,4 +1,5 @@
using System;
#if TORCH_SERVICE
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
@@ -17,21 +18,8 @@ namespace Torch.Server
public TorchServiceInstaller()
{
var serviceProcessInstaller = new ServiceProcessInstaller();
_serviceInstaller = new ServiceInstaller();
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
_serviceInstaller.DisplayName = "Torch (SEDS)";
_serviceInstaller.Description = "Service for Torch (SE Dedicated Server)";
_serviceInstaller.StartType = ServiceStartMode.Manual;
_serviceInstaller.ServiceName = TorchService.Name;
Installers.Add(serviceProcessInstaller);
Installers.Add(_serviceInstaller);
}
/// <inheritdoc />
@@ -59,3 +47,4 @@ namespace Torch.Server
}
}
}
#endif

View File

@@ -11,19 +11,17 @@ namespace Torch.Server.ViewModels
public class BlockLimitViewModel : ViewModel
{
private SessionSettingsViewModel _sessionSettings;
private string _blockType;
private short _limit;
public string BlockType { get => _blockType; set { _blockType = value; OnPropertyChanged(); } }
public short Limit { get => _limit; set { _limit = value; OnPropertyChanged(); } }
public string BlockType { get; set; }
public short Limit { get; set; }
//public CommandBinding Delete { get; } = new CommandBinding(new DeleteCommand());
public BlockLimitViewModel(SessionSettingsViewModel sessionSettings, string blockType, short limit)
{
_sessionSettings = sessionSettings;
_blockType = blockType;
_limit = limit;
BlockType = blockType;
Limit = limit;
}
/* TODO: figure out how WPF commands work

View File

@@ -15,7 +15,7 @@ namespace Torch.Server.ViewModels
{
public class CheckpointViewModel : ViewModel
{
private MyObjectBuilder_Checkpoint _checkpoint;
private readonly MyObjectBuilder_Checkpoint _checkpoint;
//private SessionSettingsViewModel _sessionSettings;
public CheckpointViewModel(MyObjectBuilder_Checkpoint checkpoint)

View File

@@ -1,17 +1,14 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog;
using Sandbox.Engine.Utils;
using Torch.Collections;
using Torch.Server.Managers;
using Torch.Utils;
using VRage.Game;
using VRage.Game.ModAPI;
using Torch.Utils.SteamWorkshopTools;
using Torch.Collections;
using VRage.GameServices;
namespace Torch.Server.ViewModels
{
@@ -76,42 +73,30 @@ namespace Torch.Server.ViewModels
}
}
public async Task UpdateAllModInfosAsync(Action<string> messageHandler = null)
public async Task UpdateAllModInfosAsync()
{
if (Mods.Count() == 0)
/*if (!Mods.Any())
return;
var ids = Mods.Select(m => m.PublishedFileId);
var workshopService = WebAPI.Instance;
Dictionary<ulong, PublishedItemDetails> modInfos = null;
List<MyWorkshopItem> modInfos;
try
{
modInfos = (await workshopService.GetPublishedFileDetails(ids.ToArray()));
modInfos = await WorkshopQueryUtils.GetModsInfo(Mods.Select(b =>
new MyObjectBuilder_Checkpoint.ModItem(b.PublishedFileId, b.UgcService, b.IsDependency)));
}
catch (Exception e)
{
Log.Error(e.Message);
Log.Error(e);
return;
}
Log.Info($"Mods Info successfully retrieved!");
Log.Info("Mods Info successfully retrieved!");
foreach (var mod in Mods)
foreach (var modItem in Mods
.Select(b => new MyObjectBuilder_Checkpoint.ModItem(b.PublishedFileId, b.UgcService))
.Except(modInfos.Select(b => new MyObjectBuilder_Checkpoint.ModItem(b.Id, b.ServiceName))))
{
if (!modInfos.ContainsKey(mod.PublishedFileId) || modInfos[mod.PublishedFileId] == null)
{
Log.Error($"Failed to retrieve info for mod with workshop id '{mod.PublishedFileId}'!");
}
//else if (!modInfo.Tags.Contains(""))
else
{
mod.FriendlyName = modInfos[mod.PublishedFileId].Title;
mod.Description = modInfos[mod.PublishedFileId].Description;
//mod.Name = modInfos[mod.PublishedFileId].FileName;
}
}
Log.Error($"Unable to retreive info about {modItem.PublishedFileId}:{modItem.PublishedServiceName}");
}*/
}
public List<string> Administrators { get => _config.Administrators; set => SetValue(x => _config.Administrators = x, value); }

View File

@@ -25,7 +25,9 @@ namespace Torch.Server.ViewModels.Blocks
get => Block?.CustomName ?? "null";
set
{
#pragma warning disable CS0618
TorchBase.Instance.Invoke(() =>
#pragma warning restore CS0618
{
Block.CustomName = value;
OnPropertyChanged();
@@ -41,7 +43,9 @@ namespace Torch.Server.ViewModels.Blocks
get => ((MySlimBlock)Block?.SlimBlock)?.BuiltBy ?? 0;
set
{
#pragma warning disable CS0618
TorchBase.Instance.Invoke(() =>
#pragma warning restore CS0618
{
((MySlimBlock)Block.SlimBlock).TransferAuthorship(value);
OnPropertyChanged();

View File

@@ -3,18 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using NLog;
using Sandbox.Game.Entities.Cube;
using Sandbox.ModAPI;
using Sandbox.ModAPI.Interfaces;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using NLog;
using Sandbox.ModAPI.Interfaces.Terminal;
namespace Torch.Server.ViewModels.Blocks
namespace Torch.Server.ViewModels.Entities.Blocks
{
public static class BlockViewModelGenerator
{
@@ -27,8 +21,8 @@ namespace Torch.Server.ViewModels.Blocks
static BlockViewModelGenerator()
{
_asmName = new AssemblyName("Torch.Server.ViewModels.Generated");
_ab = AppDomain.CurrentDomain.DefineDynamicAssembly(_asmName, AssemblyBuilderAccess.RunAndSave);
_mb = _ab.DefineDynamicModule(_asmName.Name);
_ab = AssemblyBuilder.DefineDynamicAssembly(_asmName, AssemblyBuilderAccess.RunAndCollect);
_mb = _ab.DefineDynamicModule(_asmName.Name ?? "Torch.Server.ViewModels.Generated");
}
public static void GenerateModels()
@@ -40,7 +34,6 @@ namespace Torch.Server.ViewModels.Blocks
GenerateModel(type);
}
}
_ab.Save("Generated.dll", PortableExecutableKinds.ILOnly, ImageFileMachine.AMD64);
}
public static Type GenerateModel(Type blockType, bool force = false)

View File

@@ -19,7 +19,9 @@ namespace Torch.Server.ViewModels.Blocks
get => _prop.GetValue(Block.Block);
set
{
#pragma warning disable CS0618
TorchBase.Instance.Invoke(() =>
#pragma warning restore CS0618
{
_prop.SetValue(Block.Block, value);
OnPropertyChanged();

View File

@@ -18,21 +18,9 @@ namespace Torch.Server.ViewModels.Entities
OnPropertyChanged(SignalPropertyInvalidateControl);
}
private bool _hide;
/// <summary>
/// Should this element be forced into the <see cref="Visibility.Collapsed"/>
/// </summary>
public bool Hide
{
get => _hide;
protected set
{
if (_hide == value)
return;
_hide = value;
OnPropertyChanged();
}
}
public bool Hide { get; set; }
}
}

View File

@@ -20,7 +20,7 @@ namespace Torch.Server.ViewModels.Entities
{
protected EntityTreeViewModel Tree { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
private static Logger _log = LogManager.GetCurrentClassLogger();
private IMyEntity _backing;
public IMyEntity Entity
@@ -30,7 +30,9 @@ namespace Torch.Server.ViewModels.Entities
{
_backing = value;
OnPropertyChanged();
#pragma warning disable CS0618
EntityControls = TorchBase.Instance?.Managers.GetManager<EntityControlManager>()?.BoundModels(this);
#pragma warning restore CS0618
// ReSharper disable once ExplicitCallerInfoArgument
OnPropertyChanged(nameof(EntityControls));
}
@@ -46,7 +48,9 @@ namespace Torch.Server.ViewModels.Entities
set
{
if (Entity!=null)
#pragma warning disable CS0618
TorchBase.Instance.InvokeBlocking(() => Entity.DisplayName = value);
#pragma warning restore CS0618
OnPropertyChanged();
}
}
@@ -54,7 +58,7 @@ namespace Torch.Server.ViewModels.Entities
private string _descriptiveName;
public string DescriptiveName
{
get => _descriptiveName ?? (_descriptiveName = GetSortedName(EntityTreeViewModel.SortEnum.Name));
get => _descriptiveName ??= GetSortedName(EntityTreeViewModel.SortEnum.Name);
set => _descriptiveName = value;
}
@@ -140,7 +144,9 @@ namespace Torch.Server.ViewModels.Entities
return;
if (Entity != null)
#pragma warning disable CS0618
TorchBase.Instance.InvokeBlocking(() => Entity.SetPosition(v));
#pragma warning restore CS0618
OnPropertyChanged();
}
}
@@ -176,7 +182,7 @@ namespace Torch.Server.ViewModels.Entities
public int Compare(EntityViewModel x, EntityViewModel y)
{
return x.CompareToSort(y, _sort);
return x?.CompareToSort(y, _sort) ?? default;
}
}
}

View File

@@ -101,7 +101,9 @@ namespace Torch.Server.ViewModels.Entities
return;
_load = true;
#pragma warning disable CS0618
TorchBase.Instance.Invoke(() =>
#pragma warning restore CS0618
{
Blocks.Clear();
foreach (var block in Grid.GetFatBlocks().OfType<MyTerminalBlock>())

View File

@@ -18,12 +18,12 @@ namespace Torch.Server.ViewModels.Entities
public MtObservableList<GridViewModel> AttachedGrids { get; } = new MtObservableList<GridViewModel>();
public async Task UpdateAttachedGrids()
public Task UpdateAttachedGrids()
{
return Task.CompletedTask;
//TODO: fix
return;
AttachedGrids.Clear();
/*AttachedGrids.Clear();
var box = Entity.WorldAABB;
var entities = new List<MyEntity>();
await TorchBase.Instance.InvokeAsync(() => MyEntities.GetTopMostEntitiesInBox(ref box, entities)).ConfigureAwait(false);
@@ -36,7 +36,7 @@ namespace Torch.Server.ViewModels.Entities
}
AttachedGrids.Add(gridModel);
}
}*/
}
public VoxelMapViewModel(MyVoxelBase e, EntityTreeViewModel tree) : base(e, tree)

View File

@@ -41,21 +41,11 @@ namespace Torch.Server.ViewModels
public SortedView<EntityViewModel> SortedFloatingObjects { get; }
public SortedView<VoxelMapViewModel> SortedVoxelMaps { get; }
private EntityViewModel _currentEntity;
private SortEnum _currentSort;
private UserControl _control;
public EntityViewModel CurrentEntity
{
get => _currentEntity;
set { _currentEntity = value; OnPropertyChanged(nameof(CurrentEntity)); }
}
public EntityViewModel CurrentEntity { get; set; }
public SortEnum CurrentSort
{
get => _currentSort;
set => SetValue(ref _currentSort, value);
}
public SortEnum CurrentSort { get; set; }
// I hate you today WPF
public EntityTreeViewModel() : this(null)
@@ -65,7 +55,7 @@ namespace Torch.Server.ViewModels
public EntityTreeViewModel(UserControl control)
{
_control = control;
var comparer = new EntityViewModel.Comparer(_currentSort);
var comparer = new EntityViewModel.Comparer(CurrentSort);
SortedGrids = new SortedView<GridViewModel>(Grids.Values, comparer);
SortedCharacters = new SortedView<CharacterViewModel>(Characters.Values, comparer);
SortedFloatingObjects = new SortedView<EntityViewModel>(FloatingObjects.Values, comparer);

View File

@@ -1,17 +1,9 @@
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Runtime.CompilerServices;
using NLog;
using Sandbox.Engine.Networking;
using VRage.Game;
using Torch.Server.Annotations;
using Torch.Utils;
using Torch.Utils.SteamWorkshopTools;
using VRage.GameServices;
namespace Torch.Server.ViewModels
{
@@ -30,10 +22,8 @@ namespace Torch.Server.ViewModels
/// </summary>
public string FriendlyName
{
get { return _modItem.FriendlyName; }
set {
SetValue(ref _modItem.FriendlyName, value);
}
get => _modItem.FriendlyName;
set => SetValue(ref _modItem.FriendlyName, value);
}
/// <summary>
@@ -41,11 +31,8 @@ namespace Torch.Server.ViewModels
/// </summary>
public ulong PublishedFileId
{
get { return _modItem.PublishedFileId; }
set
{
SetValue(ref _modItem.PublishedFileId, value);
}
get => _modItem.PublishedFileId;
set => SetValue(ref _modItem.PublishedFileId, value);
}
/// <summary>
@@ -53,11 +40,8 @@ namespace Torch.Server.ViewModels
/// </summary>
public string Name
{
get { return _modItem.Name; }
set
{
SetValue(ref _modItem.FriendlyName, value);
}
get => _modItem.Name;
set => SetValue(ref _modItem.FriendlyName, value);
}
/// <summary>
@@ -66,11 +50,8 @@ namespace Torch.Server.ViewModels
/// </summary>
public bool IsDependency
{
get { return _modItem.IsDependency; }
set
{
SetValue(ref _modItem.IsDependency, value);
}
get => _modItem.IsDependency;
set => SetValue(ref _modItem.IsDependency, value);
}
private string _description;
@@ -79,20 +60,14 @@ namespace Torch.Server.ViewModels
/// </summary>
public string Description
{
get { return _description; }
set
{
SetValue(ref _description, value);
}
get => _description;
set => SetValue(ref _description, value);
}
public string UgcService
{
get { return _modItem.PublishedServiceName; }
set
{
SetValue(ref _modItem.PublishedServiceName, value);
}
get => _modItem.PublishedServiceName;
set => SetValue(ref _modItem.PublishedServiceName, value);
}
/// <summary>
@@ -112,34 +87,24 @@ namespace Torch.Server.ViewModels
/// <returns></returns>
public async Task<bool> UpdateModInfoAsync()
{
if (UgcService.ToLower() == "mod.io")
/*if (UgcService.ToLower() == "mod.io")
return true;
var msg = "";
var workshopService = WebAPI.Instance;
PublishedItemDetails modInfo = null;
MyWorkshopItem modInfo;
try
{
modInfo = (await workshopService.GetPublishedFileDetails(new ulong[] { PublishedFileId }))?[PublishedFileId];
modInfo = await WorkshopQueryUtils.GetModInfo(_modItem);
}
catch( Exception e )
{
Log.Error(e.Message);
}
if (modInfo == null)
{
Log.Error($"Failed to retrieve mod with workshop id '{PublishedFileId}'!");
Log.Error(e);
return false;
}
//else if (!modInfo.Tags.Contains(""))
else
{
Log.Info($"Mod Info successfully retrieved!");
FriendlyName = modInfo.Title;
Description = modInfo.Description;
//Name = modInfo.FileName;
return true;
}
Log.Info("Mod Info successfully retrieved!");
FriendlyName = modInfo.Title;
Description = modInfo.Description;*/
return true;
}
public override string ToString()

View File

@@ -13,13 +13,7 @@ namespace Torch.Server.ViewModels
public class PluginManagerViewModel : ViewModel
{
public MtObservableList<PluginViewModel> Plugins { get; } = new MtObservableList<PluginViewModel>();
private PluginViewModel _selectedPlugin;
public PluginViewModel SelectedPlugin
{
get => _selectedPlugin;
set { _selectedPlugin = value; OnPropertyChanged(nameof(SelectedPlugin)); }
}
public PluginViewModel SelectedPlugin { get; set; }
public PluginManagerViewModel() { }

View File

@@ -72,7 +72,7 @@ namespace Torch.Server.ViewModels
case PluginState.Enabled:
return Brushes.Transparent;
default:
throw new ArgumentOutOfRangeException();
throw new InvalidOperationException();
}
}
}

View File

@@ -80,11 +80,16 @@ namespace Torch.Server.Views
private void _instanceManager_InstanceLoaded(ConfigDedicatedViewModel obj)
{
Log.Info("Instance loaded.");
Dispatcher.Invoke(() => {
DataContext = obj?.Mods ?? new MtObservableList<ModItemInfo>();
UpdateLayout();
((MtObservableList<ModItemInfo>)DataContext).CollectionChanged += OnModlistUpdate;
if (obj is { })
Task.Run(async () =>
{
await obj.UpdateAllModInfosAsync();
Log.Info("Instance loaded.");
});
});
}
@@ -281,14 +286,11 @@ namespace Torch.Server.Views
foreach (var mod in modList)
_instanceManager.DedicatedConfig.Mods.Add(mod);
if (tasks.Any())
Task.WaitAll(tasks.ToArray());
Dispatcher.Invoke(() =>
{
_instanceManager.DedicatedConfig.Save();
});
Task.Run(async () =>
{
await Task.WhenAll(tasks);
_instanceManager.DedicatedConfig.Save();
});
}
private void UgcServiceTypeBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)

View File

@@ -3,109 +3,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Markdown.Xaml;assembly=Markdown.Xaml"
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:views="clr-namespace:Torch.Server.Views"
mc:Ignorable="d"
Title="PluginBrowser" Height="557.5" Width="1161"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<Style TargetType="FlowDocument" x:Key="DocumentStyle">
<Setter Property="FontFamily"
Value="Calibri" />
<Setter Property="TextAlignment"
Value="Left" />
</Style>
<Style x:Key="H1Style"
TargetType="Paragraph">
<Setter Property="FontSize"
Value="42" />
<Setter Property="Foreground"
Value="#ff000000" />
<Setter Property="FontWeight"
Value="Light" />
</Style>
<Style x:Key="H2Style"
TargetType="Paragraph">
<Setter Property="FontSize"
Value="20" />
<Setter Property="Foreground"
Value="#ff000000" />
<Setter Property="FontWeight"
Value="Light" />
</Style>
<Style x:Key="H3Style"
TargetType="Paragraph">
<Setter Property="FontSize"
Value="20" />
<Setter Property="Foreground"
Value="#99000000" />
<Setter Property="FontWeight"
Value="Light" />
</Style>
<Style x:Key="H4Style"
TargetType="Paragraph">
<Setter Property="FontSize"
Value="14" />
<Setter Property="Foreground"
Value="#99000000" />
<Setter Property="FontWeight"
Value="Light" />
</Style>
<Style x:Key="LinkStyle"
TargetType="Hyperlink">
<Setter Property="TextDecorations"
Value="None" />
</Style>
<Style x:Key="ImageStyle"
TargetType="Image">
<Setter Property="RenderOptions.BitmapScalingMode"
Value="NearestNeighbor" />
<Style.Triggers>
<Trigger Property="Tag"
Value="imageright">
<Setter Property="Margin"
Value="20,0,0,0" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="SeparatorStyle"
TargetType="Line">
<Setter Property="X2"
Value="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=FlowDocumentScrollViewer}}" />
<Setter Property="Stroke"
Value="#99000000" />
<Setter Property="StrokeThickness"
Value="2" />
</Style>
<local:Markdown x:Key="Markdown"
DocumentStyle="{StaticResource DocumentStyle}"
Heading1Style="{StaticResource H1Style}"
Heading2Style="{StaticResource H2Style}"
Heading3Style="{StaticResource H3Style}"
Heading4Style="{StaticResource H4Style}"
LinkStyle="{StaticResource LinkStyle}"
ImageStyle="{StaticResource ImageStyle}"
SeparatorStyle="{StaticResource SeparatorStyle}"
AssetPathRoot="{x:Static system:Environment.CurrentDirectory}"/>
<local:TextToFlowDocumentConverter x:Key="TextToFlowDocumentConverter"
Markdown="{StaticResource Markdown}"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" MinWidth="293"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
@@ -115,7 +23,7 @@ Markdown="{StaticResource Markdown}"/>
<ListView Name="PluginsList" Height="Auto" Margin="3,32,3,3" ItemsSource="{Binding Plugins}" SelectionChanged="PluginsList_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Width="220" Header="Name">
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="5, 0" Text="{Binding Name}"/>
@@ -132,11 +40,18 @@ Markdown="{StaticResource Markdown}"/>
</GridView>
</ListView.View>
</ListView>
<Button Name="DownloadButton" Grid.Row ="1" Content="Install" Margin="0,3,3,3" Height="30" Click="DownloadButton_OnClick" IsEnabled="False" HorizontalAlignment="Right" Width="144"/>
<Button Name="UninstallButton" Grid.Row ="1" Content="Uninstall" Margin="3,3,0,3" Height="30" Click="UninstallButton_OnClick" IsEnabled="False" HorizontalAlignment="Left" Width="144"/>
<TextBox x:Name="txtPluginsSearch" Height="23" Margin="3,4,3,0" TextWrapping="Wrap" Text="Plugins search..." VerticalAlignment="Top" GotFocus="TxtPluginsSearch_GotFocus" LostFocus="TxtPluginsSearch_LostFocus" Foreground="Gray" TextChanged="TxtPluginsSearch_TextChanged"/>
<Grid Grid.Row="1" Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Button Name="DownloadButton" Content="Install" Height="30" Margin="3" Click="DownloadButton_OnClick" IsEnabled="False"/>
<Button Grid.Column="1" Name="UninstallButton" Content="Uninstall" Height="30" Margin="3" Click="UninstallButton_OnClick" IsEnabled="False" />
</Grid>
<TextBox Grid.Row="0" x:Name="TxtPluginsSearch" Height="23" Margin="3,4,3,0" TextWrapping="Wrap" Text="Plugins search..." VerticalAlignment="Top" GotFocus="TxtPluginsSearch_GotFocus" LostFocus="TxtPluginsSearch_LostFocus" Foreground="Gray" TextChanged="TxtPluginsSearch_TextChanged"/>
</Grid>
<FlowDocumentScrollViewer Name="MarkdownFlow" VerticalAlignment="Stretch" Margin="0,3,3,3" Document="{Binding CurrentDescription, Converter={StaticResource TextToFlowDocumentConverter}}" Grid.Column="1"/>
<!-- <FlowDocumentScrollViewer Name="MarkdownFlow" VerticalAlignment="Stretch" Margin="0,3,3,3" Document="{Binding CurrentDescription, Converter={StaticResource TextToFlowDocumentConverter}}" Grid.Column="1"/> -->
<mdxam:MarkdownScrollViewer Name="MarkdownFlow" VerticalAlignment="Stretch" Margin="0,3,3,3" Markdown="{Binding CurrentDescription}" Grid.Column="1" />
</Grid>
</Window>

View File

@@ -31,13 +31,13 @@ namespace Torch.Server.Views
/// </summary>
public partial class PluginBrowser : Window, INotifyPropertyChanged
{
private static Logger Log = LogManager.GetCurrentClassLogger();
private static Logger _log = LogManager.GetCurrentClassLogger();
public MtObservableList<PluginItem> PluginsSource { get; set; } = new MtObservableList<PluginItem>();
public MtObservableList<PluginItem> Plugins { get; set; } = new MtObservableList<PluginItem>();
public PluginItem CurrentItem { get; set; }
public const string PLUGINS_SEARCH_TEXT = "Plugins search...";
private string PreviousSearchQuery = "";
public const string PluginsSearchText = "Plugins search...";
private string _previousSearchQuery = "";
private string _description = "Loading data from server, please wait..";
private static object _syncLock = new object();
@@ -56,24 +56,35 @@ namespace Torch.Server.Views
InitializeComponent();
var installedPlugins = pluginManager.Plugins;
BindingOperations.EnableCollectionSynchronization(Plugins,_syncLock);
BindingOperations.EnableCollectionSynchronization(Plugins, _syncLock);
Task.Run(async () =>
{
var res = await PluginQuery.Instance.QueryAll();
if (res == null)
return;
foreach (var item in res.Plugins.OrderBy(i => i.Name)) {
lock (_syncLock)
{
if (installedPlugins.Keys.Contains(Guid.Parse(item.ID)))
item.Installed = true;
Plugins.Add(item);
PluginsList.Dispatcher.Invoke(() => PluginsList.SelectedIndex = 0);
PluginsSource.Add(item);
}
}
CurrentDescription = "Please select a plugin...";
});
{
try
{
var res = await PluginQuery.Instance.QueryAll();
foreach (var item in res.Plugins.OrderBy(i => i.Name)) {
lock (_syncLock)
{
var pluginItem = item with
{
Description = item.Description.Replace("&lt;", "<").Replace("&gt;", ">"),
Installed = installedPlugins.Keys.Contains(item.Id)
};
Plugins.Add(pluginItem);
PluginsSource.Add(pluginItem);
}
}
Dispatcher.Invoke(() => PluginsList.SelectedIndex = 0);
CurrentDescription = "Please select a plugin...";
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "An Error Occurred", MessageBoxButton.OK, MessageBoxImage.Error);
Close();
throw;
}
});
MarkdownFlow.CommandBindings.Add(new CommandBinding(NavigationCommands.GoToPage, (sender, e) => OpenUri((string)e.Parameter)));
}
@@ -108,36 +119,36 @@ namespace Torch.Server.Views
private void DownloadButton_OnClick(object sender, RoutedEventArgs e)
{
var SelectedItems = PluginsList.SelectedItems;
var selectedItems = PluginsList.SelectedItems;
foreach(PluginItem PluginItem in SelectedItems)
TorchBase.Instance.Config.Plugins.Add(new Guid(PluginItem.ID));
foreach(PluginItem pluginItem in selectedItems)
TorchBase.Instance.Config.Plugins.Add(pluginItem.Id);
TorchBase.Instance.Config.Save();
Log.Info($"Started to download {SelectedItems.Count} plugin(s)");
_log.Info($"Started to download {selectedItems.Count} plugin(s)");
PluginDownloader DownloadProgress = new PluginDownloader(SelectedItems);
DownloadProgress.Show();
PluginDownloader downloadProgress = new PluginDownloader(selectedItems);
downloadProgress.Show();
}
private void UninstallButton_OnClick(object sender, RoutedEventArgs e) {
var SelectedItems = PluginsList.SelectedItems;
if(SelectedItems.Cast<PluginItem>().Any(x => x.Installed == false)) {
var selectedItems = PluginsList.SelectedItems;
if(selectedItems.Cast<PluginItem>().Any(x => x.Installed == false)) {
MessageBox.Show($"Error! You have selected at least 1 plugin which isnt currently installed. Please de-select and try again!", "Uninstall Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var result = MessageBox.Show($"Are you sure you want to attempt uninstall of {SelectedItems.Count} plugin(s)?", "Uninstall Confirmation", MessageBoxButton.YesNo);
var result = MessageBox.Show($"Are you sure you want to attempt uninstall of {selectedItems.Count} plugin(s)?", "Uninstall Confirmation", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes) {
foreach(PluginItem PluginItem in SelectedItems) {
if(TorchBase.Instance.Config.Plugins.Contains(Guid.Parse(PluginItem.ID))) {
TorchBase.Instance.Config.Plugins.Remove(Guid.Parse(PluginItem.ID));
foreach(PluginItem pluginItem in selectedItems) {
if(TorchBase.Instance.Config.Plugins.Contains(pluginItem.Id)) {
TorchBase.Instance.Config.Plugins.Remove(pluginItem.Id);
string path = $"Plugins\\{PluginItem.Name}.zip";
string path = $"Plugins\\{pluginItem.Name}.zip";
if (File.Exists(path))
File.Delete(path);
Log.Info($"Uninstalled {PluginItem.Name}");
_log.Info($"Uninstalled {pluginItem.Name}");
}
}
MessageBox.Show($"Plugins removed... Please restart your server for changes to take effect.", "Uninstall Confirmation", MessageBoxButton.OK);
@@ -153,45 +164,45 @@ namespace Torch.Server.Views
}
private void TxtPluginsSearch_GotFocus(object sender, RoutedEventArgs e) {
if (txtPluginsSearch.Text == PLUGINS_SEARCH_TEXT) {
txtPluginsSearch.Clear();
txtPluginsSearch.Foreground = Brushes.Black;
if (TxtPluginsSearch.Text == PluginsSearchText) {
TxtPluginsSearch.Clear();
TxtPluginsSearch.Foreground = Brushes.Black;
return;
}
}
private void TxtPluginsSearch_LostFocus(object sender, RoutedEventArgs e) {
if(txtPluginsSearch.Text == "") {
txtPluginsSearch.Foreground = Brushes.Gray;
txtPluginsSearch.Text = PLUGINS_SEARCH_TEXT;
if(TxtPluginsSearch.Text == "") {
TxtPluginsSearch.Foreground = Brushes.Gray;
TxtPluginsSearch.Text = PluginsSearchText;
return;
}
}
private void TxtPluginsSearch_TextChanged(object sender, TextChangedEventArgs e) {
string SearchQueryString = txtPluginsSearch.Text;
string searchQueryString = TxtPluginsSearch.Text;
if(SearchQueryString.Length < PreviousSearchQuery.Length) {
if(searchQueryString.Length < _previousSearchQuery.Length) {
ResetSearchFilter();
}
if (SearchQueryString != PLUGINS_SEARCH_TEXT && SearchQueryString != string.Empty) {
SearchPlugins(SearchQueryString);
if (searchQueryString != PluginsSearchText && searchQueryString != string.Empty) {
SearchPlugins(searchQueryString);
} else {
ResetSearchFilter();
}
PreviousSearchQuery = SearchQueryString;
_previousSearchQuery = searchQueryString;
}
private void SearchPlugins(string SearchQueryString) {
foreach (var plugin in Plugins.Where(p => !p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) &&
!p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) {
private void SearchPlugins(string searchQueryString) {
foreach (var plugin in Plugins.Where(p => !p.Name.Contains(searchQueryString, StringComparison.OrdinalIgnoreCase) &&
!p.Author.Contains(searchQueryString, StringComparison.OrdinalIgnoreCase))) {
Plugins.Remove(plugin);
}
foreach (var plugin in Plugins.Where(p => p.Name.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase) ||
p.Author.Contains(SearchQueryString, StringComparison.OrdinalIgnoreCase))) {
foreach (var plugin in Plugins.Where(p => p.Name.Contains(searchQueryString, StringComparison.OrdinalIgnoreCase) ||
p.Author.Contains(searchQueryString, StringComparison.OrdinalIgnoreCase))) {
if (!Plugins.Contains(plugin))
Plugins.Add(plugin);
}

View File

@@ -50,7 +50,7 @@ namespace Torch.Server.Views
var PercentChangeOnDownload = 100 / PluginsToDownload.Count;
foreach (PluginItem PluginItem in PluginsToDownload) {
if (!Task.Run(async () => await PluginQuery.Instance.DownloadPlugin(PluginItem.ID)).Result) {
if (!Task.Run(async () => await PluginQuery.Instance.DownloadPlugin(PluginItem.Id)).Result) {
failedDownloads++;
DownloadProgress += PercentChangeOnDownload;
(sender as BackgroundWorker).ReportProgress(DownloadProgress);

View File

@@ -81,25 +81,22 @@ namespace Torch.Server.Views
public class DictionaryItem<TKey, TValue> : ViewModel, IDictionaryItem
{
private TKey _key;
private TValue _value;
object IDictionaryItem.Key { get; set; }
object IDictionaryItem.Value { get; set; }
object IDictionaryItem.Key { get => _key; set => SetValue(ref _key, (TKey)value); }
object IDictionaryItem.Value { get => _value; set => SetValue(ref _value, (TValue)value); }
public TKey Key { get => _key; set => SetValue(ref _key, value); }
public TValue Value { get => _value; set => SetValue(ref _value, value); }
public TKey Key { get; set; }
public TValue Value { get; set; }
public DictionaryItem()
{
_key = default(TKey);
_value = default(TValue);
Key = default(TKey);
Value = default(TValue);
}
public DictionaryItem(TKey key, TValue value)
{
_key = key;
_value = value;
Key = key;
Value = value;
}
}

View File

@@ -93,8 +93,7 @@
<local:PlayerListControl Grid.Column="1" x:Name="PlayerList" DockPanel.Dock="Right"/>
</Grid>
</TabItem>
<TabItem Header="Entity Manager">
<views:EntitiesControl />
<TabItem Header="Entity Manager" x:Name="EntityManagerTab">
</TabItem>
<TabItem Header="Plugins">
<views:PluginsControl x:Name="Plugins" />

View File

@@ -20,6 +20,7 @@ using Sandbox;
using Torch.API;
using Torch.API.Managers;
using Torch.Server.Managers;
using Torch.Server.Views;
using MessageBoxResult = System.Windows.MessageBoxResult;
namespace Torch.Server
@@ -137,7 +138,11 @@ namespace Torch.Server
_config = config;
Dispatcher.Invoke(() =>
{
//InstancePathBox.Text = config.InstancePath;
EntityManagerTab.IsEnabled = _config.EntityManagerEnabled;
if (_config.EntityManagerEnabled)
{
EntityManagerTab.Content = new EntitiesControl();
}
});
}

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ControlzEx" version="3.0.2.4" targetFramework="net461" requireReinstallation="true" />
<package id="MahApps.Metro" version="1.6.1" targetFramework="net461" />
<package id="Markdown.Xaml" version="1.0.0" targetFramework="net461" />
<package id="Microsoft.Win32.Registry" version="4.4.0" targetFramework="net461" />
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
<package id="protobuf-net" version="2.4.0" targetFramework="net461" />
<package id="SteamKit2" version="2.1.0" targetFramework="net461" />
<package id="System.ComponentModel.Annotations" version="4.5.0" targetFramework="net461" />
<package id="System.Security.AccessControl" version="4.4.0" targetFramework="net461" />
<package id="System.Security.Principal.Windows" version="4.4.0" targetFramework="net461" />
</packages>

View File

@@ -1,98 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch.Tests</RootNamespace>
<AssemblyName>Torch.Tests</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFramework>net6-windows</TargetFramework>
<NoWarn>1591,0649</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin-test\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<AssemblyTitle>Torch Tests</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin-test\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<OutputPath>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\</OutputPath>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(SolutionDir)\bin-test\x64\Release\Torch.Tests.xml</DocumentationFile>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration) == 'Release'">
<DocumentationFile>$(SolutionDir)\bin-test\$(Platform)\$(Configuration)\Torch.Tests.xml</DocumentationFile>
</PropertyGroup>
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="xunit" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
</Reference>
<Reference Include="xunit.assert, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll</HintPath>
</Reference>
<Reference Include="xunit.core, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll</HintPath>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll</HintPath>
</Reference>
</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</Link>
</Compile>
<Compile Include="PatchTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionTestManager.cs" />
<Compile Include="ReflectionSystemTest.cs" />
<Compile Include="TestUtils.cs" />
<Compile Include="TorchReflectionTest.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
</ProjectReference>
<ProjectReference Include="..\Torch\Torch.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Torch</Name>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
<ProjectReference Include="..\Torch\Torch.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
</Project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.TextTransform" version="1.0.0" targetFramework="net461" />
<package id="NLog" version="4.4.12" targetFramework="net461" />
<package id="xunit" version="2.2.0" targetFramework="net461" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net461" />
<package id="xunit.assert" version="2.2.0" targetFramework="net461" />
<package id="xunit.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.core" version="2.2.0" targetFramework="net461" />
<package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net461" />
<package id="xunit.runner.console" version="2.2.0" targetFramework="net461" developmentDependency="true" />
</packages>

View File

@@ -7,22 +7,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch", "Torch\Torch.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.API", "Torch.API\Torch.API.csproj", "{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Client", "Torch.Client\Torch.Client.csproj", "{E36DF745-260B-4956-A2E8-09F08B2E7161}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server", "Torch.Server\Torch.Server.csproj", "{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7AD02A71-1D4C-48F9-A8C1-789A5512424F}"
ProjectSection(SolutionItems) = preProject
NLog.config = NLog.config
NLog-user.config = NLog-user.config
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Tests", "Torch.Tests\Torch.Tests.csproj", "{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Server.Tests", "Torch.Server.Tests\Torch.Server.Tests.csproj", "{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Torch.Client.Tests", "Torch.Client.Tests\Torch.Client.Tests.csproj", "{632E78C0-0DAC-4B71-B411-2F1B333CC310}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Versioning", "Versioning", "{762F6A0D-55EF-4173-8CDE-309D183F40C4}"
ProjectSection(SolutionItems) = preProject
Versioning\AssemblyVersion.cs = Versioning\AssemblyVersion.cs
@@ -37,49 +32,22 @@ Global
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|Any CPU.ActiveCfg = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.ActiveCfg = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|x64.Build.0 = Debug|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|Any CPU.ActiveCfg = Release|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.ActiveCfg = Release|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|x64.Build.0 = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|Any CPU.ActiveCfg = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.ActiveCfg = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|x64.Build.0 = Debug|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|Any CPU.ActiveCfg = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.ActiveCfg = Release|x64
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|x64.Build.0 = Release|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|Any CPU.ActiveCfg = Debug|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Debug|x64.ActiveCfg = Debug|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|Any CPU.ActiveCfg = Release|x64
{E36DF745-260B-4956-A2E8-09F08B2E7161}.Release|x64.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|Any CPU.ActiveCfg = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.ActiveCfg = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|x64.Build.0 = Debug|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.Build.0 = Release|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|Any CPU.ActiveCfg = Debug|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|x64.ActiveCfg = Debug|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|x64.Build.0 = Debug|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|Any CPU.ActiveCfg = Release|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|x64.ActiveCfg = Release|x64
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|x64.Build.0 = Release|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|Any CPU.ActiveCfg = Debug|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|x64.ActiveCfg = Debug|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|x64.Build.0 = Debug|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|Any CPU.ActiveCfg = Release|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|x64.ActiveCfg = Release|x64
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|x64.Build.0 = Release|x64
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Debug|Any CPU.ActiveCfg = Debug|x64
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Debug|x64.ActiveCfg = Debug|x64
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Release|Any CPU.ActiveCfg = Release|x64
{632E78C0-0DAC-4B71-B411-2F1B333CC310}.Release|x64.ActiveCfg = Release|x64
{7E01635C-3B67-472E-BCD6-C5539564F214}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E01635C-3B67-472E-BCD6-C5539564F214}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FBA5D932-6254-4A1E-BAF4-E229FA94E3C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EFD1D91-2FA2-47ED-B537-D8BC3B0E543E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3C8B671-6AD1-44AA-A8DA-E0C0DC0FEDF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -8,6 +8,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PropertyChanged;
using Torch.Utils;
namespace Torch.Collections
@@ -112,6 +113,7 @@ namespace Torch.Collections
_flushEventQueue?.Change(_eventRaiseDelay, -1);
}
[SuppressPropertyChangedWarnings]
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!NotificationsEnabled)

View File

@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PropertyChanged;
using Torch.Utils;
namespace Torch.Collections
@@ -76,7 +77,9 @@ namespace Torch.Collections
}
}
/// <inheritdoc/>
[SuppressPropertyChangedWarnings]
public T this[int index]
{
get
@@ -181,6 +184,7 @@ namespace Torch.Collections
}
/// <inheritdoc/>
[SuppressPropertyChangedWarnings]
object IList.this[int index]
{
get => this[index];

View File

@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;
using PropertyChanged;
using Torch.Utils;
namespace Torch.Collections
@@ -185,6 +186,7 @@ namespace Torch.Collections
}
/// <inheritdoc/>
[SuppressPropertyChangedWarnings]
public TV this[TK key]
{
get

View File

@@ -20,8 +20,10 @@ namespace Torch
_argPrefix = argPrefix;
foreach (var prop in GetType().GetProperties())
{
if (prop.HasAttribute<ArgAttribute>())
_args.Add(prop.GetCustomAttribute<ArgAttribute>(), prop);
var attr = prop.GetCustomAttribute<ArgAttribute>();
if (attr == null)
continue;
_args.Add(attr, prop);
}
}

View File

@@ -26,7 +26,7 @@ namespace Torch.Commands
public event CommandExecutingDel OnCommandExecuting;
private Logger _log = LogManager.GetCurrentClassLogger();
[Dependency]
private IChatManagerServer _chatManager;
private IChatManagerServer _chatManager = null!;
public CommandManager(ITorchBase torch, char prefix = '!') : base(torch)
{

View File

@@ -12,8 +12,6 @@ namespace Torch.Commands
public List<TorchChatMessage> Responses = new List<TorchChatMessage>();
public event Action<TorchChatMessage> OnResponse;
private bool _flag;
/// <inheritdoc />
public ConsoleCommandContext(ITorchBase torch, ITorchPlugin plugin, ulong steamIdSender, string rawArgs = null, List<string> args = null)
: base(torch, plugin, steamIdSender, rawArgs, args) { }
@@ -27,7 +25,11 @@ namespace Torch.Commands
font = null;
}
#pragma warning disable CS0618
#pragma warning disable CS0612
var msg = new TorchChatMessage(sender ?? TorchBase.Instance.Config.ChatName, message, font ?? TorchBase.Instance.Config.ChatColor);
#pragma warning restore CS0612
#pragma warning restore CS0618
Responses.Add(msg);
OnResponse?.Invoke(msg);
}

View File

@@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Threading;
using PropertyChanged;
namespace Torch
{
@@ -77,27 +78,29 @@ namespace Torch
_list = list;
if (_list is INotifyPropertyChanged p)
p.PropertyChanged += OnPropertyChanged;
p.PropertyChanged += OnChildPropertyChanged;
if (_list is INotifyCollectionChanged c)
c.CollectionChanged += OnCollectionChanged;
c.CollectionChanged += OnChildCollectionChanged;
}
public void Dispose()
{
if (_list is INotifyPropertyChanged p)
p.PropertyChanged -= OnPropertyChanged;
p.PropertyChanged -= OnChildPropertyChanged;
if (_list is INotifyCollectionChanged c)
c.CollectionChanged -= OnCollectionChanged;
c.CollectionChanged -= OnChildCollectionChanged;
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
[SuppressPropertyChangedWarnings]
private void OnChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChanged(e);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
[SuppressPropertyChangedWarnings]
private void OnChildPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
@@ -124,27 +127,29 @@ namespace Torch
_dictionary = dictionary;
if (_dictionary is INotifyPropertyChanged p)
p.PropertyChanged += OnPropertyChanged;
p.PropertyChanged += OnChildPropertyChanged;
if (_dictionary is INotifyCollectionChanged c)
c.CollectionChanged += OnCollectionChanged;
c.CollectionChanged += OnChildCollectionChanged;
}
public void Dispose()
{
if (_dictionary is INotifyPropertyChanged p)
p.PropertyChanged -= OnPropertyChanged;
p.PropertyChanged -= OnChildPropertyChanged;
if (_dictionary is INotifyCollectionChanged c)
c.CollectionChanged -= OnCollectionChanged;
c.CollectionChanged -= OnChildCollectionChanged;
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
[SuppressPropertyChangedWarnings]
private void OnChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChanged(e);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
[SuppressPropertyChangedWarnings]
private void OnChildPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}

3
Torch/FodyWeavers.xml Normal file
View File

@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>

74
Torch/FodyWeavers.xsd Normal file
View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressWarnings" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -12,7 +12,6 @@ using Sandbox.Game.Gui;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.World;
using Sandbox.ModAPI;
using SteamKit2.Unified.Internal;
using Torch.API;
using Torch.API.Managers;
using Torch.Utils;
@@ -120,7 +119,9 @@ namespace Torch.Managers.ChatManager
{
if (!sendToOthers)
return;
#pragma warning disable CS0612
var torchMsg = new TorchChatMessage(MySession.Static.LocalHumanPlayer?.DisplayName ?? "Player", Sync.MyId, messageText, ChatChannel.Global, 0);
#pragma warning restore CS0612
bool consumed = RaiseMessageRecieved(torchMsg);
if (!consumed)
consumed = OfflineMessageProcessor(torchMsg);
@@ -139,7 +140,9 @@ namespace Torch.Managers.ChatManager
private void Multiplayer_ChatMessageReceived(ulong steamUserId, string messageText, ChatChannel channel, long targetId, string customAuthorName)
{
#pragma warning disable CS0612
var torchMsg = new TorchChatMessage(steamUserId, messageText, channel, targetId,
#pragma warning restore CS0612
(steamUserId == MyGameService.UserId) ? MyFontEnum.DarkBlue : MyFontEnum.Blue);
if (!RaiseMessageRecieved(torchMsg) && HasHud)
_hudChatMessageReceived.Invoke(MyHud.Chat, steamUserId, messageText, channel, targetId, customAuthorName);
@@ -147,7 +150,9 @@ namespace Torch.Managers.ChatManager
private void Multiplayer_ScriptedChatMessageReceived(string message, string author, string font, Color color)
{
#pragma warning disable CS0612
var torchMsg = new TorchChatMessage(author, message, font);
#pragma warning restore CS0612
if (!RaiseMessageRecieved(torchMsg) && HasHud)
_hudChatScriptedMessageReceived.Invoke(MyHud.Chat, author, message, font, color);
}
@@ -165,14 +170,14 @@ namespace Torch.Managers.ChatManager
protected static bool HasHud => !Sandbox.Engine.Platform.Game.IsDedicated;
[ReflectedMethod(Name = _hudChatMessageReceivedName)]
private static Action<MyHudChat, ulong, string, ChatChannel, long, string> _hudChatMessageReceived;
private static Action<MyHudChat, ulong, string, ChatChannel, long, string> _hudChatMessageReceived = null!;
[ReflectedMethod(Name = _hudChatScriptedMessageReceivedName)]
private static Action<MyHudChat, string, string, string, Color> _hudChatScriptedMessageReceived;
private static Action<MyHudChat, string, string, string, Color> _hudChatScriptedMessageReceived = null!;
[ReflectedEventReplace(typeof(MyMultiplayerBase), nameof(MyMultiplayerBase.ChatMessageReceived), typeof(MyHudChat), _hudChatMessageReceivedName)]
private static Func<ReflectedEventReplacer> _chatMessageReceivedFactory;
private static Func<ReflectedEventReplacer> _chatMessageReceivedFactory = null!;
[ReflectedEventReplace(typeof(MyMultiplayerBase), nameof(MyMultiplayerBase.ScriptedChatMessageReceived), typeof(MyHudChat), _hudChatScriptedMessageReceivedName)]
private static Func<ReflectedEventReplacer> _scriptedChatMessageReceivedFactory;
private static Func<ReflectedEventReplacer> _scriptedChatMessageReceivedFactory = null!;
private ReflectedEventReplacer _chatMessageRecievedReplacer;
private ReflectedEventReplacer _scriptedChatMessageRecievedReplacer;

View File

@@ -30,7 +30,9 @@ namespace Torch.Managers.ChatManager
{
private static ChatManagerServer _chatManager;
public static event ChatReceivedDel OnChatRecvAccess;
private static ChatManagerServer ChatManager => _chatManager ?? (_chatManager = TorchBase.Instance.CurrentSession.Managers.GetManager<ChatManagerServer>());
#pragma warning disable CS0618
private static ChatManagerServer ChatManager => _chatManager ??= TorchBase.Instance.CurrentSession.Managers.GetManager<ChatManagerServer>();
#pragma warning restore CS0618
internal static void Patch(PatchContext context)
{
@@ -83,7 +85,9 @@ namespace Torch.Managers.ChatManager
{
if (targetSteamId == Sync.MyId)
{
#pragma warning disable CS0612
RaiseMessageRecieved(new TorchChatMessage(authorId, message, ChatChannel.Global, 0));
#pragma warning restore CS0612
return;
}
if (MyMultiplayer.Static == null)
@@ -97,7 +101,7 @@ namespace Torch.Managers.ChatManager
{
var msg = new ChatMsg() { Author = authorId, Text = message };
_dedicatedServerBaseSendChatMessage.Invoke(ref msg);
_dedicatedServerBaseOnChatMessage.Invoke(dedicated, new object[] { msg });
_dedicatedServerOnChatMessage.Invoke(dedicated, new object[] { msg });
}
}
@@ -108,15 +112,15 @@ namespace Torch.Managers.ChatManager
private static MultiplayerBaseSendChatMessageDel _dedicatedServerBaseSendChatMessage;
// [ReflectedMethod] doesn't play well with instance methods and refs.
[ReflectedMethodInfo(typeof(MyDedicatedServerBase), "OnChatMessage")]
private static MethodInfo _dedicatedServerBaseOnChatMessage;
[ReflectedMethodInfo(typeof(MyDedicatedServer), "OnChatMessage")]
private static MethodInfo _dedicatedServerOnChatMessage;
#pragma warning restore 649
public void SendMessageAsOther(string author, string message, Color color = default, ulong targetSteamId = 0, string font = MyFontEnum.White)
{
if (targetSteamId == Sync.MyId)
{
RaiseMessageRecieved(new TorchChatMessage(author, message, font));
RaiseMessageRecieved(new TorchChatMessage(author, message, color, font));
return;
}
if (MyMultiplayer.Static == null)
@@ -158,7 +162,9 @@ namespace Torch.Managers.ChatManager
internal void RaiseMessageRecieved(ChatMsg message, ref bool consumed)
{
#pragma warning disable CS0612
var torchMsg = new TorchChatMessage(GetMemberName(message.Author), message.Author, message.Text, (ChatChannel)message.Channel, message.TargetId);
#pragma warning restore CS0612
if (_muted.Contains(message.Author))
{
consumed = true;

View File

@@ -1,115 +0,0 @@
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Torch.Utils;
namespace Torch.Managers.PatchManager
{
internal class AssemblyMemory
{
#pragma warning disable 649
[ReflectedMethod(Name = "GetMethodDescriptor")]
private static Func<DynamicMethod, RuntimeMethodHandle> _getMethodHandle;
#pragma warning restore 649
/// <summary>
/// Gets the address, in RAM, where the body of a method starts.
/// </summary>
/// <param name="method">Method to find the start of</param>
/// <returns>Address of the method's start</returns>
public static long GetMethodBodyStart(MethodBase method)
{
RuntimeMethodHandle handle;
if (method is DynamicMethod dyn)
handle = _getMethodHandle.Invoke(dyn);
else
handle = method.MethodHandle;
RuntimeHelpers.PrepareMethod(handle);
return handle.GetFunctionPointer().ToInt64();
}
internal static void UnprotectMemoryPage(long memory) {
if (NativeLibrary.IsWindows) {
var succ = NativeLibrary.VirtualProtect(
new IntPtr(memory), new UIntPtr(1),
NativeLibrary.Protection.PAGE_EXECUTE_READWRITE, out var _ignored);
if (!succ) {
throw new System.ComponentModel.Win32Exception();
}
}
}
// x64 ISA format:
// [prefixes] [opcode] [mod-r/m]
// [mod-r/m] is bitfield:
// [7-6] = "mod" adressing mode
// [5-3] = register or opcode extension
// [2-0] = "r/m" extra addressing mode
// http://ref.x86asm.net/coder64.html
/// Direct register addressing mode. (Jump directly to register)
private const byte MODRM_MOD_DIRECT = 0b11;
/// Long-mode prefix (64-bit operand)
private const byte REX_W = 0x48;
/// Moves a 16/32/64 operand into register i when opcode is (MOV_R0+i)
private const byte MOV_R0 = 0xB8;
// Extra opcodes. Used with opcode extension.
private const byte EXT = 0xFF;
/// Opcode extension used with <see cref="EXT"/> for the JMP opcode.
private const byte OPCODE_EXTENSION_JMP = 4;
/// <summary>
/// Reads a byte array from a memory location
/// </summary>
/// <param name="memory">Address to read from</param>
/// <param name="bytes">Number of bytes to read</param>
/// <returns>The bytes that were read</returns>
public static byte[] ReadMemory(long memory, int bytes)
{
var data = new byte[bytes];
Marshal.Copy(new IntPtr(memory), data,0, bytes);
return data;
}
/// <summary>
/// Writes a byte array to a memory location.
/// </summary>
/// <param name="memory">Address to write to</param>
/// <param name="bytes">Data to write</param>
public static void WriteMemory(long memory, byte[] bytes)
{
Marshal.Copy(bytes,0, new IntPtr(memory), bytes.Length);
}
/// <summary>
/// Writes an x64 assembly jump instruction at the given address.
/// </summary>
/// <param name="memory">Address to write the instruction at</param>
/// <param name="jumpTarget">Target address of the jump</param>
/// <returns>The bytes that were overwritten</returns>
public static byte[] WriteJump(long memory, long jumpTarget)
{
byte[] result = ReadMemory(memory, 12);
unsafe
{
var ptr = (byte*)memory;
*ptr = REX_W;
*(ptr + 1) = MOV_R0;
*((long*)(ptr + 2)) = jumpTarget;
*(ptr + 10) = EXT;
*(ptr + 11) = (MODRM_MOD_DIRECT << 6) | (OPCODE_EXTENSION_JMP << 3) | 0;
}
return result;
}
}
}

View File

@@ -8,6 +8,10 @@ using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using MonoMod.Utils.Cil;
using NLog;
using Torch.Managers.PatchManager.MSIL;
using Torch.Managers.PatchManager.Transpile;
@@ -17,18 +21,22 @@ namespace Torch.Managers.PatchManager
{
internal class DecoratedMethod : MethodRewritePattern
{
private static Action<ILHook, bool> IsAppliedSetter;
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
private readonly MethodBase _method;
private ILHook _hook;
internal DecoratedMethod(MethodBase method) : base(null)
{
_method = method;
if (IsAppliedSetter == null)
{
IsAppliedSetter = typeof(ILHook).GetProperty(nameof(ILHook.IsApplied)).CreateSetter<ILHook, bool>();
}
}
private long _revertAddress;
private byte[] _revertData = null;
private GCHandle? _pinnedPatch;
internal bool HasChanged()
{
return Prefixes.HasChanges() || Suffixes.HasChanges() || Transpilers.HasChanges() || PostTranspilers.HasChanges();
@@ -47,60 +55,33 @@ namespace Torch.Managers.PatchManager
return;
_log.Log(PrintMode != 0 ? LogLevel.Info : LogLevel.Debug,
$"Begin patching {_method.DeclaringType?.FullName}#{_method.Name}({string.Join(", ", _method.GetParameters().Select(x => x.ParameterType.Name))})");
var patch = ComposePatchedMethod();
_revertAddress = AssemblyMemory.GetMethodBodyStart(_method);
var newAddress = AssemblyMemory.GetMethodBodyStart(patch);
AssemblyMemory.UnprotectMemoryPage(_revertAddress);
_revertData = AssemblyMemory.WriteJump(_revertAddress, newAddress);
_pinnedPatch = GCHandle.Alloc(patch);
if (_hook == null)
_hook = new ILHook(_method, Manipulator, new ILHookConfig {ManualApply = true});
IsAppliedSetter(_hook, false);
_hook.Apply();
_log.Log(PrintMode != 0 ? LogLevel.Info : LogLevel.Debug,
$"Done patching {_method.DeclaringType?.FullName}#{_method.Name}({string.Join(", ", _method.GetParameters().Select(x => x.ParameterType.Name))})");
$"Done patching {_method.GetID()})");
}
catch (Exception exception)
{
_log.Fatal(exception, $"Error patching {_method.DeclaringType?.FullName}#{_method}");
_log.Fatal(exception, $"Error patching {_method.GetID()}");
throw;
}
}
internal void Revert()
{
if (_pinnedPatch.HasValue)
{
_log.Debug(
$"Revert {_method.DeclaringType?.FullName}#{_method.Name}({string.Join(", ", _method.GetParameters().Select(x => x.ParameterType.Name))})");
AssemblyMemory.WriteMemory(_revertAddress, _revertData);
_revertData = null;
_pinnedPatch.Value.Free();
_pinnedPatch = null;
}
if (_hook == null)
return;
_log.Debug($"Revert {_method.GetID()}");
_hook.Dispose();
_hook = null;
}
#region Create
private int _patchSalt = 0;
private DynamicMethod AllocatePatchMethod()
{
Debug.Assert(_method.DeclaringType != null);
var methodName = "Patched_" + _method.DeclaringType.FullName + _method.Name + $"_{_patchSalt++}";
var returnType = _method is MethodInfo meth ? meth.ReturnType : typeof(void);
var parameters = _method.GetParameters();
var parameterTypes = (_method.IsStatic ? Enumerable.Empty<Type>() : new[] {typeof(object)})
.Concat(parameters.Select(x => x.ParameterType)).ToArray();
var patchMethod = new DynamicMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
returnType, parameterTypes, _method.DeclaringType, true);
if (!_method.IsStatic)
patchMethod.DefineParameter(0, ParameterAttributes.None, INSTANCE_PARAMETER);
for (var i = 0; i < parameters.Length; i++)
patchMethod.DefineParameter((patchMethod.IsStatic ? 0 : 1) + i, parameters[i].Attributes, parameters[i].Name);
return patchMethod;
}
public const string INSTANCE_PARAMETER = "__instance";
public const string RESULT_PARAMETER = "__result";
public const string PREFIX_SKIPPED_PARAMETER = "__prefixSkipped";
@@ -108,40 +89,41 @@ namespace Torch.Managers.PatchManager
private void SavePatchedMethod(string target)
{
var asmBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("SomeName"), AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(target));
var moduleBuilder = asmBuilder.DefineDynamicModule(Path.GetFileNameWithoutExtension(target), Path.GetFileName(target));
var typeBuilder = moduleBuilder.DefineType("Test", TypeAttributes.Public);
var methodName = _method.Name + $"_{_patchSalt}";
var returnType = _method is MethodInfo meth ? meth.ReturnType : typeof(void);
var parameters = _method.GetParameters();
var parameterTypes = (_method.IsStatic ? Enumerable.Empty<Type>() : new[] {_method.DeclaringType})
.Concat(parameters.Select(x => x.ParameterType)).ToArray();
var patchMethod = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
returnType, parameterTypes);
if (!_method.IsStatic)
patchMethod.DefineParameter(0, ParameterAttributes.None, INSTANCE_PARAMETER);
for (var i = 0; i < parameters.Length; i++)
patchMethod.DefineParameter((patchMethod.IsStatic ? 0 : 1) + i, parameters[i].Attributes, parameters[i].Name);
var generator = new LoggingIlGenerator(patchMethod.GetILGenerator(), LogLevel.Trace);
List<MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList();
MethodTranspiler.EmitMethod(il, generator);
Type res = typeBuilder.CreateType();
asmBuilder.Save(Path.GetFileName(target));
foreach (var method in res.GetMethods(BindingFlags.Public | BindingFlags.Static))
_log.Info($"Information " + method);
throw new NotSupportedException();
// var asmBuilder =
// AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("SomeName"), AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(target));
// var moduleBuilder = asmBuilder.DefineDynamicModule(Path.GetFileNameWithoutExtension(target), Path.GetFileName(target));
// var typeBuilder = moduleBuilder.DefineType("Test", TypeAttributes.Public);
//
//
// var methodName = _method.Name + $"_{_patchSalt}";
// var returnType = _method is MethodInfo meth ? meth.ReturnType : typeof(void);
// var parameters = _method.GetParameters();
// var parameterTypes = (_method.IsStatic ? Enumerable.Empty<Type>() : new[] {_method.DeclaringType})
// .Concat(parameters.Select(x => x.ParameterType)).ToArray();
//
// var patchMethod = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
// returnType, parameterTypes);
// if (!_method.IsStatic)
// patchMethod.DefineParameter(0, ParameterAttributes.None, INSTANCE_PARAMETER);
// for (var i = 0; i < parameters.Length; i++)
// patchMethod.DefineParameter((patchMethod.IsStatic ? 0 : 1) + i, parameters[i].Attributes, parameters[i].Name);
//
// var generator = new LoggingIlGenerator(patchMethod.GetILGenerator(), LogLevel.Trace);
// List<MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList();
//
// MethodTranspiler.EmitMethod(il, generator);
//
// Type res = typeBuilder.CreateType();
// asmBuilder.Save(Path.GetFileName(target));
// foreach (var method in res.GetMethods(BindingFlags.Public | BindingFlags.Static))
// _log.Info($"Information " + method);
}
public DynamicMethod ComposePatchedMethod()
public void Manipulator(ILContext context)
{
DynamicMethod method = AllocatePatchMethod();
var generator = new LoggingIlGenerator(method.GetILGenerator(),
context.IL.Clear();
var generator = new LoggingIlGenerator(new CecilILGenerator(context.IL),
PrintMode.HasFlag(PrintModeEnum.EmittedReflection) ? LogLevel.Info : LogLevel.Trace);
List<MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList();
@@ -161,7 +143,9 @@ namespace Torch.Managers.PatchManager
_log.Info(msg);
}
#pragma warning disable CS0612
if (PrintMsil || DumpTarget != null)
#pragma warning restore CS0612
{
lock (_log)
{
@@ -181,31 +165,16 @@ namespace Torch.Managers.PatchManager
MethodTranspiler.EmitMethod(il, generator);
try
{
PatchUtilities.Compile(method);
}
catch (Exception failure)
{
lock (_log)
{
_log.Error(failure, $"Failed to patch method {_method}");
var ctx = new MethodContext(method);
ctx.Read();
MethodTranspiler.IntegrityAnalysis((err, msg) => _log.Warn(msg), ctx.Instructions);
LogManager.Flush();
}
throw;
}
#pragma warning disable CS0612
if (PrintMsil || DumpTarget != null)
#pragma warning restore CS0612
{
lock (_log)
{
var ctx = new MethodContext(method);
ctx.Read();
var instructions = context.Body.Instructions
.Select(b => new MsilInstruction(b)).ToList();
LogTarget(PrintModeEnum.Patched, false, "========== Patched method ==========");
MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Patched, a, b), ctx.Instructions, true);
MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Patched, a, b), instructions, true);
LogTarget(PrintModeEnum.Patched, false, gap);
}
}
@@ -214,8 +183,6 @@ namespace Torch.Managers.PatchManager
{
dumpTarget?.Close();
}
return method;
}
#endregion
@@ -284,8 +251,8 @@ namespace Torch.Managers.PatchManager
if (prefix.ReturnType == typeof(bool))
instructions.Add(new MsilInstruction(OpCodes.Brfalse).InlineTarget(labelSkipMethodContent));
else if (prefix.ReturnType != typeof(void))
throw new Exception(
$"Prefixes must return void or bool. {prefix.DeclaringType?.FullName}.{prefix.Name} returns {prefix.ReturnType}");
throw new PatchException(
$"Prefixes must return void or bool. {prefix.DeclaringType?.FullName}.{prefix.Name} returns {prefix.ReturnType}", prefix);
}
instructions.AddRange(MethodTranspiler.Transpile(_method, (x) => declareLocal(x, false), Transpilers, labelAfterOriginalContent));
@@ -308,7 +275,7 @@ namespace Torch.Managers.PatchManager
{
instructions.AddRange(EmitMonkeyCall(suffix, specialVariables));
if (suffix.ReturnType != typeof(void))
throw new Exception($"Suffixes must return void. {suffix.DeclaringType?.FullName}.{suffix.Name} returns {suffix.ReturnType}");
throw new PatchException($"Suffixes must return void. {suffix.DeclaringType?.FullName}.{suffix.Name} returns {suffix.ReturnType}", suffix);
}
if (resultVariable != null)
@@ -331,16 +298,16 @@ namespace Torch.Managers.PatchManager
case INSTANCE_PARAMETER:
{
if (_method.IsStatic)
throw new Exception("Can't use an instance parameter for a static method");
throw new PatchException("Can't use an instance parameter for a static method", _method);
yield return new MsilInstruction(OpCodes.Ldarg_0);
break;
}
case PREFIX_SKIPPED_PARAMETER:
{
if (param.ParameterType != typeof(bool))
throw new Exception($"Prefix skipped parameter {param.ParameterType} must be of type bool");
throw new PatchException($"Prefix skipped parameter {param.ParameterType} must be of type bool", _method);
if (param.ParameterType.IsByRef || param.IsOut)
throw new Exception($"Prefix skipped parameter {param.ParameterType} can't be a reference type");
throw new PatchException($"Prefix skipped parameter {param.ParameterType} can't be a reference type", _method);
if (specialVariables.TryGetValue(PREFIX_SKIPPED_PARAMETER, out MsilLocal prefixSkip))
yield return new MsilInstruction(OpCodes.Ldloc).InlineValue(prefixSkip);
else
@@ -353,8 +320,8 @@ namespace Torch.Managers.PatchManager
? param.ParameterType.GetElementType()
: param.ParameterType;
if (retType == null || !retType.IsAssignableFrom(specialVariables[RESULT_PARAMETER].Type))
throw new Exception(
$"Return type {specialVariables[RESULT_PARAMETER].Type} can't be assigned to result parameter type {retType}");
throw new PatchException(
$"Return type {specialVariables[RESULT_PARAMETER].Type} can't be assigned to result parameter type {retType}", _method);
yield return new MsilInstruction(param.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc)
.InlineValue(specialVariables[RESULT_PARAMETER]);
break;
@@ -372,7 +339,7 @@ namespace Torch.Managers.PatchManager
{
var fieldName = param.Name.Substring(8);
var fieldDef = _method.DeclaringType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).FirstOrDefault(x => x.Name == fieldName);
if (fieldDef == null) throw new Exception($"Could not find field {fieldName}");
if (fieldDef == null) throw new PatchException($"Could not find field {fieldName}", _method);
if (fieldDef.IsStatic)
yield return new MsilInstruction(param.ParameterType.IsByRef ? OpCodes.Ldsflda : OpCodes.Ldsfld)
.InlineValue(fieldDef);
@@ -388,7 +355,7 @@ namespace Torch.Managers.PatchManager
ParameterInfo declParam = _method.GetParameters().FirstOrDefault(x => x.Name == param.Name);
if (declParam == null)
throw new Exception($"Parameter name {param.Name} not found");
throw new PatchException($"Parameter name {param.Name} not found", _method);
int paramIdx = (_method.IsStatic ? 0 : 1) + declParam.Position;
bool patchByRef = param.IsOut || param.ParameterType.IsByRef;

View File

@@ -7,8 +7,14 @@ using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Windows.Documents;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Utils;
using Torch.Managers.PatchManager.Transpile;
using Torch.Utils;
using OpCode = System.Reflection.Emit.OpCode;
using OpCodes = System.Reflection.Emit.OpCodes;
using OperandType = System.Reflection.Emit.OperandType;
namespace Torch.Managers.PatchManager.MSIL
{
@@ -82,6 +88,132 @@ namespace Torch.Managers.PatchManager.MSIL
}
}
public MsilInstruction(Instruction instruction)
{
Label CreateLabel(int pos)
{
var instance = Activator.CreateInstance(typeof(Label),
BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null,
new object[] {pos}, null);
if (instance == null)
return default;
return (Label) instance;
}
if (!MethodContext.OpCodeLookup.TryGetValue(instruction.OpCode.Value, out var opCode))
return;
OpCode = opCode;
var opType = opCode.OperandType;
if (opType == OperandType.InlineNone)
{
Operand = null;
return;
}
switch (instruction.Operand)
{
case OperandType.InlineNone:
break;
case Instruction targetInstruction when opType == OperandType.InlineBrTarget || opType == OperandType.ShortInlineBrTarget:
Operand = new MsilOperandBrTarget(this)
{
Target = new MsilLabel(CreateLabel(targetInstruction.Offset))
};
break;
case FieldReference reference when opType == OperandType.InlineField:
Operand = new MsilOperandInline.MsilOperandReflected<FieldInfo>(this)
{
Value = reference.ResolveReflection()
};
break;
case int int32 when opType == OperandType.InlineI || opType == OperandType.ShortInlineI:
Operand = new MsilOperandInline.MsilOperandInt32(this)
{
Value = int32
};
break;
case long int64 when opType == OperandType.InlineI8:
Operand = new MsilOperandInline.MsilOperandInt64(this)
{
Value = int64
};
break;
case MethodReference methodReference when opType == OperandType.InlineMethod:
Operand = new MsilOperandInline.MsilOperandReflected<MethodBase>(this)
{
Value = methodReference.ResolveReflection()
};
break;
case double @double when opType == OperandType.InlineR:
Operand = new MsilOperandInline.MsilOperandDouble(this)
{
Value = @double
};
break;
case null when opType == OperandType.InlineSig:
throw new NotSupportedException("InlineSignature is not supported by instruction converter");
case string @string when opType == OperandType.InlineString:
Operand = new MsilOperandInline.MsilOperandString(this)
{
Value = @string
};
break;
case Instruction[] targetInstructions when opType == OperandType.InlineSwitch:
Operand = new MsilOperandSwitch(this)
{
Labels = targetInstructions.Select(b => new MsilLabel(CreateLabel(b.Offset))).ToArray()
};
break;
case MemberReference memberReference when opType == OperandType.InlineTok:
Operand = new MsilOperandInline.MsilOperandReflected<MemberInfo>(this)
{
Value = memberReference.ResolveReflection()
};
break;
case TypeReference typeReference when opType == OperandType.InlineType:
Operand = new MsilOperandInline.MsilOperandReflected<Type>(this)
{
Value = typeReference.ResolveReflection()
};
break;
case VariableDefinition variableDefinition when opType == OperandType.InlineVar || opType == OperandType.ShortInlineVar:
if (OpCode.IsLocalStore() || OpCode.IsLocalLoad() || OpCode.IsLocalLoadByRef())
Operand = new MsilOperandInline.MsilOperandLocal(this)
{
Value = new MsilLocal(variableDefinition.Index)
};
else
Operand = new MsilOperandInline.MsilOperandArgument(this)
{
Value = new MsilArgument(variableDefinition.Index)
};
break;
case ParameterDefinition parameterDefinition when opType == OperandType.InlineVar || opType == OperandType.ShortInlineVar:
if (OpCode.IsLocalStore() || OpCode.IsLocalLoad() || OpCode.IsLocalLoadByRef())
Operand = new MsilOperandInline.MsilOperandLocal(this)
{
Value = new MsilLocal(parameterDefinition.Index)
};
else
Operand = new MsilOperandInline.MsilOperandArgument(this)
{
Value = new MsilArgument(parameterDefinition.Index)
};
break;
case float @float when opType == OperandType.ShortInlineR:
Operand = new MsilOperandInline.MsilOperandSingle(this)
{
Value = @float
};
break;
#pragma warning disable 618
case null when opType == OperandType.InlinePhi:
#pragma warning restore 618
default:
throw new ArgumentOutOfRangeException(nameof(instruction.Operand), instruction.Operand, "Invalid operand type");
}
}
/// <summary>
/// Opcode of this instruction
/// </summary>

View File

@@ -79,7 +79,10 @@ namespace Torch.Managers.PatchManager.MSIL
switch (Instruction.OpCode.OperandType)
{
case OperandType.ShortInlineI:
generator.Emit(Instruction.OpCode, (byte)Value);
if (Instruction.OpCode == OpCodes.Ldc_I4_S)
generator.Emit(Instruction.OpCode, Value);
else
generator.Emit(Instruction.OpCode);
return;
case OperandType.InlineI:
generator.Emit(Instruction.OpCode, Value);

View File

@@ -1,40 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Torch.Managers.PatchManager {
internal static class NativeLibrary {
private static readonly HashSet<PlatformID> WindowsPlatformIDSet = new HashSet<PlatformID>
{
PlatformID.Win32NT, PlatformID.Win32S, PlatformID.Win32Windows, PlatformID.WinCE
};
public static bool IsWindows {
get {
return WindowsPlatformIDSet.Contains(Environment.OSVersion.Platform);
}
}
[Flags]
public enum Protection {
PAGE_NOACCESS = 0x01,
PAGE_READONLY = 0x02,
PAGE_READWRITE = 0x04,
PAGE_WRITECOPY = 0x08,
PAGE_EXECUTE = 0x10,
PAGE_EXECUTE_READ = 0x20,
PAGE_EXECUTE_READWRITE = 0x40,
PAGE_EXECUTE_WRITECOPY = 0x80,
PAGE_GUARD = 0x100,
PAGE_NOCACHE = 0x200,
PAGE_WRITECOMBINE = 0x400
}
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize,
Protection flNewProtect, out Protection lpflOldProtect);
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Reflection;
namespace Torch.Managers.PatchManager
{
public class PatchException : Exception
{
public PatchException(string message, MemberInfo targetMember) : base(
$"Patching exception in {targetMember.DeclaringType?.FullName}::{targetMember.Name}: {message}")
{
}
}
}

View File

@@ -53,25 +53,27 @@ namespace Torch.Managers.PatchManager
}
#pragma warning disable 649
[ReflectedStaticMethod(Type = typeof(RuntimeHelpers), Name = "_CompileMethod", OverrideTypeNames = new[] {"System.IRuntimeMethodInfo"})]
private static Action<object> _compileDynamicMethod;
[ReflectedMethod(Name = "GetMethodInfo")]
private static Func<RuntimeMethodHandle, object> _getMethodInfo;
[ReflectedMethod(Name = "GetMethodDescriptor")]
private static Func<DynamicMethod, RuntimeMethodHandle> _getMethodHandle;
// [ReflectedStaticMethod(Type = typeof(RuntimeHelpers), Name = "_CompileMethod", OverrideTypeNames = new[] {"System.IRuntimeMethodInfo"})]
// private static Action<object> _compileDynamicMethod;
//
// [ReflectedMethod(Name = "GetMethodInfo")]
// private static Func<RuntimeMethodHandle, object> _getMethodInfo;
//
// [ReflectedMethod(Name = "GetMethodDescriptor")]
// private static Func<DynamicMethod, RuntimeMethodHandle> _getMethodHandle;
#pragma warning restore 649
/// <summary>
/// Forces the given dynamic method to be compiled
/// </summary>
/// <param name="method"></param>
[Obsolete]
public static void Compile(DynamicMethod method)
{
throw new NotSupportedException();
// Force it to compile
RuntimeMethodHandle handle = _getMethodHandle.Invoke(method);
object runtimeMethodInfo = _getMethodInfo.Invoke(handle);
_compileDynamicMethod.Invoke(runtimeMethodInfo);
// RuntimeMethodHandle handle = _getMethodHandle.Invoke(method);
// object runtimeMethodInfo = _getMethodInfo.Invoke(handle);
// _compileDynamicMethod.Invoke(runtimeMethodInfo);
}
}
}

View File

@@ -3,8 +3,11 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using Mono.Cecil.Cil;
using MonoMod.Utils.Cil;
using NLog;
using Torch.Utils;
using OpCode = System.Reflection.Emit.OpCode;
// ReSharper disable ConditionIsAlwaysTrueOrFalse
#pragma warning disable 162 // unreachable code
@@ -22,7 +25,7 @@ namespace Torch.Managers.PatchManager.Transpile
/// <summary>
/// Backing generator
/// </summary>
public ILGenerator Backing { get; }
public ILGeneratorShim Backing { get; }
private readonly LogLevel _level;
@@ -30,7 +33,7 @@ namespace Torch.Managers.PatchManager.Transpile
/// Creates a new logging IL generator backed by the given generator.
/// </summary>
/// <param name="backing">Backing generator</param>
public LoggingIlGenerator(ILGenerator backing, LogLevel level)
public LoggingIlGenerator(ILGeneratorShim backing, LogLevel level)
{
Backing = backing;
_level = level;
@@ -45,7 +48,7 @@ namespace Torch.Managers.PatchManager.Transpile
}
/// <inheritdoc cref="ILGenerator.Emit(OpCode)"/>
/// <inheritdoc cref="ILGenerator.Emit(System.Reflection.Emit.OpCode)"/>
public void Emit(OpCode op)
{
_log?.Log(_level, $"Emit\t{op,_opcodePadding}");

View File

@@ -45,36 +45,36 @@ namespace Torch.Managers.PatchManager.Transpile
#pragma warning disable 649
[ReflectedMethod(Name = "BakeByteArray")]
// [ReflectedMethod(Name = "BakeByteArray")]
private static Func<ILGenerator, byte[]> _ilGeneratorBakeByteArray;
[ReflectedMethod(Name = "GetExceptions")]
// [ReflectedMethod(Name = "GetExceptions")]
private static Func<ILGenerator, Array> _ilGeneratorGetExceptionHandlers;
private const string InternalExceptionInfo = "System.Reflection.Emit.__ExceptionInfo, mscorlib";
private const string InternalExceptionInfo = "System.Reflection.Emit.__ExceptionInfo, System.Private.CoreLib";
[ReflectedMethod(Name = "GetExceptionTypes", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetExceptionTypes", TypeName = InternalExceptionInfo)]
private static Func<object, int[]> _exceptionHandlerGetTypes;
[ReflectedMethod(Name = "GetStartAddress", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetStartAddress", TypeName = InternalExceptionInfo)]
private static Func<object, int> _exceptionHandlerGetStart;
[ReflectedMethod(Name = "GetEndAddress", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetEndAddress", TypeName = InternalExceptionInfo)]
private static Func<object, int> _exceptionHandlerGetEnd;
[ReflectedMethod(Name = "GetFinallyEndAddress", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetFinallyEndAddress", TypeName = InternalExceptionInfo)]
private static Func<object, int> _exceptionHandlerGetFinallyEnd;
[ReflectedMethod(Name = "GetNumberOfCatches", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetNumberOfCatches", TypeName = InternalExceptionInfo)]
private static Func<object, int> _exceptionHandlerGetCatchCount;
[ReflectedMethod(Name = "GetCatchAddresses", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetCatchAddresses", TypeName = InternalExceptionInfo)]
private static Func<object, int[]> _exceptionHandlerGetCatchAddrs;
[ReflectedMethod(Name = "GetCatchEndAddresses", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetCatchEndAddresses", TypeName = InternalExceptionInfo)]
private static Func<object, int[]> _exceptionHandlerGetCatchEndAddrs;
[ReflectedMethod(Name = "GetFilterAddresses", TypeName = InternalExceptionInfo)]
// [ReflectedMethod(Name = "GetFilterAddresses", TypeName = InternalExceptionInfo)]
private static Func<object, int[]> _exceptionHandlerGetFilterAddrs;
#pragma warning restore 649
@@ -216,7 +216,7 @@ namespace Torch.Managers.PatchManager.Transpile
return string.Join("\n", _instructions.Select(x => $"IL_{x.Offset:X4}: {x.StackChange():+0;-#} {x}"));
}
private static readonly Dictionary<short, OpCode> OpCodeLookup;
internal static readonly Dictionary<short, OpCode> OpCodeLookup;
private static readonly HashSet<short> Prefixes;
static MethodContext()

View File

@@ -20,14 +20,15 @@ namespace Torch.Managers
/// </summary>
public class UpdateManager : Manager
{
private Timer _updatePollTimer;
private readonly Timer _updatePollTimer;
private string _torchDir = new FileInfo(typeof(UpdateManager).Assembly.Location).DirectoryName;
private Logger _log = LogManager.GetCurrentClassLogger();
[Dependency]
private FilesystemManager _fsManager;
private FilesystemManager _fsManager = null!;
public UpdateManager(ITorchBase torchInstance) : base(torchInstance)
{
_updatePollTimer = null;
//_updatePollTimer = new Timer(TimerElapsed, this, TimeSpan.Zero, TimeSpan.FromMinutes(5));
}

View File

@@ -4,6 +4,7 @@ using Sandbox;
using Torch.API;
using Torch.Managers.PatchManager;
using Torch.Utils;
#pragma warning disable CS0618
namespace Torch.Patches
{

View File

@@ -67,28 +67,17 @@ namespace Torch.Patches
}
[ReflectedMethod(Name = "GetIdentByThread")]
private static Func<MyLog, int, int> _getIndentByThread;
private static Func<MyLog, int, int> GetIndentByThread = null!;
[ThreadStatic]
private static StringBuilder _tmpStringBuilder;
private static StringBuilder PrepareLog(MyLog log)
{
if (_tmpStringBuilder == null)
_tmpStringBuilder = new StringBuilder();
_tmpStringBuilder ??= new();
_tmpStringBuilder.Clear();
var i = Thread.CurrentThread.ManagedThreadId;
int t = 0;
try
{
t = _getIndentByThread(log, i);
}
catch (Exception e)
{
_log.Debug(e, "Failed to get thread indent");
}
var t = GetIndentByThread(log, Environment.CurrentManagedThreadId);
_tmpStringBuilder.Append(' ', t * 3);
return _tmpStringBuilder;
@@ -96,24 +85,27 @@ namespace Torch.Patches
private static bool PrefixWriteLine(MyLog __instance, string msg)
{
_log.Debug(PrepareLog(__instance).Append(msg));
if (__instance.LogEnabled)
_log.Debug(PrepareLog(__instance).Append(msg));
return false;
}
private static bool PrefixWriteLineConsole(MyLog __instance, string msg)
{
_log.Info(PrepareLog(__instance).Append(msg));
if (__instance.LogEnabled)
_log.Info(PrepareLog(__instance).Append(msg));
return false;
}
private static bool PrefixAppendToClosedLog(MyLog __instance, string text)
{
_log.Info(PrepareLog(__instance).Append(text));
if (__instance.LogEnabled)
_log.Info(PrepareLog(__instance).Append(text));
return false;
}
private static bool PrefixWriteLineOptions(MyLog __instance, string message, LoggingOptions option)
{
if (__instance.LogFlag(option))
if (__instance.LogEnabled && __instance.LogFlag(option))
_log.Info(PrepareLog(__instance).Append(message));
return false;
}
@@ -132,10 +124,12 @@ namespace Torch.Patches
private static bool PrefixLogFormatted(MyLog __instance, MyLogSeverity severity, string format, object[] args)
{
if (__instance.LogEnabled)
return false;
// Sometimes this is called with a pre-formatted string and no args
// and causes a crash when the format string contains braces
var sb = PrepareLog(__instance);
if (args != null && args.Length > 0)
if (args is {Length: > 0})
sb.AppendFormat(format, args);
else
sb.Append(format);
@@ -146,27 +140,22 @@ namespace Torch.Patches
private static bool PrefixLogStringBuilder(MyLog __instance, MyLogSeverity severity, StringBuilder builder)
{
_log.Log(LogLevelFor(severity), PrepareLog(__instance).Append(builder));
if (__instance.LogEnabled)
_log.Log(LogLevelFor(severity), PrepareLog(__instance).Append(builder));
return false;
}
private static LogLevel LogLevelFor(MyLogSeverity severity)
{
switch (severity)
return severity switch
{
case MyLogSeverity.Debug:
return LogLevel.Debug;
case MyLogSeverity.Info:
return LogLevel.Info;
case MyLogSeverity.Warning:
return LogLevel.Warn;
case MyLogSeverity.Error:
return LogLevel.Error;
case MyLogSeverity.Critical:
return LogLevel.Fatal;
default:
return LogLevel.Info;
}
MyLogSeverity.Debug => LogLevel.Debug,
MyLogSeverity.Info => LogLevel.Info,
MyLogSeverity.Warning => LogLevel.Warn,
MyLogSeverity.Error => LogLevel.Error,
MyLogSeverity.Critical => LogLevel.Fatal,
_ => LogLevel.Info
};
}
}
}

View File

@@ -19,7 +19,7 @@ namespace Torch.Patches
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
#pragma warning disable 649
[ReflectedMethodInfo(typeof(MyWorkshop), nameof(MyWorkshop.DownloadWorldModsBlocking))]
private readonly static MethodInfo _downloadWorldModsBlockingMethod;
private static MethodInfo _downloadWorldModsBlockingMethod;
#pragma warning restore 649
public static void Patch(PatchContext ctx)
@@ -29,11 +29,15 @@ namespace Torch.Patches
ctx.GetPattern(_downloadWorldModsBlockingMethod).Suffixes
.Add(typeof(ModsDownloadingPatch).GetMethod(nameof(Postfix)));
}
public static void Postfix(MyWorkshop.ResultData __result)
public static void Postfix(MyWorkshop.ResultData __result, List<MyObjectBuilder_Checkpoint.ModItem> mods)
{
if (__result.Success) return;
_log.Warn("Missing Mods:");
__result.MismatchMods?.ForEach(b => _log.Info($"\t{b}"));
var mismatchMods = mods.Where(b => __result.Mods.All(c => b.PublishedFileId != c.Id));
foreach (var mod in mismatchMods)
{
_log.Warn($"\t{mod.PublishedFileId} : {mod.FriendlyName}");
}
}
}
}

View File

@@ -26,7 +26,7 @@ namespace Torch.Patches
{
#pragma warning disable 649
[ReflectedGetter(Name = "m_objectFactory", TypeName = "Sandbox.Game.Entities.MyEntityFactory, Sandbox.Game")]
private static readonly Func<MyObjectFactory<MyEntityTypeAttribute, MyEntity>> _entityFactoryObjectFactory;
private static Func<MyObjectFactory<MyEntityTypeAttribute, MyEntity>> EntityFactoryObjectFactory;
#pragma warning restore 649
internal static void ForceRegisterAssemblies()
@@ -35,7 +35,7 @@ namespace Torch.Patches
// static MyEntities() called by MySandboxGame.ForceStaticCtor
RuntimeHelpers.RunClassConstructor(typeof(MyEntities).TypeHandle);
{
MyObjectFactory<MyEntityTypeAttribute, MyEntity> factory = _entityFactoryObjectFactory();
MyObjectFactory<MyEntityTypeAttribute, MyEntity> factory = EntityFactoryObjectFactory();
ObjectFactory_RegisterFromAssemblySafe(factory, typeof(MySandboxGame).Assembly); // calling assembly
ObjectFactory_RegisterFromAssemblySafe(factory, MyPlugins.GameAssembly);
ObjectFactory_RegisterFromAssemblySafe(factory, MyPlugins.SandboxAssembly);
@@ -105,11 +105,11 @@ namespace Torch.Patches
#region MyComponentTypeFactory Adders
[ReflectedGetter(Name = "m_idToType", Type = typeof(MyComponentTypeFactory))]
private static Func<Dictionary<MyStringId, Type>> _componentTypeFactoryIdToType;
private static Func<Dictionary<MyStringId, Type>> ComponentTypeFactoryIdToType = null!;
[ReflectedGetter(Name = "m_typeToId", Type = typeof(MyComponentTypeFactory))]
private static Func<Dictionary<Type, MyStringId>> _componentTypeFactoryTypeToId;
private static Func<Dictionary<Type, MyStringId>> ComponentTypeFactoryTypeToId = null!;
[ReflectedGetter(Name = "m_typeToContainerComponentType", Type = typeof(MyComponentTypeFactory))]
private static Func<Dictionary<Type, Type>> _componentTypeFactoryContainerComponentType;
private static Func<Dictionary<Type, Type>> ComponentTypeFactoryContainerComponentType = null!;
private static void ComponentTypeFactory_RegisterFromAssemblySafe(Assembly assembly)
{
@@ -127,13 +127,13 @@ namespace Torch.Patches
{
Type componentType = type.GetCustomAttribute<MyComponentTypeAttribute>(true)?.ComponentType;
if (componentType != null)
_componentTypeFactoryContainerComponentType()[type] = componentType;
ComponentTypeFactoryContainerComponentType()[type] = componentType;
}
private static void ComponentTypeFactory_AddIdSafe(Type type, MyStringId id)
{
_componentTypeFactoryIdToType()[id] = type;
_componentTypeFactoryTypeToId()[type] = id;
ComponentTypeFactoryIdToType()[id] = type;
ComponentTypeFactoryTypeToId()[type] = id;
}
#endregion
}

View File

@@ -43,10 +43,12 @@ namespace Torch.Patches
//nasty hack
Task.Run(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(30));
TorchBase.Instance.Restart();
});
{
Thread.Sleep(TimeSpan.FromSeconds(30));
#pragma warning disable CS0618
TorchBase.Instance.Restart();
#pragma warning restore CS0618
});
return false;
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.CodeAnalysis;
using ProtoBuf;
using Torch.Managers.PatchManager;
using Torch.Managers.PatchManager.MSIL;
using Torch.Utils;
using VRage.FileSystem;
using VRage.Scripting;
namespace Torch.Patches
{
[PatchShim]
public static class ScriptCompilerPatch
{
[ReflectedMethodInfo(typeof(MyScriptWhitelist), "Register", Parameters = new[] {typeof(MyWhitelistTarget), typeof(INamespaceSymbol), typeof(Type)})]
private static MethodInfo Register1Method = null!;
[ReflectedMethodInfo(typeof(MyScriptWhitelist), "Register", Parameters = new[] {typeof(MyWhitelistTarget), typeof(ITypeSymbol), typeof(Type)})]
private static MethodInfo Register2Method = null!;
public static void Patch(PatchContext context)
{
context.GetPattern(typeof(MyScriptWhitelist).GetConstructor(new[] {typeof(MyScriptCompiler)}))
.AddPrefix(nameof(WhitelistCtorPrefix));
context.GetPattern(Type.GetType("VRage.Scripting.MyVRageScriptingInternal, VRage.Scripting", true).GetMethod("Initialize"))
.AddPrefix(nameof(InitializePrefix));
context.GetPattern(typeof(MyScriptWhitelist).GetNestedType("MyWhitelistBatch", BindingFlags.NonPublic)!
.GetMethod("AllowMembers")).AddPrefix(nameof(AllowMembersPrefix));
context.GetPattern(Register1Method).AddTranspiler(nameof(RegisterTranspiler));
context.GetPattern(Register2Method).AddTranspiler(nameof(RegisterTranspiler));
}
private static void WhitelistCtorPrefix(MyScriptCompiler scriptCompiler)
{
scriptCompiler.AddReferencedAssemblies(
typeof(Regex).Assembly.Location,
typeof(Enumerable).Assembly.Location,
typeof(ConcurrentBag<>).Assembly.Location,
typeof(ImmutableArray).Assembly.Location,
typeof(System.ComponentModel.TypeConverter).Assembly.Location,
typeof(System.Diagnostics.TraceSource).Assembly.Location,
typeof(ProtoBuf.Meta.RuntimeTypeModel).Assembly.Location,
Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll"),
Path.Combine(MyFileSystem.ExePath, "Sandbox.Common.dll"),
Path.Combine(MyFileSystem.ExePath, "Sandbox.Graphics.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.Library.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.Math.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.Game.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.Render.dll"),
Path.Combine(MyFileSystem.ExePath, "VRage.Input.dll"),
Path.Combine(MyFileSystem.ExePath, "SpaceEngineers.ObjectBuilders.dll"),
Path.Combine(MyFileSystem.ExePath, "SpaceEngineers.Game.dll"));
}
private static bool InitializePrefix(Thread updateThread, Type[] referencedTypes, string[] symbols)
{
MyModWatchdog.Init(updateThread);
MyScriptCompiler.Static.AddImplicitIngameNamespacesFromTypes(referencedTypes);
MyScriptCompiler.Static.AddConditionalCompilationSymbols(symbols);
return false;
}
[SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalse")]
private static void AllowMembersPrefix(ref MemberInfo[] members)
{
if (members.Any(b => b is null))
members = members.Where(b => b is { }).ToArray();
}
private static IEnumerable<MsilInstruction> RegisterTranspiler(IEnumerable<MsilInstruction> instructions)
{
var ins = instructions.ToList();
var throwIns = ins.FindAll(b => b.OpCode == OpCodes.Throw).Select(b => ins.IndexOf(b));
foreach (var index in throwIns)
{
var i = index;
do
{
ins[i] = new(OpCodes.Nop);
} while (ins[--i].OpCode.OperandType != OperandType.ShortInlineBrTarget);
ins[index] = new(OpCodes.Ret);
}
return ins;
}
}
}

View File

@@ -19,7 +19,9 @@ namespace Torch.Patches
internal static class SessionDownloadPatch
{
private static ITorchSessionManager _sessionManager;
private static ITorchSessionManager SessionManager => _sessionManager ?? (_sessionManager = TorchBase.Instance.Managers.GetManager<ITorchSessionManager>());
#pragma warning disable CS0618
private static ITorchSessionManager SessionManager => _sessionManager ??= TorchBase.Instance.Managers.GetManager<ITorchSessionManager>();
#pragma warning restore CS0618
internal static void Patch(PatchContext context)

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Xml;
using Torch.Managers.PatchManager;
using Torch.Managers.PatchManager.MSIL;
using Torch.Utils;
using VRage;
namespace Torch.Patches;
internal static class XmlRootWriterPatch
{
[ReflectedMethodInfo(typeof(CustomRootWriter), "Init")]
private static MethodInfo InitMethod = null!;
public static void Patch(PatchContext context)
{
context.GetPattern(InitMethod).AddTranspiler();
}
private static IEnumerable<MsilInstruction> Transpiler(IEnumerable<MsilInstruction> instructions)
{
var ins = instructions.ToList();
var index = ins.FindIndex(b =>
b.OpCode == OpCodes.Ldstr && b.Operand is MsilOperandInline.MsilOperandString {Value: "xsi:type"});
((MsilOperandInline.MsilOperandString)ins[index].Operand).Value = "xsi";
ins.InsertRange(index + 1, new[]
{
new MsilInstruction(OpCodes.Ldstr).InlineValue("type"),
new MsilInstruction(OpCodes.Ldstr).InlineValue("http://www.w3.org/2001/XMLSchema-instance")
});
var instruction = ins[ins.FindIndex(b => b.OpCode == OpCodes.Callvirt)];
instruction.InlineValue(typeof(XmlWriter).GetMethod(
"WriteAttributeString", new[]
{
typeof(string),
typeof(string),
typeof(string),
typeof(string)
}));
return ins;
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace Torch.Plugins;
internal static class AssemblyRewriter
{
public static Assembly ProcessWeavers(this Stream stream)
{
using var assStream = new MemoryStream();
stream.CopyTo(assStream);
assStream.Position = 0;
using var module = ModuleDefinition.ReadModule(assStream);
foreach (var fieldDefinition in FindAllToRewrite(module))
{
fieldDefinition.IsInitOnly = false;
}
using var memStream = new MemoryStream();
module.Assembly.Write(memStream);
return Assembly.Load(memStream.ToArray());
}
private static IEnumerable<FieldDefinition> FindAllToRewrite(ModuleDefinition definition)
{
return definition.Types.SelectMany(b => b.Fields.Where(HasValidAttributes));
}
private static bool HasValidAttributes(FieldDefinition definition) =>
definition.CustomAttributes.Any(b => b.AttributeType.Name.Contains("Reflected") || b.AttributeType.Name == "DependencyAttribute");
}

View File

@@ -18,6 +18,7 @@ using Torch.API.Session;
using Torch.API.WebAPI;
using Torch.Collections;
using Torch.Commands;
using Torch.Plugins;
using Torch.Utils;
namespace Torch.Managers
@@ -332,42 +333,20 @@ namespace Torch.Managers
{
var assemblies = new List<Assembly>();
var loaded = AppDomain.CurrentDomain.GetAssemblies();
if (item.IsZip)
{
using (var zipFile = ZipFile.OpenRead(item.Path))
using var zipFile = ZipFile.OpenRead(item.Path);
foreach (var entry in zipFile.Entries)
{
foreach (var entry in zipFile.Entries)
{
if (!entry.Name.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase))
continue;
if (!entry.Name.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase))
continue;
//if (loaded.Any(a => entry.Name.Contains(a.GetName().Name)))
// continue;
//if (loaded.Any(a => entry.Name.Contains(a.GetName().Name)))
// continue;
using (var stream = entry.Open())
{
var data = stream.ReadToEnd((int) entry.Length);
byte[] symbol = null;
var symbolEntryName =
entry.FullName.Substring(0, entry.FullName.Length - "dll".Length) + "pdb";
var symbolEntry = zipFile.GetEntry(symbolEntryName);
if (symbolEntry != null)
try
{
using (var symbolStream = symbolEntry.Open())
symbol = symbolStream.ReadToEnd((int) symbolEntry.Length);
}
catch (Exception e)
{
_log.Warn(e, $"Failed to read debugging symbols from {item.Filename}:{symbolEntryName}");
}
assemblies.Add(symbol != null ? Assembly.Load(data, symbol) : Assembly.Load(data));
}
}
using var stream = entry.Open();
assemblies.Add(stream.ProcessWeavers());
}
}
else
@@ -384,25 +363,8 @@ namespace Torch.Managers
//if (loaded.Any(a => file.Contains(a.GetName().Name)))
// continue;
using (var stream = File.OpenRead(file))
{
var data = stream.ReadToEnd();
byte[] symbol = null;
var symbolPath = Path.Combine(Path.GetDirectoryName(file) ?? ".",
Path.GetFileNameWithoutExtension(file) + ".pdb");
if (File.Exists(symbolPath))
try
{
using (var symbolStream = File.OpenRead(symbolPath))
symbol = symbolStream.ReadToEnd();
}
catch (Exception e)
{
_log.Warn(e, $"Failed to read debugging symbols from {symbolPath}");
}
assemblies.Add(symbol != null ? Assembly.Load(data, symbol) : Assembly.Load(data));
}
using var stream = File.OpenRead(file);
assemblies.Add(stream.ProcessWeavers());
}
@@ -486,10 +448,12 @@ namespace Torch.Managers
}
// Backwards compatibility for PluginAttribute.
#pragma warning disable CS0618
var pluginAttr = pluginType.GetCustomAttribute<PluginAttribute>();
if (pluginAttr != null)
{
_log.Warn($"Plugin '{manifest.Name}' is using the obsolete {nameof(PluginAttribute)}, using info from attribute if necessary.");
#pragma warning restore CS0618
manifest.Version = manifest.Version ?? pluginAttr.Version.ToString();
manifest.Name = manifest.Name ?? pluginAttr.Name;
if (manifest.Guid == default(Guid))

View File

@@ -1,74 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{7E01635C-3B67-472E-BCD6-C5539564F214}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Torch</RootNamespace>
<AssemblyName>Torch</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>$(SolutionDir)\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<TargetFramework>net6-windows</TargetFramework>
<AssemblyTitle>Torch</AssemblyTitle>
<Product>Torch</Product>
<Copyright>Copyright © Torch API 2017</Copyright>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>$(SolutionDir)\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutputPath>
<UseWpf>True</UseWpf>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>$(SolutionDir)\bin\x64\Release\Torch.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration) == 'Release'">
<DocumentationFile>$(SolutionDir)\bin\$(Platform)\$(Configuration)\Torch.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<!-- I don't know why this needs to exist -->
<Import Project="..\Torch.Mod\Torch.Mod.projitems" Label="Shared" />
<!-- <Import Project="$(SolutionDir)\TransformOnBuild.targets" /> -->
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<PackageReference Include="ControlzEx" Version="5.0.1" />
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="MonoMod.RuntimeDetour" Version="22.1.4.3" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" PrivateAssets="all" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="HavokWrapper, Version=1.0.6278.22649, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\HavokWrapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MahApps.Metro, Version=1.6.1.4, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MahApps.Metro.1.6.1\lib\net45\MahApps.Metro.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.4.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\GameBinaries\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
<Reference Include="Microsoft.CodeAnalysis, Version=2.9.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<HintPath>..\GameBinaries\Microsoft.CodeAnalysis.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="protobuf-net, Version=2.4.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
<HintPath>..\packages\protobuf-net.2.4.0\lib\net40\protobuf-net.dll</HintPath>
<Reference Include="ProtoBuf.Net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\ProtoBuf.Net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ProtoBuf.Net.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\ProtoBuf.Net.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Sandbox.Common">
<HintPath>..\GameBinaries\Sandbox.Common.dll</HintPath>
@@ -86,49 +61,9 @@
<HintPath>..\GameBinaries\SpaceEngineers.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders">
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers">
<HintPath>..\GameBinaries\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SteamKit2, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SteamKit2.2.1.0\lib\netstandard2.0\SteamKit2.dll</HintPath>
</Reference>
<Reference Include="Steamworks.NET">
<HintPath>..\GameBinaries\Steamworks.NET.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<HintPath>..\packages\System.ComponentModel.Annotations.4.5.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.AccessControl, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.4.4.0\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.4.4.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>..\GameBinaries\VRage.dll</HintPath>
<Private>False</Private>
@@ -149,10 +84,6 @@
<HintPath>..\GameBinaries\VRage.Game.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Game.XmlSerializers">
<HintPath>..\GameBinaries\VRage.Game.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Input">
<HintPath>..\GameBinaries\VRage.Input.dll</HintPath>
<Private>False</Private>
@@ -173,9 +104,6 @@
<HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="VRage.Platform.Windows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>..\GameBinaries\VRage.Platform.Windows.dll</HintPath>
</Reference>
<Reference Include="VRage.Render">
<HintPath>..\GameBinaries\VRage.Render.dll</HintPath>
<Private>False</Private>
@@ -192,190 +120,32 @@
<HintPath>..\GameBinaries\VRage.Steam.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Versioning\AssemblyVersion.cs">
<Link>Properties\AssemblyVersion.cs</Link>
</Compile>
<Compile Include="Collections\BinaryMinHeap.cs" />
<Compile Include="Collections\MtObservableCollection.cs" />
<Compile Include="Collections\MtObservableCollectionBase.cs" />
<Compile Include="Collections\MtObservableSortedDictionary.cs" />
<Compile Include="Collections\MtObservableEvent.cs" />
<Compile Include="Collections\MtObservableList.cs" />
<Compile Include="Collections\SortedView.cs" />
<Compile Include="Collections\SystemSortedView.cs" />
<Compile Include="Collections\TransformComparer.cs" />
<Compile Include="Collections\TransformEnumerator.cs" />
<Compile Include="Commands\ConsoleCommandContext.cs" />
<Compile Include="Event\EventShimAttribute.cs" />
<Compile Include="Extensions\LinqExtensions.cs" />
<Compile Include="Managers\ChatManager\ChatManagerClient.cs" />
<Compile Include="Managers\ChatManager\ChatManagerServer.cs" />
<Compile Include="Extensions\DispatcherExtensions.cs" />
<Compile Include="Extensions\ICollectionExtensions.cs" />
<Compile Include="Managers\DependencyManager.cs" />
<Compile Include="Event\EventList.cs" />
<Compile Include="Event\EventManager.cs" />
<Compile Include="Event\IEventList.cs" />
<Compile Include="Managers\PatchManager\AssemblyMemory.cs" />
<Compile Include="Managers\PatchManager\DecoratedMethod.cs" />
<Compile Include="Managers\PatchManager\EmitExtensions.cs" />
<Compile Include="Managers\PatchManager\MSIL\ITokenResolver.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilInstruction.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilInstructionExtensions.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilLabel.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilArgument.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilLocal.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilOperand.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilOperandBrTarget.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilOperandInline.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilOperandSwitch.cs" />
<Compile Include="Managers\PatchManager\MethodRewritePattern.cs" />
<Compile Include="Managers\PatchManager\MSIL\MsilTryCatchOperation.cs" />
<Compile Include="Managers\PatchManager\NativeLibrary.cs" />
<Compile Include="Managers\PatchManager\PatchShimAttribute.cs" />
<Compile Include="Managers\PatchManager\PatchContext.cs" />
<Compile Include="Managers\PatchManager\PatchManager.cs" />
<Compile Include="Managers\PatchManager\PatchPriorityAttribute.cs" />
<Compile Include="Managers\PatchManager\PatchUtilities.cs" />
<Compile Include="Managers\PatchManager\Transpile\LoggingILGenerator.cs" />
<Compile Include="Managers\PatchManager\Transpile\MethodContext.cs" />
<Compile Include="Managers\PatchManager\Transpile\MethodTranspiler.cs" />
<Compile Include="MySteamServiceWrapper.cs" />
<Compile Include="Patches\GameAnalyticsPatch.cs" />
<Compile Include="Patches\GameStatePatchShim.cs" />
<Compile Include="Patches\KeenLogPatch.cs" />
<Compile Include="Patches\ModsDownloadingPatch.cs" />
<Compile Include="Patches\ObjectFactoryInitPatch.cs" />
<Compile Include="Patches\PhysicsMemoryPatch.cs" />
<Compile Include="Patches\SessionDownloadPatch.cs" />
<Compile Include="Patches\TorchAsyncSaving.cs" />
<Compile Include="Plugins\PluginDependency.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Collections\KeyTree.cs" />
<Compile Include="Collections\RollingAverage.cs" />
<Compile Include="CommandLine.cs" />
<Compile Include="Commands\CategoryAttribute.cs" />
<Compile Include="Commands\Command.cs" />
<Compile Include="Commands\CommandAttribute.cs" />
<Compile Include="Commands\CommandModule.cs" />
<Compile Include="Commands\CommandContext.cs" />
<Compile Include="Commands\CommandManager.cs" />
<Compile Include="Commands\CommandTree.cs" />
<Compile Include="Commands\Permissions\PermissionAttribute.cs" />
<Compile Include="Commands\Permissions\PermissonsSystem.cs" />
<Compile Include="Commands\TorchCommands.cs" />
<Compile Include="Managers\EntityManager.cs" />
<Compile Include="Managers\FilesystemManager.cs" />
<Compile Include="Managers\Manager.cs" />
<Compile Include="Managers\NetworkManager\NetworkManager.cs" />
<Compile Include="Managers\MultiplayerManagerBase.cs" />
<Compile Include="Managers\UpdateManager.cs" />
<Compile Include="Persistent.cs" />
<Compile Include="Plugins\PluginManifest.cs" />
<Compile Include="Utils\ModItemUtils.cs" />
<Compile Include="Utils\SteamWorkshopTools\KeyValueExtensions.cs" />
<Compile Include="Utils\MiscExtensions.cs" />
<Compile Include="Utils\Reflected\ReflectedEventReplaceAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedEventReplacer.cs" />
<Compile Include="Utils\Reflected\ReflectedFieldInfoAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedGetterAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedLazyAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedMemberAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedMethodAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedMethodInfoAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedPropertyInfoAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedSetterAttribute.cs" />
<Compile Include="Utils\Reflected\ReflectedStaticMethodAttribute.cs" />
<Compile Include="Utils\Reflection.cs" />
<Compile Include="Utils\SteamWorkshopTools\WebAPI.cs" />
<Compile Include="Utils\SynchronizationExtensions.cs" />
<Compile Include="Utils\TorchAssemblyResolver.cs" />
<Compile Include="Utils\Reflected\ReflectedManager.cs" />
<Compile Include="Session\TorchSessionManager.cs" />
<Compile Include="TorchBase.cs" />
<Compile Include="TorchPluginBase.cs" />
<Compile Include="Session\TorchSession.cs" />
<Compile Include="Utils\TorchLauncher.cs" />
<Compile Include="Utils\SteamWorkshopTools\PublishedItemDetails.cs" />
<Compile Include="ViewModels\ModViewModel.cs" />
<Compile Include="Extensions\MyPlayerCollectionExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="ViewModels\PlayerViewModel.cs" />
<Compile Include="ViewModels\ViewModel.cs" />
<Compile Include="Plugins\PluginManager.cs" />
<Compile Include="ViewModels\PluginViewModel.cs" />
<Compile Include="Views\CollectionEditor.xaml.cs">
<Compile Update="Views\CollectionEditor.xaml.cs">
<DependentUpon>CollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\DictionaryEditor.xaml.cs">
<Compile Update="Views\DictionaryEditor.xaml.cs">
<DependentUpon>DictionaryEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\DisplayAttribute.cs" />
<Compile Include="Views\EmbeddedCollectionEditor.xaml.cs">
<Compile Update="Views\EmbeddedCollectionEditor.xaml.cs">
<DependentUpon>EmbeddedCollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\FlagsEditor.xaml.cs">
<Compile Update="Views\FlagsEditor.xaml.cs">
<DependentUpon>FlagsEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ObjectCollectionEditor.xaml.cs">
<Compile Update="Views\ObjectCollectionEditor.xaml.cs">
<DependentUpon>ObjectCollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ObjectEditor.xaml.cs">
<Compile Update="Views\ObjectEditor.xaml.cs">
<DependentUpon>ObjectEditor.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PropertyGrid.xaml.cs">
<Compile Update="Views\PropertyGrid.xaml.cs">
<DependentUpon>PropertyGrid.xaml</DependentUpon>
</Compile>
<Compile Include="VRageGame.cs" />
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Torch.API</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Page Include="Views\CollectionEditor.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\DictionaryEditor.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\EmbeddedCollectionEditor.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\FlagsEditor.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ObjectCollectionEditor.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ObjectEditor.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\PropertyGrid.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<Import Project="..\Torch.Mod\Torch.Mod.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\TransformOnBuild.targets" />
</Project>

View File

@@ -2,30 +2,16 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using ProtoBuf.Meta;
using Sandbox;
using Sandbox.Engine.Multiplayer;
using Sandbox.Engine.Networking;
using Sandbox.Engine.Platform.VideoMode;
using Sandbox.Engine.Utils;
using Sandbox.Game;
using Sandbox.Game.Multiplayer;
using Sandbox.Game.Screens.Helpers;
using Sandbox.Game.World;
using Sandbox.Graphics.GUI;
using Sandbox.ModAPI;
using SpaceEngineers.Game;
using SpaceEngineers.Game.GUI;
using Torch.API;
using Torch.API.Managers;
using Torch.API.ModAPI;
@@ -38,23 +24,9 @@ using Torch.Managers.PatchManager;
using Torch.Patches;
using Torch.Utils;
using Torch.Session;
using VRage;
using VRage.Collections;
using VRage.FileSystem;
using VRage.Game;
using VRage.Game.Common;
using VRage.Game.Components;
using VRage.Game.ObjectBuilder;
using VRage.Game.SessionComponents;
using VRage.GameServices;
using VRage.Library;
using VRage.ObjectBuilders;
using VRage.Platform.Windows;
using VRage.Plugins;
using VRage.Scripting;
using VRage.Steam;
using VRage.Utils;
using VRageRender;
namespace Torch
{
@@ -71,6 +43,7 @@ namespace Torch
PatchManager.AddPatchShim(typeof(GameStatePatchShim));
PatchManager.AddPatchShim(typeof(GameAnalyticsPatch));
PatchManager.AddPatchShim(typeof(KeenLogPatch));
PatchManager.AddPatchShim(typeof(XmlRootWriterPatch));
PatchManager.CommitInternal();
RegisterCoreAssembly(typeof(ITorchBase).Assembly);
RegisterCoreAssembly(typeof(TorchBase).Assembly);
@@ -134,10 +107,12 @@ namespace Torch
protected TorchBase(ITorchConfig config)
{
RegisterCoreAssembly(GetType().Assembly);
#pragma warning disable CS0618
if (Instance != null)
throw new InvalidOperationException("A TorchBase instance already exists.");
Instance = this;
#pragma warning restore CS0618
Config = config;
var versionString = Assembly.GetEntryAssembly()
@@ -153,7 +128,9 @@ namespace Torch
Managers = new DependencyManager();
#pragma warning disable CS0618
Plugins = new PluginManager(this);
#pragma warning restore CS0618
var sessionManager = new TorchSessionManager(this);
sessionManager.AddFactory((x) => Sync.IsServer ? new ChatManagerServer(this) : new ChatManagerClient(this));
@@ -165,7 +142,9 @@ namespace Torch
Managers.AddManager(new FilesystemManager(this));
Managers.AddManager(new UpdateManager(this));
Managers.AddManager(new EventManager(this));
#pragma warning disable CS0618
Managers.AddManager(Plugins);
#pragma warning restore CS0618
TorchAPI.Instance = this;
GameStateChanged += (game, state) =>

View File

@@ -67,15 +67,7 @@ namespace Torch.Utils
var identityId = grid.BigOwners[0];
if (MySession.Static.Players.IdentityIsNpc(identityId))
{
var identity = MySession.Static.Players.TryGetIdentity(identityId);
return identity.DisplayName;
}
else
{
return MyMultiplayer.Static.GetMemberName(MySession.Static.Players.TryGetSteamId(identityId));
}
return MySession.Static.Players.TryGetIdentity(identityId)?.DisplayName ?? "nobody";
}
}
}

View File

@@ -28,7 +28,9 @@ namespace Torch.Utils
}
catch
{
#pragma warning disable CS0618
return TorchBase.Instance.Config.UgcServiceType.ToString();
#pragma warning restore CS0618
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using Torch.Managers.PatchManager;
namespace Torch.Utils;
public static class PatchExtensions
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddPrefix(this MethodRewritePattern pattern, string methodName = "Prefix")
{
pattern.Prefixes.Add(GetPatchingMethod(methodName));
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddSuffix(this MethodRewritePattern pattern, string methodName = "Suffix")
{
pattern.Suffixes.Add(GetPatchingMethod(methodName));
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddTranspiler(this MethodRewritePattern pattern, string methodName = "Transpiler")
{
pattern.Transpilers.Add(GetPatchingMethod(methodName));
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddPostTranspiler(this MethodRewritePattern pattern, string methodName = "PostTranspiler")
{
pattern.PostTranspilers.Add(GetPatchingMethod(methodName));
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static MethodInfo GetPatchingMethod(string name)
{
if (new StackFrame(2, false).GetMethod()?.DeclaringType is { } type)
return type.GetMethod(name,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) ??
throw new MissingMethodException(type.FullName, name);
throw new InvalidOperationException("Unable to retrieve previous stackframe method");
}
}

View File

@@ -1,48 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Linq;
using NLog;
using SteamKit2;
namespace Torch.Utils.SteamWorkshopTools
{
public static class KeyValueExtensions
{
private static Logger Log = LogManager.GetLogger("SteamWorkshopService");
public static T GetValueOrDefault<T>(this KeyValue kv, string key)
{
kv.TryGetValueOrDefault<T>(key, out T result);
return result;
}
public static bool TryGetValueOrDefault<T>(this KeyValue kv, string key, out T typedValue)
{
var match = kv.Children?.Find((KeyValue item) => item.Name == key);
object result = default(T);
if (match == null)
{
typedValue = (T) result;
return false;
}
var value = match.Value ?? "";
try
{
var converter = TypeDescriptor.GetConverter(typeof(T));
result = converter.ConvertFromString(value);
typedValue = (T)result;
return true;
}
catch (NotSupportedException)
{
throw new Exception($"Unexpected Type '{typeof(T)}'!");
}
}
}
}

View File

@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Torch.Utils.SteamWorkshopTools
{
public class PublishedItemDetails
{
public ulong PublishedFileId;
public uint Views;
public uint Subscriptions;
public DateTime TimeUpdated;
public DateTime TimeCreated;
public string Description;
public string Title;
public string FileUrl;
public long FileSize;
public string FileName;
public ulong ConsumerAppId;
public ulong CreatorAppId;
public ulong Creator;
public string[] Tags;
}
}

View File

@@ -1,291 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Net;
using NLog;
using SteamKit2;
using System.Net.Http;
namespace Torch.Utils.SteamWorkshopTools
{
public class WebAPI
{
private static Logger Log = LogManager.GetLogger("SteamWorkshopService");
public const uint AppID = 244850U;
public string Username { get; private set; }
private string password;
public bool IsReady { get; private set; }
public bool IsRunning { get; private set; }
private TaskCompletionSource<bool> logonTaskCompletionSource;
private SteamClient steamClient;
private CallbackManager cbManager;
private SteamUser steamUser;
private static WebAPI _instance;
public static WebAPI Instance
{
get
{
return _instance ?? (_instance = new WebAPI());
}
}
private WebAPI()
{
steamClient = new SteamClient();
cbManager = new CallbackManager(steamClient);
IsRunning = true;
}
public async Task<bool> Logon(string user = "anonymous", string pw = "")
{
if (string.IsNullOrEmpty(user))
throw new ArgumentNullException("User can't be null!");
if (!user.Equals("anonymous") && !pw.Equals(""))
throw new ArgumentNullException("Password can't be null if user is not anonymous!");
Username = user;
password = pw;
logonTaskCompletionSource = new TaskCompletionSource<bool>();
steamUser = steamClient.GetHandler<SteamUser>();
cbManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
cbManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
cbManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
cbManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
Log.Info("Connecting to Steam...");
steamClient.Connect();
await logonTaskCompletionSource.Task;
return logonTaskCompletionSource.Task.Result;
}
public void CancelLogon()
{
logonTaskCompletionSource?.SetCanceled();
}
public async Task<Dictionary<ulong, PublishedItemDetails>> GetPublishedFileDetails(IEnumerable<ulong> workshopIds)
{
//if (!IsReady)
// throw new Exception("SteamWorkshopService not initialized!");
using (dynamic remoteStorage = SteamKit2.WebAPI.GetInterface("ISteamRemoteStorage"))
{
KeyValue allFilesDetails = null ;
remoteStorage.Timeout = TimeSpan.FromSeconds(30);
allFilesDetails = await Task.Run(delegate {
try
{
return remoteStorage.GetPublishedFileDetails1(
itemcount: workshopIds.Count(),
publishedfileids: workshopIds,
method: HttpMethod.Post);
// var ifaceArgs = new Dictionary<string, string>();
// ifaceArgs["itemcount"] = workshopIds.Count().ToString();
// no idea if that formatting is correct - in fact I get a 404 response
// ifaceArgs["publishedfileids"] = string.Join(",", workshopIds);
// return remoteStorage.Call(HttpMethod.Post, "GetPublishedFileDetails", args: ifaceArgs);
}
catch (HttpRequestException e)
{
Log.Error($"Fetching File Details failed: {e.Message}");
return null;
}
});
if (allFilesDetails == null)
return null;
//fileDetails = remoteStorage.Call(HttpMethod.Post, "GetPublishedFileDetails", 1, new Dictionary<string, string>() { { "itemcount", workshopIds.Count().ToString() }, { "publishedfileids", workshopIds.ToString() } });
var detailsList = allFilesDetails?.Children.Find((KeyValue kv) => kv.Name == "publishedfiledetails")?.Children;
var resultCount = allFilesDetails?.GetValueOrDefault<int>("resultcount");
if( detailsList == null || resultCount == null)
{
Log.Error("Received invalid data: ");
#if DEBUG
if(allFilesDetails != null)
PrintKeyValue(allFilesDetails);
return null;
#endif
}
if ( detailsList.Count != workshopIds.Count() || resultCount != workshopIds.Count())
{
Log.Error($"Received unexpected number of fileDetails. Expected: {workshopIds.Count()}, Received: {resultCount}");
return null;
}
var result = new Dictionary<ulong, PublishedItemDetails>();
for( int i = 0; i < resultCount; i++ )
{
var fileDetails = detailsList[i];
var tagContainer = fileDetails.Children.Find(item => item.Name == "tags");
List<string> tags = new List<string>();
if (tagContainer != null)
foreach (var tagKv in tagContainer.Children)
{
var tag = tagKv.Children.Find(item => item.Name == "tag")?.Value;
if( tag != null)
tags.Add(tag);
}
var publishedFileId = fileDetails.GetValueOrDefault<ulong>("publishedfileid");
result[publishedFileId] = new PublishedItemDetails()
{
PublishedFileId = publishedFileId,
Views = fileDetails.GetValueOrDefault<uint>("views"),
Subscriptions = fileDetails.GetValueOrDefault<uint>("subscriptions"),
TimeUpdated = DateTimeOffset.FromUnixTimeSeconds(fileDetails.GetValueOrDefault<long>("time_updated")).DateTime,
TimeCreated = DateTimeOffset.FromUnixTimeSeconds(fileDetails.GetValueOrDefault<long>("time_created")).DateTime,
Description = fileDetails.GetValueOrDefault<string>("description"),
Title = fileDetails.GetValueOrDefault<string>("title"),
FileUrl = fileDetails.GetValueOrDefault<string>("file_url"),
FileSize = fileDetails.GetValueOrDefault<long>("file_size"),
FileName = fileDetails.GetValueOrDefault<string>("filename"),
ConsumerAppId = fileDetails.GetValueOrDefault<ulong>("consumer_app_id"),
CreatorAppId = fileDetails.GetValueOrDefault<ulong>("creator_app_id"),
Creator = fileDetails.GetValueOrDefault<ulong>("creator"),
Tags = tags.ToArray()
};
}
return result;
}
}
[Obsolete("Space Engineers has transitioned to Steam's UGC api, therefore this method might not always work!")]
public async Task DownloadPublishedFile(PublishedItemDetails fileDetails, string dir, string name = null)
{
var fullPath = Path.Combine(dir, name);
if (name == null)
name = fileDetails.FileName;
var expectedSize = (fileDetails.FileSize == 0) ? -1 : fileDetails.FileSize;
using (var client = new WebClient())
{
try
{
var downloadTask = client.DownloadFileTaskAsync(fileDetails.FileUrl, Path.Combine(dir, name));
DateTime start = DateTime.Now;
for (int i = 0; i < 30; i++)
{
await Task.Delay(1000);
if (downloadTask.IsCompleted)
break;
}
if ( !downloadTask.IsCompleted )
{
client.CancelAsync();
throw new Exception("Timeout while attempting to downloading published workshop item!");
}
//var text = await client.DownloadStringTaskAsync(url);
//File.WriteAllText(fullPath, text);
}
catch (Exception e)
{
Log.Error("Failed to download workshop item! /n" +
$"{e.Message} - url: {fileDetails.FileUrl}, path: {Path.Combine(dir, name)}");
throw e;
}
}
}
class Printable
{
public KeyValue Data;
public int Offset;
public void Print()
{
Log.Info($"{new string(' ', Offset)}{Data.Name}: {Data.Value}");
}
}
private static void PrintKeyValue(KeyValue data)
{
var dataSet = new Stack<Printable>();
dataSet.Push(new Printable()
{
Data = data,
Offset = 0
});
while (dataSet.Count != 0)
{
var printable = dataSet.Pop();
foreach (var child in printable.Data.Children)
dataSet.Push(new Printable()
{
Data = child,
Offset = printable.Offset + 2
});
printable.Print();
}
}
#region CALLBACKS
private void OnConnected( SteamClient.ConnectedCallback callback)
{
Log.Info("Connected to Steam! Logging in '{0}'...", Username);
if( Username == "anonymous" )
steamUser.LogOnAnonymous();
else
steamUser.LogOn(new SteamUser.LogOnDetails
{
Username = Username,
Password = password
});
}
private void OnDisconnected( SteamClient.DisconnectedCallback callback )
{
Log.Info("Disconnected from Steam");
IsReady = false;
IsRunning = false;
}
private void OnLoggedOn( SteamUser.LoggedOnCallback callback )
{
if( callback.Result != EResult.OK )
{
string msg;
if( callback.Result == EResult.AccountLogonDenied )
{
msg = "Unable to logon to Steam: This account is Steamguard protected.";
Log.Warn(msg);
logonTaskCompletionSource.SetException(new Exception(msg));
IsRunning = false;
return;
}
msg = $"Unable to logon to Steam: {callback.Result} / {callback.ExtendedResult}";
Log.Warn(msg);
logonTaskCompletionSource.SetException(new Exception(msg));
IsRunning = false;
return;
}
IsReady = true;
Log.Info("Successfully logged on!");
logonTaskCompletionSource.SetResult(true);
}
private void OnLoggedOff( SteamUser.LoggedOffCallback callback )
{
IsReady = false;
Log.Info($"Logged off of Steam: {callback.Result}");
}
#endregion
}
}

View File

@@ -4,50 +4,40 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;
using Torch.API;
namespace Torch.Utils
{
public class TorchLauncher
{
private const string TorchKey = "TorchWrapper";
private static readonly Dictionary<string, string> Assemblies = new Dictionary<string, string>();
public static bool IsTorchWrapped()
public static void Launch(params string[] binaryPaths)
{
return AppDomain.CurrentDomain.GetData(TorchKey) != null;
foreach (var file in binaryPaths.SelectMany(path => Directory.EnumerateFiles(path, "*.dll")))
{
try
{
var name = AssemblyName.GetAssemblyName(file);
Assemblies.TryAdd(name.Name ?? name.FullName.Split(',')[0], file);
}
catch (BadImageFormatException)
{
// if we are trying to load native image
}
}
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
}
public static void Launch(string entryPoint, string[] args, params string[] binaryPaths)
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
if (IsTorchWrapped())
throw new Exception("Can't wrap torch twice");
string exePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)?.ToLower().Replace('/', '\\');
if (exePath == null)
throw new ArgumentException("Unable to determine executing assembly's path");
var allPaths = new HashSet<string> { exePath };
foreach (string other in binaryPaths)
allPaths.Add(other.ToLower().Replace('/', '\\'));
var pathPrefix = StringUtils.CommonPrefix(allPaths);
#pragma warning disable 618
AppDomain.CurrentDomain.AppendPrivatePath(string.Join(Path.PathSeparator.ToString(), allPaths));
#pragma warning restore 618
AppDomain.CurrentDomain.SetData(TorchKey, true);
AppDomain.CurrentDomain.ExecuteAssemblyByName(entryPoint, args);
return;
// this would be way better but HAVOK IS UNMANAGED :clang:
// exclude application base from probing
// var setup = new AppDomainSetup
// {
// ApplicationBase = pathPrefix.ToString(),
// PrivateBinPathProbe = "",
// PrivateBinPath = string.Join(";", allPaths)
// };
// AppDomain domain = AppDomain.CreateDomain($"TorchDomain-{Assembly.GetEntryAssembly().GetName().Name}-{new Random().Next():X}", null, setup);
// domain.SetData(TorchKey, true);
// domain.ExecuteAssemblyByName(entryPoint, args);
// AppDomain.Unload(domain);
var name = args.Name;
return Assemblies.TryGetValue(name[..name.IndexOf(',')], out var path) ? Assembly.LoadFrom(path) : null;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sandbox.Engine.Networking;
using VRage.Game;
using VRage.GameServices;
namespace Torch.Utils;
public static class WorkshopQueryUtils
{
// TODO: Maybe later
public static async Task<List<MyWorkshopItem>> GetModsInfo(IEnumerable<MyObjectBuilder_Checkpoint.ModItem> mods)
{
throw new NotImplementedException();
/*return (await Task.WhenAll(mods.GroupBy(b => b.PublishedServiceName)
.Select(b => GetModsInfo(b.Key, b.Select(c => c.PublishedFileId)))))
.SelectMany(b => b).ToList();*/
}
public static Task<MyWorkshopItem> GetModInfo(MyObjectBuilder_Checkpoint.ModItem item)
{
throw new NotImplementedException();
/*var query = MyGameService.CreateWorkshopQuery(item.PublishedServiceName);
query.ItemIds = new() {item.PublishedFileId};
var source = new TaskCompletionSource<MyWorkshopItem>();
query.QueryCompleted += result =>
{
if (result == MyGameServiceCallResult.OK)
{
source.SetResult(query.Items[0]);
return;
}
source.SetException(new Exception($"Workshop query resulted in {result}"));
};
query.Run();
return source.Task;*/
}
private static Task<List<MyWorkshopItem>> GetModsInfo(string serviceName, IEnumerable<ulong> ids)
{
var query = MyGameService.CreateWorkshopQuery(serviceName);
query.ItemIds = ids.ToList();
var source = new TaskCompletionSource<List<MyWorkshopItem>>();
query.QueryCompleted += result =>
{
if (result == MyGameServiceCallResult.OK)
{
source.SetResult(query.Items);
return;
}
source.SetException(new Exception($"Workshop query resulted in {result}"));
};
query.Run();
return source.Task;
}
}

View File

@@ -50,18 +50,18 @@ namespace Torch
#pragma warning disable 649
[ReflectedGetter(Name = "m_plugins", Type = typeof(MyPlugins))]
private static readonly Func<List<IPlugin>> _getVRagePluginList;
private static Func<List<IPlugin>> _getVRagePluginList;
[ReflectedGetter(Name = "Static", TypeName = "Sandbox.Game.Audio.MyMusicController, Sandbox.Game")]
private static readonly Func<object> _getMusicControllerStatic;
private static Func<object> _getMusicControllerStatic;
[ReflectedSetter(Name = "Static", TypeName = "Sandbox.Game.Audio.MyMusicController, Sandbox.Game")]
private static readonly Action<object> _setMusicControllerStatic;
private static Action<object> _setMusicControllerStatic;
[ReflectedMethod(Name = "Unload", TypeName = "Sandbox.Game.Audio.MyMusicController, Sandbox.Game")]
private static readonly Action<object> _musicControllerUnload;
private static Action<object> _musicControllerUnload;
// [ReflectedGetter(Name = "UpdateLayerDescriptors", Type = typeof(MyReplicationServer))]
// private static readonly Func<MyReplicationServer.UpdateLayerDesc[]> _layerSettings;
@@ -168,7 +168,9 @@ namespace Torch
//Type.GetType("VRage.Steam.MySteamService, VRage.Steam").GetProperty("IsActive").GetSetMethod(true).Invoke(service, new object[] {SteamAPI.Init()});
_log.Info("Initializing network services");
#pragma warning disable CS0618
var isEos = TorchBase.Instance.Config.UgcServiceType == UGCServiceType.EOS;
#pragma warning restore CS0618
if (isEos)
{
@@ -334,8 +336,8 @@ namespace Torch
#pragma warning disable 649
[ReflectedMethod(Name = "StartServer")]
private static Action<MySession, MyMultiplayerBase> _hostServerForSession;
// [ReflectedMethod(Name = "StartServer")]
// private static Action<MySession, MyMultiplayerBase> _hostServerForSession;
#pragma warning restore 649
private void DoLoadSession(string sessionPath)

View File

@@ -15,8 +15,7 @@ namespace Torch.ViewModels
{
public ulong SteamId { get; }
public string Name { get; }
private ConnectionState _state;
public ConnectionState State { get => _state; set { _state = value; OnPropertyChanged(); } }
public ConnectionState State { get; set; }
public MyPromoteLevel PromoteLevel => MySession.Static.GetUserPromoteLevel(SteamId);
public string PromotedName
@@ -24,10 +23,7 @@ namespace Torch.ViewModels
get
{
var p = PromoteLevel;
if (p <= MyPromoteLevel.None)
return Name;
else
return $"{Name} ({p})";
return p <= MyPromoteLevel.None ? Name : $"{Name} ({p})";
}
}

View File

@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using PropertyChanged;
namespace Torch
{
@@ -27,6 +28,7 @@ namespace Torch
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
[SuppressPropertyChangedWarnings]
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler collectionChanged = CollectionChanged;

Some files were not shown because too many files have changed in this diff Show More