Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimanRaftBridge v1.1.1
ValheimanRaftBridge.dll
Decompiled 2 weeks agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")] [assembly: AssemblyCompany("ValheimanRaftBridge")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("ValheimanRaftBridge")] [assembly: AssemblyTitle("ValheimanRaftBridge")] [assembly: AssemblyVersion("1.1.1.0")] namespace ValheimanRaftBridge; internal static class Hooks { private static bool _rudderBroken; private static bool _sailBroken; private static bool _wheelBroken; private static bool _windBroken; private static bool _damageBroken; public static void SailForcePrefix(object __instance, ref float __0) { if (_sailBroken) { return; } ValheimanRaftBridgePlugin instance = ValheimanRaftBridgePlugin.Instance; if ((Object)(object)instance == (Object)null) { return; } try { if (instance.IsLocalHelmsman(__instance)) { instance.NoteHelm(__instance); if (instance.SailSpeedEnabled && instance.BoostActive) { __0 *= 1f + instance.SailBonus; } } } catch (Exception ex) { _sailBroken = true; instance.Log.LogError((object)("Ship speed hook disabled: " + ex.Message)); } } public static void RudderForcePostfix(object __instance, ref float __result) { if (_rudderBroken) { return; } ValheimanRaftBridgePlugin instance = ValheimanRaftBridgePlugin.Instance; if ((Object)(object)instance == (Object)null || !instance.RudderSpeedEnabled) { return; } try { if (instance.BoostActive && !(instance.SailBonus <= 0f) && instance.IsLocalHelmsman(__instance)) { __result = Math.Max(__result, 1f) * (1f + instance.SailBonus); } } catch (Exception ex) { _rudderBroken = true; instance.Log.LogError((object)("Rudder speed hook disabled: " + ex.Message)); } } public static void WheelTurningSpeedPostfix(object __instance) { if (_wheelBroken) { return; } ValheimanRaftBridgePlugin instance = ValheimanRaftBridgePlugin.Instance; if ((Object)(object)instance == (Object)null) { return; } try { if (instance.IsLocalHelmsman(__instance)) { instance.NoteHelm(__instance); if (instance.HandlingEnabled && instance.BoostActive) { RaftApi raft = instance.Raft; raft.SetRudderSpeed(__instance, raft.RudderSpeed(__instance) * (1f + instance.HandlingBonus)); } } } catch (Exception ex) { _wheelBroken = true; instance.Log.LogError((object)("Ship handling hook disabled: " + ex.Message)); } } public static void WindControlPostfix(object __instance, ref bool __result) { if (__result || _windBroken) { return; } ValheimanRaftBridgePlugin instance = ValheimanRaftBridgePlugin.Instance; if ((Object)(object)instance == (Object)null) { return; } try { if (instance.TailwindActiveFor(__instance)) { __result = true; } } catch (Exception ex) { _windBroken = true; instance.Log.LogError((object)("Tailwind hook disabled: " + ex.Message)); } } public static void DamagePrefix(Component __instance, object hit) { if (_damageBroken || hit == null) { return; } ValheimanRaftBridgePlugin instance = ValheimanRaftBridgePlugin.Instance; if ((Object)(object)instance == (Object)null || !instance.ShipDamageEnabled) { return; } try { RaftApi raft = instance.Raft; object obj = raft.MovementFor(__instance.transform); if (obj == null || RaftApi.IsDead(obj)) { return; } long num = raft.Helmsman(obj); if (num != 0L) { float num2 = ((num == instance.LocalPlayerId) ? instance.DamageMultiplier : raft.PublishedDamage(obj, num)); if (num2 > 0f && Math.Abs(num2 - 1f) > 0.0001f) { raft.ScaleDamage(hit, num2); } } } catch (Exception ex) { _damageBroken = true; instance.Log.LogError((object)("Ship damage hook disabled: " + ex.Message)); } } } [BepInPlugin("burksheim.valheimanraftbridge", "Valheiman Raft Bridge", "1.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ValheimanRaftBridgePlugin : BaseUnityPlugin { public const string PluginGuid = "burksheim.valheimanraftbridge"; public const string PluginName = "Valheiman Raft Bridge"; public const string PluginVersion = "1.1.1"; public const string ValheimRaftGuid = "zolantris.ValheimRAFT"; public const string PathOfValheimanGuid = "treextr.pathofvalheiman"; private const float MaxHandlingBonus = 0.6f; private const float MinDamageMultiplier = 0.05f; private const float TailwindRollInterval = 10f; private const float TailwindDuration = 15f; internal static ValheimanRaftBridgePlugin Instance; private ConfigEntry<bool> _sailSpeed; private ConfigEntry<float> _sailSpeedCap; private ConfigEntry<bool> _rudderSpeed; private ConfigEntry<bool> _handling; private ConfigEntry<bool> _tailwind; private ConfigEntry<bool> _shipDamage; internal readonly RaftApi Raft = new RaftApi(); internal readonly PovStats Pov = new PovStats(); private Harmony _harmony; private readonly Random _random = new Random(); internal long LocalPlayerId; internal float SailBonus; internal float HandlingBonus; internal bool BoostActive; internal float TailwindChance; internal float DamageMultiplier = 1f; private float _nextRefresh; private object _helmVehicle; private float _helmSeenAt = float.MinValue; private object _tailwindVehicle; private float _tailwindUntil; private float _nextTailwindRoll; internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger; internal bool SailSpeedEnabled => _sailSpeed.Value; internal bool RudderSpeedEnabled { get { if (_sailSpeed.Value) { return _rudderSpeed.Value; } return false; } } internal bool HandlingEnabled => _handling.Value; internal bool ShipDamageEnabled => _shipDamage.Value; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown Instance = this; _sailSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Perks", "Ship Speed", true, "Path of Valheiman's 'ship speed while you are at the helm' boosts your raft's sails (up to Ship Speed Cap Percent)."); _sailSpeedCap = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Perks", "Ship Speed Cap Percent", 50f, new ConfigDescription("Highest ship speed bonus that counts on a raft, in percent. Path of Valheiman uses 40 on vanilla ships.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>())); _rudderSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Perks", "Ship Speed Boosts Rudder", true, "Ship speed also boosts the raft's rudder push (rowing, reverse, and ValheimRAFT's Rudder Half/Full Speed), not just the sails."); _handling = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Perks", "Ship Handling", true, "Path of Valheiman's 'ship handling while you are at the helm' makes the raft's wheel respond faster (capped at +60%)."); _tailwind = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Perks", "Minor Tailwind", true, "Path of Valheiman's minor tailwind chance can give your raft a following wind for 15 seconds (rolled every 10 seconds)."); _shipDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Perks", "Ship Damage Taken", true, "The Shipwright 'damage taken by the ship while you are at the helm' applies to your raft's pieces. Pieces owned by another player's game only get it if that player has this addon too."); if (Raft.TryResolve(((BaseUnityPlugin)this).Logger) && Pov.TryResolve(((BaseUnityPlugin)this).Logger)) { _harmony = new Harmony("burksheim.valheimanraftbridge"); Patch(Raft.GetSailForce, "SailForcePrefix", null, "sail force (ship speed)"); Patch(Raft.RudderForce, null, "RudderForcePostfix", "rudder push (ship speed on the rudder)"); if (Raft.CanBoostHandling) { Patch(Raft.WheelTurningSpeed, null, "WheelTurningSpeedPostfix", "wheel turning speed (ship handling)"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Ship handling: ValheimRAFT's wheel speed members not found; skipped."); } Patch(Raft.WindControlActive, null, "WindControlPostfix", "wind control (minor tailwind)"); if (Raft.CanShareDamage) { Patch(Raft.WearNTearDamage, "DamagePrefix", null, "piece damage (ship damage taken)"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Ship damage taken: required members not found; skipped."); } } } private void Patch(MethodInfo target, string prefix = null, string postfix = null, string what = "") { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (target == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not find ValheimRAFT's " + what + "; that perk will not apply to rafts.")); return; } try { _harmony.Patch((MethodBase)target, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Hooks), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Hooks), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Hooked " + what + ".")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to hook " + what + ": " + ex.Message)); } } private void Update() { if (!Raft.Ready || !Pov.Ready) { return; } float time = Time.time; if (time < _nextRefresh) { return; } _nextRefresh = time + 0.5f; try { Refresh(time); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Refresh failed (will retry): " + ex.Message)); } } private void Refresh(float now) { LocalPlayerId = Raft.LocalPlayerId(); if (LocalPlayerId == 0L) { SailBonus = (HandlingBonus = (TailwindChance = 0f)); BoostActive = false; DamageMultiplier = 1f; EndTailwind(); return; } SailBonus = Math.Min(_sailSpeedCap.Value / 100f, Pov.SailSpeed); HandlingBonus = Math.Min(0.6f, Pov.SailControl); BoostActive = SailBonus > 0f || HandlingBonus > 0f; TailwindChance = Clamp01(Pov.TailwindChance); float shipDamageTaken = Pov.ShipDamageTaken; DamageMultiplier = ((shipDamageTaken != 0f) ? Math.Max(0.05f, 1f + shipDamageTaken) : 1f); if (_helmVehicle == null || !(now - _helmSeenAt < 1.5f) || !IsLocalHelmsman(_helmVehicle)) { _helmVehicle = null; EndTailwind(); return; } if (_shipDamage.Value) { Raft.Publish(_helmVehicle, LocalPlayerId, DamageMultiplier); } UpdateTailwind(now); } private void UpdateTailwind(float now) { if (!_tailwind.Value || TailwindChance <= 0f) { EndTailwind(); } else if (_tailwindVehicle != _helmVehicle) { _tailwindVehicle = _helmVehicle; _tailwindUntil = 0f; _nextTailwindRoll = now + 10f; } else { if (now < _nextTailwindRoll) { return; } _nextTailwindRoll = now + 10f; if (_random.NextDouble() < (double)TailwindChance) { bool num = now >= _tailwindUntil; _tailwindUntil = now + 15f; if (num) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Minor tailwind on your raft for " + 15f + " s.")); } } } } private void EndTailwind() { _tailwindVehicle = null; _tailwindUntil = 0f; } internal bool IsLocalHelmsman(object movement) { if (LocalPlayerId != 0L) { return Raft.Helmsman(movement) == LocalPlayerId; } return false; } internal void NoteHelm(object movement) { _helmVehicle = movement; _helmSeenAt = Time.time; } internal bool TailwindActiveFor(object movement) { if (_tailwind.Value && _tailwindVehicle != null && _tailwindVehicle == movement && Time.time < _tailwindUntil) { return IsLocalHelmsman(movement); } return false; } private static float Clamp01(float v) { if (!(v < 0f)) { if (!(v > 1f)) { return v; } return 1f; } return 0f; } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if (Instance == this) { Instance = null; } } } internal sealed class PovStats { private Func<object, object> _progressCurrent; private Func<object, object> _progressStats; private Func<object, object> _tradeStats; private MethodInfo _statGet; private object _sailSpeed; private object _sailControl; private object _tailwindChance; private object _shipDamageTaken; public bool Ready { get; private set; } public float SailSpeed => Main(_sailSpeed); public float SailControl => Main(_sailControl); public float TailwindChance => Main(_tailwindChance); public float ShipDamageTaken => Read(_tradeStats?.Invoke(null), _shipDamageTaken); public bool TryResolve(ManualLogSource log) { Type type = Reflect.FindType("PassiveTree.Progress"); Type type2 = Reflect.FindType("PassiveTree.StatSet"); Type type3 = Reflect.FindType("PassiveTree.Stat"); if (type == null || type2 == null || type3 == null || !type3.IsEnum) { log.LogWarning((object)"Path of Valheiman not found; sailing bonuses will not apply to rafts."); return false; } _progressCurrent = Reflect.Getter(type, "Current"); _progressStats = Reflect.Getter(type, "Stats"); _statGet = Reflect.Method(type2, "Get", type3); Type type4 = Reflect.FindType("PassiveTree.TradeMechanics"); _tradeStats = ((type4 != null) ? Reflect.Getter(type4, "S") : null); _sailSpeed = EnumValue(type3, "SailSpeedPct"); _sailControl = EnumValue(type3, "SailControlPct"); _tailwindChance = EnumValue(type3, "SmallTailwindChance"); _shipDamageTaken = EnumValue(type3, "ShipDamageTakenPct"); if (_progressCurrent == null || _progressStats == null || _statGet == null || _statGet.ReturnType != typeof(float)) { log.LogWarning((object)"This Path of Valheiman version stores its stats differently than expected; bridge disabled."); return false; } Ready = true; log.LogInfo((object)("Path of Valheiman found: ship speed " + Found(_sailSpeed) + ", handling " + Found(_sailControl) + ", tailwind " + Found(_tailwindChance) + ", ship damage taken " + Found((_shipDamageTaken != null && _tradeStats != null) ? _shipDamageTaken : null) + ".")); return true; } private float Main(object statId) { if (!Ready || statId == null) { return 0f; } object obj = _progressCurrent(null); if (obj != null) { return Read(_progressStats(obj), statId); } return 0f; } private float Read(object statSet, object statId) { if (statSet == null || statId == null || _statGet == null) { return 0f; } return (float)_statGet.Invoke(statSet, new object[1] { statId }); } private static object EnumValue(Type enumType, string name) { try { return Enum.IsDefined(enumType, name) ? Enum.Parse(enumType, name) : null; } catch (Exception) { return null; } } private static string Found(object o) { if (o == null) { return "missing"; } return "yes"; } } internal sealed class RaftApi { public Type MovementType; public Type PiecesType; public MethodInfo GetSailForce; public MethodInfo WheelTurningSpeed; public MethodInfo RudderForce; public MethodInfo WindControlActive; private MethodInfo _getUser; private FieldInfo _rudderSpeed; private Func<object, object> _netView; private Func<object, object> _piecesToMovement; private FieldInfo _localPlayer; private MethodInfo _getPlayerId; public MethodInfo WearNTearDamage; private FieldInfo _hitDamage; private MethodInfo _damageModify; private MethodInfo _nviewGetZdo; private MethodInfo _nviewIsOwner; private MethodInfo _zdoGetFloat; private MethodInfo _zdoGetLong; private MethodInfo _zdoSetFloat; private MethodInfo _zdoSetLong; public const string DamageKey = "ValheimanRaft_ShipDamageMult"; public const string DamageUserKey = "ValheimanRaft_ShipDamageUser"; public bool Ready { get; private set; } public bool CanBoostHandling { get { if (WheelTurningSpeed != null) { return _rudderSpeed != null; } return false; } } public bool CanShareDamage { get { if (WearNTearDamage != null && _hitDamage != null && _damageModify != null) { return _piecesToMovement != null; } return false; } } public bool CanPublish { get { if (_netView != null && _nviewGetZdo != null && _nviewIsOwner != null && _zdoGetFloat != null && _zdoGetLong != null && _zdoSetFloat != null) { return _zdoSetLong != null; } return false; } } public bool TryResolve(ManualLogSource log) { MovementType = Reflect.FindType("ValheimVehicles.Controllers.VehicleMovementController") ?? Reflect.FindTypeByName("VehicleMovementController", "Valheim"); PiecesType = Reflect.FindType("ValheimVehicles.Controllers.VehiclePiecesController") ?? Reflect.FindTypeByName("VehiclePiecesController", "Valheim"); Type type = Reflect.FindType("Player"); if (MovementType == null || PiecesType == null || type == null) { log.LogWarning((object)"ValheimRAFT not found; nothing to bridge."); return false; } GetSailForce = Reflect.MethodWithFirstParam(MovementType, "GetSailForce", typeof(float)); WheelTurningSpeed = Reflect.Method(MovementType, "UpdateShipWheelTurningSpeed"); RudderForce = Reflect.Method(MovementType, "GetRudderForcePerSpeed"); if (RudderForce != null && RudderForce.ReturnType != typeof(float)) { RudderForce = null; } WindControlActive = Reflect.Method(MovementType, "IsWindControllActive"); if (WindControlActive != null && WindControlActive.ReturnType != typeof(bool)) { WindControlActive = null; } _getUser = Reflect.Method(MovementType, "GetUser"); if (_getUser != null && _getUser.ReturnType != typeof(long)) { _getUser = null; } _rudderSpeed = Reflect.Field(MovementType, "m_rudderSpeed"); if (_rudderSpeed != null && _rudderSpeed.FieldType != typeof(float)) { _rudderSpeed = null; } _netView = Reflect.Getter(MovementType, "m_nview"); _piecesToMovement = Reflect.Getter(PiecesType, "MovementController"); _localPlayer = Reflect.Field(type, "m_localPlayer"); _getPlayerId = Reflect.Method(type, "GetPlayerID"); Type type2 = Reflect.FindType("WearNTear"); Type type3 = Reflect.FindType("HitData"); if (type2 != null && type3 != null) { WearNTearDamage = Reflect.Method(type2, "RPC_Damage", typeof(long), type3); _hitDamage = Reflect.Field(type3, "m_damage"); if (_hitDamage != null) { _damageModify = Reflect.Method(_hitDamage.FieldType, "Modify", typeof(float)); } } Type type4 = Reflect.FindType("ZNetView"); Type type5 = Reflect.FindType("ZDO"); if (type4 != null && type5 != null) { _nviewGetZdo = Reflect.Method(type4, "GetZDO"); _nviewIsOwner = Reflect.Method(type4, "IsOwner"); _zdoGetFloat = Reflect.Method(type5, "GetFloat", typeof(string), typeof(float)); _zdoGetLong = Reflect.Method(type5, "GetLong", typeof(string), typeof(long)); _zdoSetFloat = Reflect.Method(type5, "Set", typeof(string), typeof(float)); _zdoSetLong = Reflect.Method(type5, "Set", typeof(string), typeof(long)); } if (_getUser == null || _localPlayer == null || _getPlayerId == null) { log.LogWarning((object)"This ValheimRAFT version doesn't expose who is steering; bridge disabled."); return false; } Ready = true; return true; } public long LocalPlayerId() { object? value = _localPlayer.GetValue(null); Object val = (Object)((value is Object) ? value : null); if (val == (Object)null) { return 0L; } return (long)_getPlayerId.Invoke(val, null); } public long Helmsman(object movement) { if (IsDead(movement)) { return 0L; } return (long)_getUser.Invoke(movement, null); } public float RudderSpeed(object movement) { return (float)_rudderSpeed.GetValue(movement); } public void SetRudderSpeed(object movement, float value) { _rudderSpeed.SetValue(movement, value); } public object MovementFor(Transform piece) { int num = 0; Transform val = piece; while ((Object)(object)val != (Object)null && num < 32) { Component component = ((Component)val).GetComponent(PiecesType); if ((Object)(object)component != (Object)null) { return _piecesToMovement(component); } val = val.parent; num++; } return null; } public void ScaleDamage(object hit, float multiplier) { object value = _hitDamage.GetValue(hit); _damageModify.Invoke(value, new object[1] { multiplier }); _hitDamage.SetValue(hit, value); } public void Publish(object movement, long playerId, float damageMultiplier) { object obj = OwnedZdo(movement); if (obj != null && ((long)_zdoGetLong.Invoke(obj, new object[2] { "ValheimanRaft_ShipDamageUser", 0L }) != playerId || !(Math.Abs((float)_zdoGetFloat.Invoke(obj, new object[2] { "ValheimanRaft_ShipDamageMult", 1f }) - damageMultiplier) < 0.0001f))) { _zdoSetFloat.Invoke(obj, new object[2] { "ValheimanRaft_ShipDamageMult", damageMultiplier }); _zdoSetLong.Invoke(obj, new object[2] { "ValheimanRaft_ShipDamageUser", playerId }); } } public float PublishedDamage(object movement, long helmsman) { if (!CanPublish) { return 1f; } object obj = _netView(movement); object obj2 = ((obj != null) ? _nviewGetZdo.Invoke(obj, null) : null); if (obj2 == null) { return 1f; } if ((long)_zdoGetLong.Invoke(obj2, new object[2] { "ValheimanRaft_ShipDamageUser", 0L }) != helmsman) { return 1f; } return (float)_zdoGetFloat.Invoke(obj2, new object[2] { "ValheimanRaft_ShipDamageMult", 1f }); } private object OwnedZdo(object movement) { if (!CanPublish || IsDead(movement)) { return null; } object obj = _netView(movement); if (obj == null || !(bool)_nviewIsOwner.Invoke(obj, null)) { return null; } return _nviewGetZdo.Invoke(obj, null); } public static bool IsDead(object unityObject) { return (Object)((unityObject is Object) ? unityObject : null) == (Object)null; } } internal static class Reflect { public const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; public static Type FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = null; try { type = assembly.GetType(fullName, throwOnError: false); } catch (Exception) { } if (type != null) { return type; } } return null; } public static Type FindTypeByName(string name, string assemblyHint) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name.IndexOf(assemblyHint, StringComparison.OrdinalIgnoreCase) < 0) { continue; } Type[] types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } catch (Exception) { continue; } Type[] array = types; foreach (Type type in array) { if (type != null && type.Name == name) { return type; } } } return null; } public static FieldInfo Field(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo field = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type2 = type2.BaseType; } return null; } public static Func<object, object> Getter(Type type, string name) { Type type2 = type; while (type2 != null) { FieldInfo f = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (f != null) { return (object o) => f.GetValue(o); } PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.GetIndexParameters().Length == 0 && property.GetGetMethod(nonPublic: true) != null) { MethodInfo g = property.GetGetMethod(nonPublic: true); return (object o) => g.Invoke(o, null); } type2 = type2.BaseType; } return null; } public static MethodInfo Method(Type type, string name, params Type[] parameters) { Type type2 = type; while (type2 != null) { MethodInfo method = type2.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null); if (method != null) { return method; } type2 = type2.BaseType; } return null; } public static MethodInfo MethodWithFirstParam(Type type, string name, Type firstParam) { MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != name)) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == firstParam) { return methodInfo; } } } return null; } }