feature: first
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 2m47s
Build / Build Nuget package (CringePlugins) (push) Successful in 5m31s
Build / Build Nuget package (NuGet) (push) Successful in 6m2s
Build / Build Nuget package (SharedCringe) (push) Successful in 7m25s
Build / Build Launcher (push) Successful in 9m11s
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 2m47s
Build / Build Nuget package (CringePlugins) (push) Successful in 5m31s
Build / Build Nuget package (NuGet) (push) Successful in 6m2s
Build / Build Nuget package (SharedCringe) (push) Successful in 7m25s
Build / Build Launcher (push) Successful in 9m11s
This commit is contained in:
108
CringeLauncher/Utils/ExceptionFormatter.cs
Normal file
108
CringeLauncher/Utils/ExceptionFormatter.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace CringeLauncher.Utils;
|
||||
|
||||
public static class ExceptionFormatter
|
||||
{
|
||||
private static readonly AccessTools.FieldRef<Exception, string> StackTraceField = AccessTools.FieldRefAccess<Exception, string>("_remoteStackTraceString");
|
||||
|
||||
public static void FormatStackTrace(this Exception exception)
|
||||
{
|
||||
var stackTrace = new StackTrace(exception, true);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var i = 0;
|
||||
while (stackTrace.GetFrame(i++) is { } frame)
|
||||
{
|
||||
var method = frame.GetMethod();
|
||||
if (method is null)
|
||||
continue;
|
||||
|
||||
sb.Append("at ");
|
||||
if (method.DeclaringType is { } declaringType &&
|
||||
AssemblyLoadContext.GetLoadContext(declaringType.Assembly) is { } assemblyLoadContext)
|
||||
sb.Append(assemblyLoadContext).Append("//");
|
||||
|
||||
if (method.IsStatic)
|
||||
sb.Append("static ");
|
||||
|
||||
if (method is MethodInfo methodInfo)
|
||||
sb.Append(methodInfo.ReturnType, false);
|
||||
else
|
||||
sb.Append("new");
|
||||
|
||||
sb.Append(' ');
|
||||
|
||||
if (method.DeclaringType is null)
|
||||
sb.Append("<null>");
|
||||
else
|
||||
sb.Append(method.DeclaringType, true);
|
||||
|
||||
if (method is MethodInfo)
|
||||
{
|
||||
sb.Append('.');
|
||||
sb.Append(method.Name);
|
||||
}
|
||||
|
||||
if (method.ContainsGenericParameters)
|
||||
sb.Append(method.GetGenericArguments(), false);
|
||||
|
||||
sb.Append('(');
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
for (var j = 0; j < parameters.Length; j++)
|
||||
{
|
||||
sb.Append(parameters[j].ParameterType, false);
|
||||
if (!string.IsNullOrEmpty(parameters[j].Name))
|
||||
sb.Append(' ').Append(parameters[j].Name);
|
||||
if (j < parameters.Length - 1)
|
||||
sb.Append(", ");
|
||||
}
|
||||
|
||||
sb.Append(')');
|
||||
|
||||
if (frame.GetFileName() is { } fileName)
|
||||
{
|
||||
sb.Append(" in ").Append(fileName).Append('(').Append(frame.GetFileLineNumber()).Append(':').Append(frame.GetFileColumnNumber()).Append(')');
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
ref var stackTraceString = ref StackTraceField(exception);
|
||||
|
||||
stackTraceString = sb.ToString();
|
||||
}
|
||||
|
||||
private static StringBuilder Append(this StringBuilder sb, Type type, bool fullName = false)
|
||||
{
|
||||
if (fullName && !string.IsNullOrEmpty(type.Namespace))
|
||||
sb.Append(type.Namespace).Append('.');
|
||||
sb.Append(type.Name);
|
||||
if (type.ContainsGenericParameters)
|
||||
sb.Append(type.GetGenericArguments(), fullName);
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static StringBuilder Append(this StringBuilder sb, Type[] genericArguments, bool fullName)
|
||||
{
|
||||
sb.Append('<');
|
||||
for (var i = 0; i < genericArguments.Length; i++)
|
||||
{
|
||||
sb.Append(genericArguments[i], fullName);
|
||||
if (i < genericArguments.Length - 1)
|
||||
sb.Append(", ");
|
||||
}
|
||||
|
||||
sb.Append('>');
|
||||
|
||||
return sb;
|
||||
}
|
||||
}
|
19
CringeLauncher/Utils/MethodTools.cs
Normal file
19
CringeLauncher/Utils/MethodTools.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace CringeLauncher.Utils;
|
||||
|
||||
public static class MethodTools
|
||||
{
|
||||
public static MethodInfo AsyncMethodBody(MethodInfo method)
|
||||
{
|
||||
var (_, operand) = PatchProcessor.ReadMethodBody(method).First();
|
||||
|
||||
if (operand is not LocalVariableInfo localVar)
|
||||
throw new InvalidOperationException($"Method {method.FullDescription()} does not contain a valid async state machine");
|
||||
|
||||
return AccessTools.Method(localVar.LocalType, "MoveNext") ??
|
||||
throw new InvalidOperationException(
|
||||
$"Async State machine of method {method.FullDescription()} does not contain a valid MoveNext method");
|
||||
}
|
||||
}
|
85
CringeLauncher/Utils/ThreadPoolScheduler.cs
Normal file
85
CringeLauncher/Utils/ThreadPoolScheduler.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using HarmonyLib;
|
||||
using Havok;
|
||||
using ParallelTasks;
|
||||
using CringeTask = ParallelTasks.Task;
|
||||
|
||||
namespace CringeLauncher.Utils;
|
||||
|
||||
public class ThreadPoolScheduler : IWorkScheduler
|
||||
{
|
||||
public void Schedule(CringeTask item)
|
||||
{
|
||||
ThreadPool.UnsafeQueueUserWorkItem(new ThreadPoolWorkItemTask(item), false);
|
||||
}
|
||||
|
||||
public bool WaitForTasksToFinish(TimeSpan waitTimeout) => true;
|
||||
|
||||
public void ScheduleOnEachWorker(Action action)
|
||||
{
|
||||
}
|
||||
|
||||
public int ReadAndClearExecutionTime() => 0;
|
||||
|
||||
public void SuspendThreads(TimeSpan waitTimeout)
|
||||
{
|
||||
}
|
||||
|
||||
public void ResumeThreads()
|
||||
{
|
||||
}
|
||||
|
||||
public int ThreadCount { get; } = ThreadPool.ThreadCount;
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
internal class KeenThreadingPatch
|
||||
{
|
||||
private static MethodBase TargetMethod()
|
||||
{
|
||||
var type = Type.GetType(
|
||||
"VRage.Render11.Resources.Textures.MyTextureStreamingManager+MyStreamedTextureBase, VRage.Render11");
|
||||
|
||||
return AccessTools.FirstConstructor(type, _ => true);
|
||||
}
|
||||
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var property = AccessTools.Property(typeof(Environment), nameof(Environment.ProcessorCount));
|
||||
|
||||
return instructions.Manipulator(i => i.Calls(property.GetMethod),
|
||||
i =>
|
||||
{
|
||||
i.opcode = OpCodes.Ldc_I4;
|
||||
i.operand = 1024;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch]
|
||||
internal class ThreadPoolWorkItemTask(CringeTask task) : IThreadPoolWorkItem
|
||||
{
|
||||
public void Execute()
|
||||
{
|
||||
if (HkBaseSystem.IsInitialized && !HkBaseSystem.IsThreadInitialized)
|
||||
HkBaseSystem.InitThread(Thread.CurrentThread.Name);
|
||||
|
||||
task.Execute();
|
||||
}
|
||||
|
||||
private static MethodBase TargetMethod()
|
||||
{
|
||||
var type = Type.GetType("System.Threading.PortableThreadPool+WorkerThread, System.Private.CoreLib", true);
|
||||
return AccessTools.DeclaredMethod(type, "WorkerThreadStart");
|
||||
}
|
||||
|
||||
private static void Postfix()
|
||||
{
|
||||
if (!HkBaseSystem.IsInitialized || !HkBaseSystem.IsThreadInitialized) return;
|
||||
|
||||
HkBaseSystem.QuitThread();
|
||||
Debug.WriteLine($"Hk Shutdown for {Thread.CurrentThread.Name}");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user