Compare commits

..

8 Commits

Author SHA1 Message Date
zznty
cf5c00ce0e fixed steamcmd path does not follow TORCH_GAME_PATH env variable 2022-03-07 13:25:38 +07:00
zznty
9c185d5577 fixed mods not being properly cleared from bulk edit
fixed bulk edit crash if input format is invalid
2022-03-05 20:19:01 +07:00
LTP
8b6c401531 fixed plugin dependencies resolution 2022-03-03 22:30:55 +07:00
z__
92db8994ef fixed ScriptCompilerPatch 2022-02-28 17:16:23 +07:00
z__
aee36661fd fixed keen log indent 2022-02-28 17:15:33 +07:00
z__
feda84fac8 Merge remote-tracking branch 'zznty/master' 2022-02-18 17:27:52 +07:00
z__
2503cd6372 fixed NRE in edit roles button 2022-02-18 17:27:40 +07:00
zznty
f321034eeb Update README.md 2022-02-16 10:08:20 +07:00
11 changed files with 140 additions and 83 deletions

View File

@@ -1,4 +1,3 @@
[![Discord](https://discordapp.com/api/guilds/929141809769226271/widget.png)](https://discord.gg/trK6sYdcNE)
[![Build status](https://ci.appveyor.com/api/projects/status/us64kmwshl50f5a3/branch/master?svg=true)](https://ci.appveyor.com/project/zznty/torch/branch/master)
# What is Torch?
@@ -17,6 +16,10 @@ Torch is the successor to SE Server Extender and gives server admins the tools t
* .NET 6.0 runtime
* Additional options & features
### Discord
If you have any questions or issues please join our [discord](https://discord.gg/UyYFSe3TyQ)
### Installation
* Unzip the Torch release into its own directory and run the executable. It will automatically download the SE DS and generate the other necessary files.

View File

@@ -29,12 +29,7 @@ namespace Torch.Server
private const string STEAMCMD_DIR = "steamcmd";
private const string STEAMCMD_ZIP = "temp.zip";
private static readonly string STEAMCMD_EXE = "steamcmd.exe";
private static readonly string RUNSCRIPT_FILE = "runscript.txt";
private const string RUNSCRIPT = @"force_install_dir ../
login anonymous
app_update 298740
quit";
private const string STEAMCMD_ARGS = "+force_install_dir \"{0}\" +login anonymous +app_update 298740 +quit";
private TorchServer _server;
internal Persistent<TorchConfig> ConfigPersistent { get; }
@@ -140,10 +135,6 @@ quit";
Directory.CreateDirectory(path);
}
var runScriptPath = Path.Combine(path, RUNSCRIPT_FILE);
if (!File.Exists(runScriptPath))
File.WriteAllText(runScriptPath, RUNSCRIPT);
var steamCmdExePath = Path.Combine(path, STEAMCMD_EXE);
if (!File.Exists(steamCmdExePath))
{
@@ -166,8 +157,9 @@ quit";
}
log.Info("Checking for DS updates.");
var steamCmdProc = new ProcessStartInfo(steamCmdExePath, "+runscript runscript.txt")
var steamCmdProc = new ProcessStartInfo(steamCmdExePath)
{
Arguments = string.Format(STEAMCMD_ARGS, Environment.GetEnvironmentVariable("TORCH_GAME_PATH") ?? "../"),
WorkingDirectory = path,
UseShellExecute = false,
RedirectStandardOutput = true,

View File

@@ -140,12 +140,6 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Update="TorchService.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="TorchServiceInstaller.cs">
<SubType>Component</SubType>
</Compile>
<Compile Remove="ServerManager.cs" />
<Compile Remove="ViewModels\SessionSettingsViewModel1.cs" />
<Compile Remove="Views\WorldSelectControl.xaml.cs" />

View File

@@ -144,22 +144,17 @@ namespace Torch.Server.Views
{
//var w = new RoleEditor(_instanceManager.DedicatedConfig.SelectedWorld);
//w.Show();
var d = new RoleEditor();
var w = _instanceManager.DedicatedConfig.SelectedWorld;
if(w.Checkpoint.PromotedUsers == null) {
w.Checkpoint.PromotedUsers = new VRage.Serialization.SerializableDictionary<ulong, MyPromoteLevel>();
}
if (w == null)
if (w is null)
{
MessageBox.Show("A world is not selected.");
return;
}
if (w.Checkpoint.PromotedUsers == null)
w.Checkpoint.PromotedUsers = new SerializableDictionary<ulong, MyPromoteLevel>();
d.Edit(w.Checkpoint.PromotedUsers.Dictionary);
w.Checkpoint.PromotedUsers ??= new();
new RoleEditor().Edit(w.Checkpoint.PromotedUsers.Dictionary);
_instanceManager.DedicatedConfig.Administrators = w.Checkpoint.PromotedUsers.Dictionary.Where(k => k.Value >= MyPromoteLevel.Admin).Select(k => k.Key.ToString()).ToList();
}
}

View File

@@ -130,17 +130,17 @@ namespace Torch.Server.Views
//blocking
editor.Edit<string>(idList, "Mods");
modList.RemoveAll(m =>
{
var mod = m.ToString();
return idList.Any(mod.Equals);
});
modList.Clear();
modList.AddRange(idList.Select(id =>
{
var info = new ModItemInfo(ModItemUtils.Create(id));
if (!ModItemUtils.TryParse(id, out var item))
return null;
var info = new ModItemInfo(item);
tasks.Add(Task.Run(info.UpdateModInfoAsync));
return info;
}));
}).Where(b => b is not null));
_instanceManager.DedicatedConfig.Mods.Clear();
foreach (var mod in modList)
_instanceManager.DedicatedConfig.Mods.Add(mod);

View File

@@ -103,27 +103,27 @@ namespace Torch.Patches
private static bool PrefixWriteLine(MyLog __instance, string msg)
{
if (__instance.LogEnabled && _log.IsDebugEnabled)
_log.Debug($"{" ".PadRight(3 * GetIndentByCurrentThread())}{msg}");
_log.Debug($"{string.Empty.PadRight(3 * GetIndentByCurrentThread(), ' ')}{msg}");
return false;
}
private static bool PrefixWriteLineConsole(MyLog __instance, string msg)
{
if (__instance.LogEnabled && _log.IsInfoEnabled)
_log.Info($"{" ".PadRight(3 * GetIndentByCurrentThread())}{msg}");
_log.Info($"{string.Empty.PadRight(3 * GetIndentByCurrentThread(), ' ')}{msg}");
return false;
}
private static bool PrefixAppendToClosedLog(MyLog __instance, string text)
{
if (__instance.LogEnabled && _log.IsDebugEnabled)
_log.Debug($"{" ".PadRight(3 * GetIndentByCurrentThread())}{text}");
_log.Debug($"{string.Empty.PadRight(3 * GetIndentByCurrentThread(), ' ')}{text}");
return false;
}
private static bool PrefixWriteLineOptions(MyLog __instance, string message, LoggingOptions option)
{
if (__instance.LogEnabled && __instance.LogFlag(option) && _log.IsDebugEnabled)
_log.Info($"{" ".PadRight(3 * GetIndentByCurrentThread())}{message}");
_log.Info($"{string.Empty.PadRight(3 * GetIndentByCurrentThread(), ' ')}{message}");
return false;
}
@@ -145,7 +145,7 @@ namespace Torch.Patches
return false;
// ReSharper disable once TemplateIsNotCompileTimeConstantProblem
_log.Log(new(LogLevelFor(severity), _log.Name, $"{" ".PadRight(3 * GetIndentByCurrentThread())}{string.Format(format, args)}"));
_log.Log(new(LogLevelFor(severity), _log.Name, $"{string.Empty.PadRight(3 * GetIndentByCurrentThread(), ' ')}{string.Format(format, args)}"));
return false;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -12,7 +11,6 @@ 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;
@@ -42,10 +40,14 @@ namespace Torch.Patches
context.GetPattern(Register2Method).AddTranspiler(nameof(RegisterTranspiler));
}
private static void WhitelistCtorPrefix(MyScriptCompiler scriptCompiler)
private static void WhitelistCtorPrefix(MyScriptCompiler scriptCompiler, MyScriptWhitelist __instance)
{
var basePath = new FileInfo(typeof(object).Assembly.Location).DirectoryName!;
scriptCompiler.AddReferencedAssemblies(
typeof(ValueType).Assembly.Location,
Path.Combine(basePath, "netstandard.dll"),
Path.Combine(basePath, "mscorlib.dll"),
Path.Combine(basePath, "System.Runtime.dll"),
typeof(LinkedList<>).Assembly.Location,
typeof(Regex).Assembly.Location,
typeof(Enumerable).Assembly.Location,
@@ -55,6 +57,7 @@ namespace Torch.Patches
typeof(TypeConverter).Assembly.Location,
typeof(System.Diagnostics.TraceSource).Assembly.Location,
typeof(ProtoBuf.Meta.RuntimeTypeModel).Assembly.Location,
typeof(ProtoBuf.ProtoMemberAttribute).Assembly.Location,
Path.Combine(MyFileSystem.ExePath, "Sandbox.Game.dll"),
Path.Combine(MyFileSystem.ExePath, "Sandbox.Common.dll"),
Path.Combine(MyFileSystem.ExePath, "Sandbox.Graphics.dll"),
@@ -73,6 +76,9 @@ namespace Torch.Patches
MyModWatchdog.Init(updateThread);
MyScriptCompiler.Static.AddImplicitIngameNamespacesFromTypes(referencedTypes);
MyScriptCompiler.Static.AddConditionalCompilationSymbols(symbols);
using var batch = MyScriptCompiler.Static.Whitelist.OpenBatch();
// Dict and queue in different assemblies, microsoft being microsoft
batch.AllowNamespaceOfTypes(MyWhitelistTarget.ModApi, typeof(ConcurrentQueue<>));
return false;
}

View File

@@ -1,34 +1,52 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
using NLog;
namespace Torch.Plugins;
internal static class AssemblyRewriter
{
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();
private static readonly IAssemblyResolver Resolver;
private static readonly ZipResolver _zipResolver;
private static readonly DefaultAssemblyResolver _defaultResolver;
static AssemblyRewriter()
{
var resolver = new DefaultAssemblyResolver();
Resolver = resolver;
resolver.AddSearchDirectory(Directory.GetCurrentDirectory());
resolver.AddSearchDirectory(Path.Combine(Directory.GetCurrentDirectory(), "DedicatedServer64"));
_defaultResolver = new();
_zipResolver = new(_defaultResolver);
_defaultResolver.AddSearchDirectory(Directory.GetCurrentDirectory());
_defaultResolver.AddSearchDirectory(Path.Combine(Directory.GetCurrentDirectory(), "DedicatedServer64"));
}
public static Assembly ProcessWeavers(this Stream stream)
public static Assembly ProcessWeavers(this Stream stream, ZipArchive archive)
{
_zipResolver.Archive = archive;
using var assStream = new MemoryStream();
stream.CopyTo(assStream);
assStream.Position = 0;
using var module = ModuleDefinition.ReadModule(assStream, new()
var ass = ProcessInternal(assStream, _zipResolver);
_zipResolver.Archive = null;
return ass;
}
public static Assembly ProcessWeavers(this Stream stream, string path)
{
_defaultResolver.AddSearchDirectory(path);
using var assStream = new MemoryStream();
stream.CopyTo(assStream);
assStream.Position = 0;
var ass = ProcessInternal(assStream, _defaultResolver);
_defaultResolver.RemoveSearchDirectory(path);
return ass;
}
private static Assembly ProcessInternal(Stream inputStream, IAssemblyResolver resolver)
{
using var module = ModuleDefinition.ReadModule(inputStream, new()
{
AssemblyResolver = Resolver
AssemblyResolver = _zipResolver
});
foreach (var fieldDefinition in FindAllToRewrite(module))
{
@@ -47,4 +65,40 @@ internal static class AssemblyRewriter
private static bool HasValidAttributes(FieldDefinition definition) =>
definition.CustomAttributes.Any(b => b.AttributeType.Name.Contains("Reflected") || b.AttributeType.Name == "DependencyAttribute");
private class ZipResolver : IAssemblyResolver
{
private readonly IAssemblyResolver _fallbackResolver;
public ZipArchive Archive { get; set; }
public ZipResolver(IAssemblyResolver fallbackResolver)
{
_fallbackResolver = fallbackResolver;
}
public void Dispose()
{
_fallbackResolver.Dispose();
}
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
return Resolve(name, new());
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
var fileName = $"{name.Name}.dll";
if (Archive.Entries.FirstOrDefault(entry => entry.Name == fileName) is not { } archiveEntry)
return _fallbackResolver.Resolve(name, parameters);
using var stream = archiveEntry.Open();
using var memStream = new MemoryStream();
stream.CopyTo(memStream);
memStream.Position = 0;
return AssemblyDefinition.ReadAssembly(memStream, parameters);
}
}
}

View File

@@ -360,7 +360,7 @@ namespace Torch.Managers
using var stream = entry.Open();
assemblies.Add(stream.ProcessWeavers());
assemblies.Add(stream.ProcessWeavers(zipFile));
}
}
else
@@ -378,7 +378,7 @@ namespace Torch.Managers
// continue;
using var stream = File.OpenRead(file);
assemblies.Add(stream.ProcessWeavers());
assemblies.Add(stream.ProcessWeavers(item.Path));
}

