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 TameFollow v1.0.0
plugins/TameFollow.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("TameFollow")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+bf2e1b0a01a752b3562806e48708ba2eefcb0a26")] [assembly: AssemblyProduct("TameFollow")] [assembly: AssemblyTitle("TameFollow")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Oddhatter.TameFollow { [HarmonyPatch(typeof(Tameable), "Interact")] internal static class Tameable_Interact_Patch { private static readonly HashSet<string> s_logged = new HashSet<string>(); private static void Prefix(Tameable __instance, bool alt, out bool? __state) { __state = null; if (!TameFollowPlugin.Enabled.Value || alt || __instance.m_commandable || !__instance.IsTamed()) { return; } string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if ((Object)(object)__instance.m_monsterAI == (Object)null) { if (s_logged.Add(prefabName)) { TameFollowPlugin.Log.LogInfo((object)(prefabName + " can't follow (no MonsterAI); it is petted as normal.")); } return; } if (s_logged.Add(prefabName)) { TameFollowPlugin.Log.LogInfo((object)(prefabName + " can now be told to follow / stay.")); } __state = __instance.m_commandable; __instance.m_commandable = true; } private static Exception Finalizer(Tameable __instance, bool? __state, Exception __exception) { if (__state.HasValue && (Object)(object)__instance != (Object)null) { __instance.m_commandable = __state.Value; } return __exception; } } [BepInPlugin("com.oddhatter.tamefollow", "TameFollow", "1.0.0")] [BepInProcess("valheim.exe")] public sealed class TameFollowPlugin : BaseUnityPlugin { public const string Guid = "com.oddhatter.tamefollow"; public const string Name = "TameFollow"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; private const float ConfigReloadDelay = 0.5f; private Harmony _harmony; private FileSystemWatcher _configWatcher; private volatile bool _configFileChanged; private float _configReloadAt = -1f; private bool _configLockedLogged; private void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "true: pressing Use on any tamed creature that can follow (lox, asksvin, boar, ...) toggles follow / stay, like wolves. false: vanilla, where those creatures are only petted."); _harmony = new Harmony("com.oddhatter.tamefollow"); _harmony.PatchAll(typeof(TameFollowPlugin).Assembly); foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods()) { Log.LogInfo((object)("Patched " + patchedMethod.DeclaringType?.Name + "." + patchedMethod.Name)); } WatchConfigFile(); Log.LogInfo((object)"TameFollow 1.0.0 loaded."); } private void Update() { if (_configFileChanged) { _configFileChanged = false; _configReloadAt = Time.realtimeSinceStartup + 0.5f; } if (_configReloadAt >= 0f && Time.realtimeSinceStartup >= _configReloadAt) { _configReloadAt = -1f; ReloadConfigFromDisk(); } } private void OnDestroy() { _configWatcher?.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void WatchConfigFile() { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), IncludeSubdirectories = false }; _configWatcher.Changed += OnConfigFileEvent; _configWatcher.Created += OnConfigFileEvent; _configWatcher.Renamed += OnConfigFileEvent; _configWatcher.EnableRaisingEvents = true; } private void OnConfigFileEvent(object sender, FileSystemEventArgs e) { _configFileChanged = true; } private void ReloadConfigFromDisk() { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return; } bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; try { ((BaseUnityPlugin)this).Config.Reload(); _configLockedLogged = false; Log.LogInfo((object)"Configuration reloaded from disk."); } catch (IOException ex) { if (!_configLockedLogged) { _configLockedLogged = true; Log.LogWarning((object)("Config file busy, will retry: " + ex.Message)); } _configReloadAt = Time.realtimeSinceStartup + 0.5f; } catch (Exception ex2) { Log.LogError((object)("Failed to reload configuration: " + ex2.Message)); } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }