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 HoldToCommand v1.0.4
BepInEx\plugins\Vonny1412.HoldToCommand\HoldToCommand.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HoldToCommand.ValheimAPI; using HoldToCommand.ValheimAPI.LowLevel; using HoldToCommand.ValheimAPI.LowLevel.Core; using HoldToCommand.ValheimAPI.LowLevel.Core.Invokers; using HoldToCommand.ValheimAPI.LowLevel.Core.Signatures; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Yvonne Pautz")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Yvonne Pautz 2026")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.4+build.202603141306.377c33382d823959f799c5a8e859381244888418")] [assembly: AssemblyProduct("HoldToCommand")] [assembly: AssemblyTitle("HoldToCommand")] [assembly: AssemblyVersion("1.0.0.0")] namespace HoldToCommand { [BepInPlugin("Vonny1412.HoldToCommand", "HoldToCommand", "1.0.4")] public sealed class Plugin : BaseUnityPlugin { public class Configs { private const string Section_General = "General"; public static ConfigEntry<float> HoldThreshold { get; private set; } public static ConfigEntry<bool> ShowInNewLine { get; private set; } public static void Initialize(ConfigFile Config) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown string text = ""; text = "General"; HoldThreshold = Config.Bind<float>(text, "HoldThreshold", 0.45f, new ConfigDescription("Time in seconds the Use key must be held to issue a command.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ShowInNewLine = Config.Bind<bool>(text, "ShowInNewLine", false, new ConfigDescription("Show the command on a new line instead of after the pet command.", (AcceptableValueBase)null, Array.Empty<object>())); } } internal const string TranslationsFile = "HoldToCommand.Translations.txt"; internal static readonly Dictionary<string, (string holdTpl, string commandVerb)> TranslationsByLanguage = new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase); public const string Version = "1.0.4"; public const string ModName = "HoldToCommand"; public const string ModGuid = "Vonny1412.HoldToCommand"; internal static ManualLogSource Log { get; private set; } internal static string HoldTemplate { get; private set; } = ""; internal static string CommandVerb { get; private set; } = ""; internal static bool TranslationsRegistered { get; private set; } = false; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Configs.Initialize(((BaseUnityPlugin)this).Config); LoadTranslationsFile(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); } private static void LoadTranslationsFile() { try { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "HoldToCommand.Translations.txt"); if (!File.Exists(text)) { Log.LogInfo((object)("Translations file not found: " + text + " (will use English fallback)")); return; } string[] array = File.ReadAllLines(text); foreach (string text2 in array) { string text3 = text2.Trim(); if (text3.Length == 0 || text3.StartsWith("#")) { continue; } string[] array2 = text3.Split('|'); if (array2.Length < 3) { Log.LogWarning((object)("Invalid translations line (expected 3 columns): " + text2)); continue; } string text4 = array2[0].Trim(); string text5 = array2[1].Trim(); string text6 = array2[2].Trim(); if (text4.Length != 0) { if (text5.Length == 0 || text6.Length == 0) { Log.LogWarning((object)("Empty values in translations line: " + text2)); } else { TranslationsByLanguage[text4] = (text5, text6); } } } Log.LogDebug((object)string.Format("Loaded {0} translation entries from {1}", TranslationsByLanguage.Count, "HoldToCommand.Translations.txt")); } catch (Exception arg) { Log.LogError((object)$"Failed to load translations file: {arg}"); } } internal static void InvalidateTranslations() { TranslationsRegistered = false; } internal static bool RegisterTranslations(Localization loc) { if (TranslationsRegistered) { return true; } if (loc == null) { return false; } string selectedLanguage; try { selectedLanguage = loc.GetSelectedLanguage(); } catch { return false; } if (!TranslationsByLanguage.TryGetValue(selectedLanguage, out (string, string) value) && !TranslationsByLanguage.TryGetValue("English", out value)) { value = ("Hold $1", "Command"); } HoldTemplate = value.Item1; CommandVerb = value.Item2; TranslationsRegistered = true; return true; } } } namespace HoldToCommand.ValheimAPI { internal static class TameableExtensions { private static Tameable lastTarget; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetName(this Tameable tameable) { Tameable.__IAPI_SetName_Invoker1.Invoke(tameable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float GetLastPetTime(this Tameable tameable) { return Tameable.__IAPI_m_lastPetTime_Invoker.Get(tameable); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetLastPetTime(this Tameable tameable, float t) { Tameable.__IAPI_m_lastPetTime_Invoker.Set(tameable, t); } public static bool CustomInteract(this Tameable tameable, Humanoid user, bool hold, bool alt) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)tameable).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return false; } if (alt) { tameable.SetName(); return true; } if (!tameable.IsTamed()) { return false; } float time = Time.time; float lastPetTime = tameable.GetLastPetTime(); if (hold) { if (!tameable.m_commandable) { return false; } if ((Object)(object)lastTarget == (Object)(object)tameable) { return false; } if (time - lastPetTime < Plugin.Configs.HoldThreshold.Value) { return false; } lastTarget = tameable; tameable.Command(user, true); return true; } lastTarget = null; if (time - lastPetTime <= 1f) { return false; } tameable.SetLastPetTime(time); EffectList petEffect = tameable.m_petEffect; if (petEffect != null) { petEffect.Create(((Component)tameable).transform.position, ((Component)tameable).transform.rotation, (Transform)null, 1f, -1); } string text = null; if (tameable.m_tameTextGetter != null) { string text2 = tameable.m_tameTextGetter.Invoke(); if (!string.IsNullOrEmpty(text2)) { text = text2; } } if (string.IsNullOrEmpty(text)) { string hoverName = tameable.GetHoverName(); string text3 = tameable.m_tameText ?? ""; text = (tameable.m_nameBeforeText ? (hoverName + " " + text3) : text3); } if (!string.IsNullOrEmpty(text)) { ((Character)user).Message((MessageType)2, text, 0, (Sprite)null); } return true; } } } namespace HoldToCommand.ValheimAPI.LowLevel { public class Tameable : ClassPublicizer { public static readonly FieldMutateInvoker<float> __IAPI_m_lastPetTime_Invoker = new FieldMutateInvoker<float>(typeof(Tameable), "m_lastPetTime"); public static readonly VoidMethodInvoker __IAPI_SetName_Invoker1 = new VoidMethodInvoker(typeof(Tameable), "SetName", new ParamSig[0]); public Tameable(Tameable instance) : base(instance) { } } } namespace HoldToCommand.ValheimAPI.LowLevel.Core { public abstract class ClassPublicizer { protected object __IAPI_instance; public ClassPublicizer(object instance) { __IAPI_instance = instance; } public ClassPublicizer() { __IAPI_instance = null; } public static Type __IAPI_GetInstanceType() { return typeof(void); } public object __IAPI_GetInstance() { return __IAPI_instance; } public void __IAPI_SetInstance(object instance) { __IAPI_instance = instance; } } } namespace HoldToCommand.ValheimAPI.LowLevel.Core.Signatures { public abstract class CommonParamSig : ParamSig { public override bool Matches(ParameterInfo p) { if (p.IsOut != IsByRef && p.ParameterType.IsByRef != IsByRef) { return false; } Type type = p.ParameterType; if (type.IsByRef) { type = type.GetElementType(); } if (IsGeneric) { if (!type.IsGenericParameter || type.GenericParameterPosition != GenericIndex) { return false; } } else if (type != ConcreteType) { return false; } return true; } } public class GenericContainerParamSig : ParamSig { private readonly Type _genericDef; public GenericContainerParamSig(Type genericDef, bool isByRef) { _genericDef = genericDef; IsByRef = isByRef; } public override bool Matches(ParameterInfo p) { Type parameterType = p.ParameterType; if (parameterType.IsByRef != IsByRef) { return false; } if (!parameterType.IsGenericType) { return false; } if (parameterType.GetGenericTypeDefinition() != _genericDef) { return false; } return parameterType.GetGenericArguments().All((Type a) => a.IsGenericParameter); } } public class GenericParamSig : CommonParamSig { public GenericParamSig(int GenericIndex, bool IsByRef) { IsGeneric = true; base.GenericIndex = GenericIndex; ConcreteType = null; base.IsByRef = IsByRef; } } public class NonGenericParamSig : CommonParamSig { public NonGenericParamSig(Type ConcreteType, bool IsByRef) { IsGeneric = false; GenericIndex = -1; base.ConcreteType = ConcreteType; base.IsByRef = IsByRef; } } public abstract class ParamSig { public bool IsGeneric; public int GenericIndex; public Type ConcreteType; public bool IsByRef; public abstract bool Matches(ParameterInfo p); } } namespace HoldToCommand.ValheimAPI.LowLevel.Core.Invokers { public class ConstFieldInvoker<R> { protected readonly FieldInfo member; protected readonly Func<object, R> _getter; public ConstFieldInvoker(Type type, string name) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; member = type.GetField(name, bindingAttr); if (member == null) { throw new MissingFieldException(type.FullName, name); } _ = member.IsLiteral; object rawConstantValue = member.GetRawConstantValue(); R casted = (R)rawConstantValue; _getter = (object _) => casted; } public R Get(object instance) { return _getter(instance); } } public class FieldAccessInvoker<R> { protected readonly FieldInfo member; protected readonly Func<object, R> _getter; public FieldAccessInvoker(Type type, string name) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; member = type.GetField(name, bindingAttr); if (member == null) { throw new MissingFieldException(type.FullName, name); } _ = member.IsLiteral; _getter = CreateGetter(member); } public R Get(object instance) { return _getter(instance); } protected static Func<object, R> CreateGetter(FieldInfo field) { DynamicMethod dynamicMethod = new DynamicMethod(field.Name + "_Getter", typeof(R), new Type[1] { typeof(object) }, field.DeclaringType, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!field.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, field.DeclaringType); } iLGenerator.Emit(field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, field); if (field.FieldType.IsValueType && typeof(R) == typeof(object)) { iLGenerator.Emit(OpCodes.Box, field.FieldType); } iLGenerator.Emit(OpCodes.Ret); return (Func<object, R>)dynamicMethod.CreateDelegate(typeof(Func<object, R>)); } } public class FieldMutateInvoker<R> : FieldAccessInvoker<R> { protected readonly Action<object, R> _setter; public FieldMutateInvoker(Type type, string name) : base(type, name) { _setter = CreateSetter(member); } public void Set(object instance, R value) { _setter(instance, value); } protected static Action<object, R> CreateSetter(FieldInfo field) { DynamicMethod dynamicMethod = new DynamicMethod(field.Name + "_Setter", typeof(void), new Type[2] { typeof(object), typeof(R) }, field.DeclaringType, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!field.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, field.DeclaringType); } iLGenerator.Emit(OpCodes.Ldarg_1); if (field.FieldType.IsValueType && typeof(R) == typeof(object)) { iLGenerator.Emit(OpCodes.Unbox_Any, field.FieldType); } iLGenerator.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field); iLGenerator.Emit(OpCodes.Ret); return (Action<object, R>)dynamicMethod.CreateDelegate(typeof(Action<object, R>)); } } public abstract class GenericMethodInvoker : MethodInvoker { public static MethodInfo FindGenericMethod(Type type, string name, int genericCount, ParamSig[] signature) { MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != name || !methodInfo.IsGenericMethodDefinition || methodInfo.GetGenericArguments().Length != genericCount) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != signature.Length) { continue; } bool flag = true; for (int j = 0; j < parameters.Length; j++) { ParameterInfo p = parameters[j]; if (!signature[j].Matches(p)) { flag = false; break; } } if (flag) { return methodInfo; } } throw new MissingMethodException(type.FullName, name); } } public abstract class MethodInvoker { protected delegate object MethodInvokerDelegate(object instance, object[] args); protected static MethodInvokerDelegate CreateInvokerDelegate(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); DynamicMethod dynamicMethod = new DynamicMethod(method.Name + "_Invoker", typeof(object), new Type[2] { typeof(object), typeof(object[]) }, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!method.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, method.DeclaringType); } for (int i = 0; i < parameters.Length; i++) { iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldc_I4, i); iLGenerator.Emit(OpCodes.Ldelem_Ref); Type parameterType = parameters[i].ParameterType; if (parameterType.IsByRef) { Type elementType = parameterType.GetElementType(); iLGenerator.Emit(OpCodes.Unbox, elementType); } else { iLGenerator.Emit(OpCodes.Unbox_Any, parameterType); } } iLGenerator.Emit(method.IsStatic ? OpCodes.Call : OpCodes.Callvirt, method); if (method.ReturnType == typeof(void)) { iLGenerator.Emit(OpCodes.Ldnull); } else { iLGenerator.Emit(OpCodes.Box, method.ReturnType); } iLGenerator.Emit(OpCodes.Ret); return (MethodInvokerDelegate)dynamicMethod.CreateDelegate(typeof(MethodInvokerDelegate)); } } public class PropertyInvoker<R> { protected readonly PropertyInfo member; private readonly Func<object, R> _getter; private readonly Action<object, R> _setter; public PropertyInvoker(Type type, string name) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; member = type.GetProperty(name, bindingAttr); if (member == null) { throw new MissingFieldException(type.FullName, name); } if (member.CanRead) { _getter = CreateGetter(member); } if (member.CanWrite) { _setter = CreateSetter(member); } } public R Get(object instance) { if (_getter == null) { throw new InvalidOperationException("Property has no getter"); } return _getter(instance); } public void Set(object instance, R value) { if (_setter == null) { throw new InvalidOperationException("Property has no setter"); } _setter(instance, value); } private static Func<object, R> CreateGetter(PropertyInfo prop) { MethodInfo getMethod = prop.GetGetMethod(nonPublic: true); if (getMethod == null) { return null; } DynamicMethod dynamicMethod = new DynamicMethod(prop.Name + "_Getter", typeof(R), new Type[1] { typeof(object) }, prop.DeclaringType, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!getMethod.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, prop.DeclaringType); } iLGenerator.Emit(getMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, getMethod); if (prop.PropertyType.IsValueType && typeof(R) == typeof(object)) { iLGenerator.Emit(OpCodes.Box, prop.PropertyType); } iLGenerator.Emit(OpCodes.Ret); return (Func<object, R>)dynamicMethod.CreateDelegate(typeof(Func<object, R>)); } private static Action<object, R> CreateSetter(PropertyInfo prop) { MethodInfo setMethod = prop.GetSetMethod(nonPublic: true); if (setMethod == null) { return null; } DynamicMethod dynamicMethod = new DynamicMethod(prop.Name + "_Setter", typeof(void), new Type[2] { typeof(object), typeof(R) }, prop.DeclaringType, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!setMethod.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, prop.DeclaringType); } iLGenerator.Emit(OpCodes.Ldarg_1); if (prop.PropertyType.IsValueType && typeof(R) == typeof(object)) { iLGenerator.Emit(OpCodes.Unbox_Any, prop.PropertyType); } iLGenerator.Emit(setMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt, setMethod); iLGenerator.Emit(OpCodes.Ret); return (Action<object, R>)dynamicMethod.CreateDelegate(typeof(Action<object, R>)); } } public class TypedMethodInvoker<R> : MethodInvoker { protected readonly MethodInfo member; private readonly MethodInvokerDelegate _invoker; private readonly bool anyByRef; private static readonly object[] _args0 = Array.Empty<object>(); [ThreadStatic] private static object[] _args1; [ThreadStatic] private static object[] _args2; [ThreadStatic] private static object[] _args3; [ThreadStatic] private static object[] _args4; [ThreadStatic] private static object[] _args5; public TypedMethodInvoker(Type type, string name, ParamSig[] parameters) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; anyByRef = parameters.Any((ParamSig p) => p.IsByRef); Type[] types = parameters.Select((ParamSig p) => (!p.IsByRef) ? p.ConcreteType : p.ConcreteType.MakeByRefType()).ToArray(); member = type.GetMethod(name, bindingAttr, null, types, null); if (member == null) { throw new MissingMethodException(type.FullName, name); } _invoker = MethodInvoker.CreateInvokerDelegate(member); } public R Invoke(object instance, object[] args) { return (R)_invoker(instance, args); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance) { return (R)_invoker(instance, _args0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance, object arg0) { if (anyByRef) { return (R)_invoker(instance, new object[1] { arg0 }); } object[] array = _args1 ?? (_args1 = new object[1]); array[0] = arg0; return (R)_invoker(instance, array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance, object arg0, object arg1) { if (anyByRef) { return (R)_invoker(instance, new object[2] { arg0, arg1 }); } object[] array = _args2 ?? (_args2 = new object[2]); array[0] = arg0; array[1] = arg1; return (R)_invoker(instance, array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance, object arg0, object arg1, object arg2) { if (anyByRef) { return (R)_invoker(instance, new object[3] { arg0, arg1, arg2 }); } object[] array = _args3 ?? (_args3 = new object[3]); array[0] = arg0; array[1] = arg1; array[2] = arg2; return (R)_invoker(instance, array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance, object arg0, object arg1, object arg2, object arg3) { if (anyByRef) { return (R)_invoker(instance, new object[4] { arg0, arg1, arg2, arg3 }); } object[] array = _args4 ?? (_args4 = new object[4]); array[0] = arg0; array[1] = arg1; array[2] = arg2; array[3] = arg3; return (R)_invoker(instance, array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public R Invoke(object instance, object arg0, object arg1, object arg2, object arg3, object arg4) { if (anyByRef) { return (R)_invoker(instance, new object[5] { arg0, arg1, arg2, arg3, arg4 }); } object[] array = _args5 ?? (_args5 = new object[5]); array[0] = arg0; array[1] = arg1; array[2] = arg2; array[3] = arg3; array[4] = arg4; return (R)_invoker(instance, array); } } public class VoidMethodInvoker : MethodInvoker { protected readonly MethodInfo member; private readonly MethodInvokerDelegate _invoker; private readonly bool anyByRef; private static readonly object[] _args0 = Array.Empty<object>(); [ThreadStatic] private static object[] _args1; [ThreadStatic] private static object[] _args2; [ThreadStatic] private static object[] _args3; [ThreadStatic] private static object[] _args4; [ThreadStatic] private static object[] _args5; public VoidMethodInvoker(Type type, string name, ParamSig[] parameters) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; anyByRef = parameters.Any((ParamSig p) => p.IsByRef); Type[] types = parameters.Select((ParamSig p) => (!p.IsByRef) ? p.ConcreteType : p.ConcreteType.MakeByRefType()).ToArray(); member = type.GetMethod(name, bindingAttr, null, types, null); if (member == null) { throw new MissingMethodException(type.FullName, name); } _invoker = MethodInvoker.CreateInvokerDelegate(member); } public void Invoke(object instance, object[] args) { _invoker(instance, args); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance) { _invoker(instance, _args0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance, object arg0) { if (anyByRef) { _invoker(instance, new object[1] { arg0 }); } else { object[] array = _args1 ?? (_args1 = new object[1]); array[0] = arg0; _invoker(instance, array); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance, object arg0, object arg1) { if (anyByRef) { _invoker(instance, new object[2] { arg0, arg1 }); } else { object[] array = _args2 ?? (_args2 = new object[2]); array[0] = arg0; array[1] = arg1; _invoker(instance, array); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance, object arg0, object arg1, object arg2) { if (anyByRef) { _invoker(instance, new object[3] { arg0, arg1, arg2 }); } else { object[] array = _args3 ?? (_args3 = new object[3]); array[0] = arg0; array[1] = arg1; array[2] = arg2; _invoker(instance, array); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance, object arg0, object arg1, object arg2, object arg3) { if (anyByRef) { _invoker(instance, new object[4] { arg0, arg1, arg2, arg3 }); } else { object[] array = _args4 ?? (_args4 = new object[4]); array[0] = arg0; array[1] = arg1; array[2] = arg2; array[3] = arg3; _invoker(instance, array); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(object instance, object arg0, object arg1, object arg2, object arg3, object arg4) { if (anyByRef) { _invoker(instance, new object[5] { arg0, arg1, arg2, arg3, arg4 }); } else { object[] array = _args5 ?? (_args5 = new object[5]); array[0] = arg0; array[1] = arg1; array[2] = arg2; array[3] = arg3; array[4] = arg4; _invoker(instance, array); } } } } namespace HoldToCommand.Patches { [HarmonyPatch(typeof(Localization), "SetupLanguage")] internal static class Localization_SetupLanguage_Patch { private static void Prefix() { Plugin.InvalidateTranslations(); } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] internal static class Tameable_GetHoverText_Patch { [HarmonyPriority(0)] private static void Postfix(Tameable __instance, ref string __result) { if (!__instance.IsTamed() || !__instance.m_commandable) { return; } Localization instance = Localization.instance; if (Plugin.RegisterTranslations(instance)) { string text = instance.Localize("$hud_pet"); int num = __result.IndexOf(text, StringComparison.Ordinal); if (num >= 0) { string newValue = instance.Localize("$KEY_Use"); string text2 = Plugin.HoldTemplate.Replace("$1", newValue); string commandVerb = Plugin.CommandVerb; string text3 = (Plugin.Configs.ShowInNewLine.Value ? "\n" : " "); __result = __result.Insert(num + text.Length, text3 + "[<color=yellow><b>" + text2 + "</b></color>] " + commandVerb); } } } } [HarmonyPatch(typeof(Tameable), "Interact")] internal static class Tameable_Interact_Patch { [HarmonyPriority(0)] private static bool Prefix(Tameable __instance, Humanoid user, bool hold, bool alt, ref bool __result, bool __runOriginal) { if (!__runOriginal) { return false; } __result = __instance.CustomInteract(user, hold, alt); return false; } } }