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 BuildInteract v0.5.0
BuildInteract.dll
Decompiled 8 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JG224.BuildInteract.Core; using JG224.ModCore.API; 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: AssemblyCompany("BuildInteract")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0")] [assembly: AssemblyProduct("BuildInteract")] [assembly: AssemblyTitle("BuildInteract")] [assembly: AssemblyVersion("0.5.0.0")] [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 JG224.BuildInteract { internal sealed class BuildInteractConfig { private readonly ConfigFile _file; private readonly List<Tuple<ConfigEntryBase, ConfigScope>> _entries = new List<Tuple<ConfigEntryBase, ConfigScope>>(); internal ConfigEntry<bool> Enabled { get; } internal ConfigEntry<KeyboardShortcut> PrioritizeBuild { get; } internal ConfigEntry<string> ExcludedPrefabs { get; } internal ConfigEntry<bool> DebugLogging { get; } private BuildInteractConfig(ConfigFile file) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) _file = file; Enabled = Add<bool>(file.Bind<bool>("Interaction", "InteractWhileBuilding", true, "Keep Valheim's normal Use interactions available while any placement tool is active."), (ConfigScope)1); PrioritizeBuild = Add<KeyboardShortcut>(file.Bind<KeyboardShortcut>("Interaction", "PrioritizeBuild", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Hold this shortcut to prioritize vanilla building instead of interacting. None disables the shortcut."), (ConfigScope)1); ExcludedPrefabs = Add<string>(file.Bind<string>("Interaction", "ExcludedPrefabs", "", "Semicolon-separated prefab names whose interactions remain disabled while building, for example portal_wood;piece_bed02."), (ConfigScope)1); DebugLogging = Add<bool>(file.Bind<bool>("Diagnostics", "DebugLogging", false, "Enable verbose BuildInteract diagnostics."), (ConfigScope)5); } internal static BuildInteractConfig Load(BaseUnityPlugin plugin, string configDirectory, ManualLogSource log) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (!Directory.Exists(configDirectory)) { Directory.CreateDirectory(configDirectory); } string text = LegacyBuildInteractConfigRules.FindImportSource(Directory.GetFiles(configDirectory, "*.cfg", SearchOption.TopDirectoryOnly)); BuildInteractConfig buildInteractConfig = new BuildInteractConfig(PluginConfigFiles.Attach(plugin, new ConfigFile(Path.Combine(configDirectory, "jg224.BuildInteract.cfg"), true, plugin.Info.Metadata))); if (text != null) { buildInteractConfig.ImportLegacy(text, log); } return buildInteractConfig; } internal IEnumerable<IDisposable> RegisterMetadata(ICoreServices services, ModuleId owner) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) foreach (Tuple<ConfigEntryBase, ConfigScope> pair in _entries) { yield return services.Configuration.Register(new ConfigSettingDescriptor(owner, pair.Item1.Definition.Section, pair.Item1.Definition.Key, pair.Item2, (Func<string>)(() => Convert.ToString(pair.Item1.BoxedValue, CultureInfo.InvariantCulture)), 1)); } } private void ImportLegacy(string path, ManualLogSource log) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown try { ConfigFile val = new ConfigFile(path, false); Enabled.Value = val.Bind<bool>("Interaction", "InteractWhileBuilding", Enabled.Value, (ConfigDescription)null).Value; _file.Save(); if (log != null) { log.LogInfo((object)("Imported Build Interact settings from " + Path.GetFileName(path) + ".")); } } catch (Exception ex) { if (log != null) { log.LogWarning((object)("Could not import GeneralTweaks Build Interact settings; using defaults. " + ex.Message)); } } } private ConfigEntry<T> Add<T>(ConfigEntry<T> entry, ConfigScope scope) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _entries.Add(Tuple.Create<ConfigEntryBase, ConfigScope>((ConfigEntryBase)(object)entry, scope)); return entry; } } [BepInPlugin("jg224.BuildInteract", "BuildInteract", "0.5.0")] [BepInProcess("valheim.exe")] [BepInDependency("com.jg224.modcore", "0.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "jg224.BuildInteract"; public const string PluginName = "BuildInteract"; public const string PluginVersion = "0.5.0"; public const string ModCoreGuid = "com.jg224.modcore"; public const string GeneralTweaksGuid = "JG224.GeneralTweaks"; public const int ProtocolVersion = 1; public static readonly ModuleId ModuleId = new ModuleId("buildinteract"); private readonly List<IDisposable> _registrations = new List<IDisposable>(); private Harmony _harmony; private bool _shutDown; internal static ManualLogSource Log { get; private set; } internal static BuildInteractConfig Settings { get; private set; } internal static ICoreServices Core { get; private set; } private void Awake() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Settings = BuildInteractConfig.Load((BaseUnityPlugin)(object)this, Paths.ConfigPath, ((BaseUnityPlugin)this).Logger); try { if (!ModCoreApi.IsAvailable) { throw new InvalidOperationException("ModCore did not initialize before BuildInteract."); } Core = ModCoreApi.Services; RegisterWithCore(); if (TryGetLegacyOwner(out var version)) { string text = "GeneralTweaks " + version?.ToString() + " still contains Build Interact; BuildInteract is paused to prevent duplicate hooks."; Core.Modules.SetState(ModuleId, (ModuleRuntimeState)3, text); ((BaseUnityPlugin)this).Logger.LogWarning((object)(text + " Update GeneralTweaks to 3.0.0 or newer.")); } else { _harmony = new Harmony("jg224.BuildInteract"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Client-local build interaction hooks ready."); Game.isModded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("BuildInteract 0.5.0 loaded; protocol " + 1 + ".")); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("BuildInteract failed to initialize safely: " + ex)); if (Core != null) { Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message); } Shutdown(); throw; } } private void OnDestroy() { Shutdown(); } private void RegisterWithCore() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) SemanticVersion val = default(SemanticVersion); if (!SemanticVersion.TryParse("0.5.0", ref val)) { throw new InvalidOperationException("BuildInteract has invalid release version metadata."); } _registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.BuildInteract", "BuildInteract", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1))); foreach (IDisposable item in Settings.RegisterMetadata(Core, ModuleId)) { _registrations.Add(item); } } private static bool TryGetLegacyOwner(out Version version) { version = null; if (!Chainloader.PluginInfos.TryGetValue("JG224.GeneralTweaks", out var value)) { return false; } version = value.Metadata.Version; if (version != null) { return version.CompareTo(new Version(3, 0, 0)) < 0; } return false; } private void Shutdown() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (_shutDown) { return; } _shutDown = true; Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; for (int num = _registrations.Count - 1; num >= 0; num--) { try { _registrations[num].Dispose(); } catch (Exception ex) { ManualLogSource logger = ((BaseUnityPlugin)this).Logger; if (logger != null) { logger.LogWarning((object)("Registration cleanup failed: " + ex.Message)); } } } _registrations.Clear(); if (Core != null) { Core.Metrics.RemoveOwner(ModuleId); } Core = null; Settings = null; Log = null; } } } namespace JG224.BuildInteract.Patches { internal static class InteractionContext { private static string _raw; private static HashSet<string> _excluded = InteractionRules.ParseExclusions(""); internal static bool Allowed(Player player) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) BuildInteractConfig settings = Plugin.Settings; if (!Object.op_Implicit((Object)(object)player)) { return false; } bool enabled = settings?.Enabled.Value ?? false; bool local = (Object)(object)player == (Object)(object)Player.m_localPlayer; bool building = ((Character)player).InPlaceMode(); bool dead = ((Character)player).IsDead(); bool controllingDoodad = player.GetDoodadController() != null; int prioritizeBuild; if (settings != null) { KeyboardShortcut value = settings.PrioritizeBuild.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { value = settings.PrioritizeBuild.Value; prioritizeBuild = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0); goto IL_006d; } } prioritizeBuild = 0; goto IL_006d; IL_006d: return InteractionRules.AllowInteraction(enabled, local, building, dead, controllingDoodad, (byte)prioritizeBuild != 0); } internal static bool Excluded(GameObject hover) { string text = Plugin.Settings?.ExcludedPrefabs.Value ?? ""; if (_raw != text) { _raw = text; _excluded = InteractionRules.ParseExclusions(text); } if (!Object.op_Implicit((Object)(object)hover) || _excluded.Count == 0) { return false; } Transform val = hover.transform; while (Object.op_Implicit((Object)(object)val)) { if (_excluded.Contains(InteractionRules.NormalizePrefab(((Object)val).name))) { return true; } val = val.parent; } return false; } } [HarmonyPatch(typeof(Player), "UpdateHover")] internal static class InteractWhileBuildingHoverPatch { [HarmonyPostfix] private static void Postfix(Player __instance, ref GameObject ___m_hovering, ref Character ___m_hoveringCreature) { if (InteractionContext.Allowed(__instance)) { FindHoverObject(__instance, out ___m_hovering, out ___m_hoveringCreature); if (InteractionContext.Excluded(___m_hovering)) { ___m_hovering = null; ___m_hoveringCreature = null; } } } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(Player), "FindHoverObject")] private static void FindHoverObject(Player instance, out GameObject hover, out Character hoverCreature) { hover = null; hoverCreature = null; throw new NotImplementedException("Harmony reverse patch stub"); } } [HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")] internal static class InteractWhileBuildingControllerPatch { [HarmonyPrefix] private static bool Prefix(Player __instance) { if (!InteractionContext.Allowed(__instance)) { return true; } GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); bool eligibleHover = Object.op_Implicit((Object)(object)hoverObject) && hoverObject.GetComponentInParent<Interactable>() != null && !InteractionContext.Excluded(hoverObject); return !InteractionRules.ShouldRouteControllerUse(ZInput.IsGamepadActive(), ZInput.IsNonClassicFunctionality(), Hud.IsPieceSelectionVisible(), ZInput.GetButtonDown("JoyUse"), eligibleHover); } } } namespace JG224.BuildInteract.Core { internal static class InteractionRules { internal static bool ShouldRefreshHover(bool enabled, bool isLocalPlayer, bool inPlaceMode, bool isDead) { if (enabled && isLocalPlayer && inPlaceMode) { return !isDead; } return false; } internal static bool ShouldLeaveBuildInputAlone(bool enabled, bool pieceSelectionVisible, bool joyUseDown, bool hasInteractableHover) { if (!(!enabled || pieceSelectionVisible) && joyUseDown) { return !hasInteractableHover; } return true; } internal static bool AllowInteraction(bool enabled, bool local, bool building, bool dead, bool controllingDoodad, bool prioritizeBuild) { if (ShouldRefreshHover(enabled, local, building, dead) && !controllingDoodad) { return !prioritizeBuild; } return false; } internal static bool ShouldRouteControllerUse(bool gamepadActive, bool alternateScheme, bool pieceSelectionVisible, bool useDown, bool eligibleHover) { if (gamepadActive && !alternateScheme) { return !ShouldLeaveBuildInputAlone(enabled: true, pieceSelectionVisible, useDown, eligibleHover); } return false; } internal static HashSet<string> ParseExclusions(string value) { return new HashSet<string>(from name in (value ?? "").Split(new char[1] { ';' }).Select(NormalizePrefab) where name.Length > 0 select name, StringComparer.OrdinalIgnoreCase); } internal static string NormalizePrefab(string name) { return (name ?? "").Replace("(Clone)", "").Trim(); } } internal static class LegacyBuildInteractConfigRules { internal const string CurrentFileName = "jg224.BuildInteract.cfg"; internal const string GeneralTweaksFileName = "jg224.GeneralTweaks.cfg"; internal const string LegacyGeneralTweaksFileName = "JG224.GeneralTweaks.cfg"; internal static string FindImportSource(IEnumerable<string> candidatePaths) { string[] paths = ((candidatePaths == null) ? Array.Empty<string>() : candidatePaths.ToArray()); if (FindExact(paths, "jg224.BuildInteract.cfg") != null) { return null; } return FindExact(paths, "jg224.GeneralTweaks.cfg") ?? FindExact(paths, "JG224.GeneralTweaks.cfg"); } private static string FindExact(IEnumerable<string> paths, string fileName) { return paths.FirstOrDefault((string path) => string.Equals(Path.GetFileName(path), fileName, StringComparison.Ordinal)); } } }