Files
Torch/Torch/Patches/ScriptCompilerPatch.cs
zznty cae3d9ad8c
All checks were successful
Release / Get Version (push) Successful in 8s
Release / Build and Publish Nuget (Torch.API) (push) Successful in 59s
Release / Build and Publish Nuget (Torch) (push) Successful in 1m13s
Release / Build and Publish Nuget (Torch.Server) (push) Successful in 1m22s
Release / Build and Publish Package (push) Successful in 1m54s
net 9
2025-01-13 01:47:52 +07:00

118 lines
5.5 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
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 = [typeof(MyWhitelistTarget), typeof(INamespaceSymbol), typeof(Type)])]
private static MethodInfo _register1Method;
[ReflectedMethodInfo(typeof(MyScriptWhitelist), "Register", Parameters = [typeof(MyWhitelistTarget), typeof(ITypeSymbol), typeof(Type)])]
private static MethodInfo _register2Method;
[ReflectedMethodInfo(null, "AllowMembers", TypeName = "VRage.Scripting.MyScriptWhitelist+MyWhitelistBatch, VRage.Scripting")]
private static MethodInfo _allowMembersMethod;
[ReflectedMethodInfo(null, "ResolveTypeSymbol", TypeName = "VRage.Scripting.MyScriptWhitelist+Batch, VRage.Scripting")]
private static MethodInfo _resolveTypeSymbolMethod;
public static void Patch(PatchContext context)
{
context.GetPattern(typeof(MyScriptWhitelist).GetConstructor([typeof(MyScriptCompiler)]))
.AddPrefix(nameof(WhitelistCtorPrefix));
context.GetPattern(Info.OfMethod("VRage.Scripting", "VRage.Scripting.MyVRageScriptingInternal", "Initialize"))
.AddPrefix(nameof(InitializePrefix));
context.GetPattern(_allowMembersMethod).AddPrefix(nameof(AllowMembersPrefix));
var harmony = new Harmony(nameof(ScriptCompilerPatch));
harmony.Patch(_allowMembersMethod, finalizer: new(typeof(ScriptCompilerPatch), nameof(RegisterFinalizer)));
harmony.Patch(_register1Method, finalizer: new(typeof(ScriptCompilerPatch), nameof(RegisterFinalizer)));
harmony.Patch(_register2Method, finalizer: new(typeof(ScriptCompilerPatch), nameof(RegisterFinalizer)));
harmony.Patch(_resolveTypeSymbolMethod, finalizer: new(typeof(ScriptCompilerPatch), nameof(RegisterFinalizer)));
}
private static void WhitelistCtorPrefix(MyScriptCompiler scriptCompiler)
{
var baseDir = new FileInfo(typeof(Type).Assembly.Location).DirectoryName!;
var binDir =
#if DEBUG
baseDir;
#else
Path.Join(AppContext.BaseDirectory, "torch64");
#endif
scriptCompiler.AddReferencedAssemblies(
typeof(Type).Assembly.Location,
typeof(LinkedList<>).Assembly.Location,
typeof(Regex).Assembly.Location,
typeof(Enumerable).Assembly.Location,
typeof(ConcurrentBag<>).Assembly.Location,
typeof(ImmutableArray).Assembly.Location,
typeof(PropertyChangedEventArgs).Assembly.Location,
typeof(TypeConverter).Assembly.Location,
typeof(System.Diagnostics.TraceSource).Assembly.Location,
typeof(System.Security.Policy.Evidence).Assembly.Location,
Path.Join(binDir, "System.Xml.ReaderWriter.dll"),
Path.Join(MyFileSystem.ExePath, "ProtoBuf.Net.dll"),
Path.Join(MyFileSystem.ExePath, "ProtoBuf.Net.Core.dll"),
Path.Join(binDir, "netstandard.dll"),
Path.Join(baseDir, "System.Runtime.dll"),
Path.Join(MyFileSystem.ExePath, "Sandbox.Game.dll"),
Path.Join(MyFileSystem.ExePath, "Sandbox.Common.dll"),
Path.Join(MyFileSystem.ExePath, "Sandbox.Graphics.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.Library.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.Math.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.Game.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.Render.dll"),
Path.Join(MyFileSystem.ExePath, "VRage.Input.dll"),
Path.Join(MyFileSystem.ExePath, "SpaceEngineers.ObjectBuilders.dll"),
Path.Join(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);
using var batch = MyScriptCompiler.Static.Whitelist.OpenBatch();
batch.AllowTypes(MyWhitelistTarget.ModApi, typeof(ConcurrentQueue<>));
batch.AllowNamespaceOfTypes(MyWhitelistTarget.Both, typeof(ImmutableArray));
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 Exception RegisterFinalizer(Exception __exception)
{
return __exception is MyWhitelistException ? null : __exception;
}
}
}