mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-08-05 19:40:27 +08:00
refactor: phase 5 transpiler docs, mod-compat helpers, and build quality gates
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using BepInEx;
|
||||
using BepInEx.Bootstrap;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist.Common.ModCompat;
|
||||
|
||||
public static class ModCompatHelper
|
||||
{
|
||||
public static bool TryGetLoadedPluginInfo(string guid, out BepInEx.PluginInfo pluginInfo)
|
||||
{
|
||||
return Chainloader.PluginInfos.TryGetValue(guid, out pluginInfo) && pluginInfo != null;
|
||||
}
|
||||
|
||||
public static bool TryGetPluginType(BepInEx.PluginInfo pluginInfo, string typeName, out Type type)
|
||||
{
|
||||
type = null;
|
||||
if (pluginInfo?.Instance == null) return false;
|
||||
try
|
||||
{
|
||||
type = pluginInfo.Instance.GetType().Assembly.GetType(typeName, throwOnError: false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return type != null;
|
||||
}
|
||||
|
||||
public static bool TryGetPluginType(string guid, string typeName, out Type type)
|
||||
{
|
||||
type = null;
|
||||
return TryGetLoadedPluginInfo(guid, out var pluginInfo) && TryGetPluginType(pluginInfo, typeName, out type);
|
||||
}
|
||||
|
||||
public static bool TryGetField(Type type, string fieldName, out FieldInfo field)
|
||||
{
|
||||
field = null;
|
||||
if (type == null) return false;
|
||||
field = AccessTools.Field(type, fieldName);
|
||||
return field != null;
|
||||
}
|
||||
|
||||
public static bool TryGetFieldValue<T>(Type type, string fieldName, object instance, out T value)
|
||||
{
|
||||
value = default;
|
||||
if (!TryGetField(type, fieldName, out var field)) return false;
|
||||
try
|
||||
{
|
||||
var result = field.GetValue(instance);
|
||||
if (result is T t)
|
||||
{
|
||||
value = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryGetMethod(Type type, string methodName, out MethodInfo method)
|
||||
{
|
||||
method = null;
|
||||
if (type == null) return false;
|
||||
method = AccessTools.Method(type, methodName);
|
||||
return method != null;
|
||||
}
|
||||
|
||||
public static bool TryGetPropertySetter(Type type, string propertyName, out MethodInfo setter)
|
||||
{
|
||||
setter = null;
|
||||
if (type == null) return false;
|
||||
var property = AccessTools.Property(type, propertyName);
|
||||
if (property == null) return false;
|
||||
setter = property.GetSetMethod(nonPublic: true);
|
||||
return setter != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using BepInEx.Logging;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist.Common.Patching;
|
||||
|
||||
/// <summary>
|
||||
/// Helper for Harmony transpilers. Provides a standardized way to bail out and return the original
|
||||
/// instructions when a <see cref="CodeMatcher"/> fails to match, which makes version-fragile patches
|
||||
/// easier to diagnose at runtime.
|
||||
/// </summary>
|
||||
public static class TranspilerGuard
|
||||
{
|
||||
public static IEnumerable<CodeInstruction> Finish(
|
||||
this CodeMatcher matcher,
|
||||
IEnumerable<CodeInstruction> originalInstructions,
|
||||
ManualLogSource logger,
|
||||
string transpilerName)
|
||||
{
|
||||
if (matcher.IsInvalid)
|
||||
{
|
||||
logger?.LogWarning($"Transpiler '{transpilerName}' failed to match; returning original instructions.");
|
||||
return originalInstructions;
|
||||
}
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace UXAssist.Common.Utils;
|
||||
|
||||
public static class DysonSphereReflection
|
||||
{
|
||||
private static readonly FieldInfo TotalNodeSpField = AccessTools.Field(typeof(DysonSphereLayer), "totalNodeSP");
|
||||
private static readonly FieldInfo TotalFrameSpField = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP");
|
||||
private static readonly FieldInfo TotalCpField = AccessTools.Field(typeof(DysonSphereLayer), "totalCP");
|
||||
|
||||
public static bool IsAvailable => TotalNodeSpField != null && TotalFrameSpField != null && TotalCpField != null;
|
||||
|
||||
public static bool HasTotalNodeSP => TotalNodeSpField != null;
|
||||
|
||||
public static bool HasTotalFrameSP => TotalFrameSpField != null;
|
||||
|
||||
public static bool HasTotalCP => TotalCpField != null;
|
||||
|
||||
public static long? GetTotalNodeSP(DysonSphereLayer layer)
|
||||
=> layer != null && TotalNodeSpField != null ? (long?)TotalNodeSpField.GetValue(layer) : null;
|
||||
|
||||
public static long? GetTotalFrameSP(DysonSphereLayer layer)
|
||||
=> layer != null && TotalFrameSpField != null ? (long?)TotalFrameSpField.GetValue(layer) : null;
|
||||
|
||||
public static long? GetTotalCP(DysonSphereLayer layer)
|
||||
=> layer != null && TotalCpField != null ? (long?)TotalCpField.GetValue(layer) : null;
|
||||
|
||||
public static void SetTotalNodeSP(DysonSphereLayer layer, long value)
|
||||
=> TotalNodeSpField?.SetValue(layer, value);
|
||||
|
||||
public static void SetTotalFrameSP(DysonSphereLayer layer, long value)
|
||||
=> TotalFrameSpField?.SetValue(layer, value);
|
||||
|
||||
public static void SetTotalCP(DysonSphereLayer layer, long value)
|
||||
=> TotalCpField?.SetValue(layer, value);
|
||||
}
|
||||
Reference in New Issue
Block a user