View File

@@ -122,31 +122,6 @@
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Update="Views\CollectionEditor.xaml.cs">
<DependentUpon>CollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\DictionaryEditor.xaml.cs">
<DependentUpon>DictionaryEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\EmbeddedCollectionEditor.xaml.cs">
<DependentUpon>EmbeddedCollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\FlagsEditor.xaml.cs">
<DependentUpon>FlagsEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\ObjectCollectionEditor.xaml.cs">
<DependentUpon>ObjectCollectionEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\ObjectEditor.xaml.cs">
<DependentUpon>ObjectEditor.xaml</DependentUpon>
</Compile>
<Compile Update="Views\PropertyGrid.xaml.cs">
<DependentUpon>PropertyGrid.xaml</DependentUpon>
</Compile>
<Compile Include="..\Versioning\AssemblyVersion.cs" Link="Properties/AssemblyVersion.cs" />
<Compile Remove="Commands\Permissions\PermissionManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Torch.API\Torch.API.csproj" />
</ItemGroup>

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Sandbox.Engine.Networking;
using Torch.API;
@@ -19,6 +20,43 @@ namespace Torch.Utils
return new MyObjectBuilder_Checkpoint.ModItem(ulong.Parse(arr[0]), arr[1]);
}
public static bool TryParse(string str, out MyObjectBuilder_Checkpoint.ModItem item)
{
item = default;
var arr = str.Split('-');
if (arr.Length is 0 or > 2)
return false;
if (!ulong.TryParse(arr[0], out var id))
return false;
if (arr.Length == 1 || !TryParseServiceName(arr[1], out var serviceName))
serviceName = GetDefaultServiceName();
item = new(id, serviceName);
return true;
}
public static bool TryParseServiceName(string str, out string serviceName)
{
if (str.Equals("steam", StringComparison.OrdinalIgnoreCase))
{
serviceName = "Steam";
return true;
}
if (str.Equals("mod.io", StringComparison.OrdinalIgnoreCase) ||
str.Equals("eos", StringComparison.OrdinalIgnoreCase))
{
serviceName = "mod.io";
return true;
}
serviceName = null;
return false;
}
//because KEEEN!
public static string GetDefaultServiceName()
{