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 QuickFill v1.5.0
BepInEx/plugins/QuickFill/QuickFill.dll
Decompiled 5 days 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 Kriona.Shared; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Kriona")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Kriona Hagen - MIT License")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0")] [assembly: AssemblyProduct("Quick Fill")] [assembly: AssemblyTitle("Quick Fill")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.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 QuickFill { internal static class Fill { public static bool IsModifierHeld() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.ModifierKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if ((int)mainKey == 0) { return false; } KeyCode otherSide = GetOtherSide(mainKey); if (!ZInput.GetKey(mainKey, false)) { if ((int)otherSide != 0) { return ZInput.GetKey(otherSide, false); } return false; } return true; } private static KeyCode GetOtherSide(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown return (KeyCode)((key - 303) switch { 3 => 305, 2 => 306, 1 => 303, 0 => 304, 5 => 307, 4 => 308, 7 => 309, 6 => 310, _ => 0, }); } public unsafe static string GetModifierName() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected I4, but got Unknown KeyboardShortcut value = Plugin.ModifierKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; switch (mainKey - 303) { case 2: case 3: return "Ctrl"; case 0: case 1: return "Shift"; case 4: case 5: return "Alt"; case 6: case 7: return "Cmd"; default: return ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString(); } } public static bool Repeat(Func<bool> addOne, int count) { bool result = false; for (int i = 0; i < count; i++) { if (!addOne()) { break; } result = true; } return result; } } [HarmonyPatch(typeof(Switch), "Interact")] public static class SwitchInteractPatch { private static bool Prefix(Switch __instance, Humanoid character, bool hold, ref bool __result) { if (hold || __instance.m_onUse == null || !Fill.IsModifierHeld()) { return true; } int space = GetSpace(__instance); if (space <= 0) { return true; } __result = Fill.Repeat(() => __instance.m_onUse.Invoke(__instance, character, (ItemData)null), space); return false; } private static int GetSpace(Switch sw) { Smelter componentInParent = ((Component)sw).GetComponentInParent<Smelter>(); if ((Object)(object)componentInParent != (Object)null) { if (!componentInParent.m_nview.IsValid()) { return 0; } if ((Object)(object)sw == (Object)(object)componentInParent.m_addOreSwitch) { return componentInParent.m_maxOre - componentInParent.GetQueueSize(); } if ((Object)(object)sw == (Object)(object)componentInParent.m_addWoodSwitch) { return Mathf.FloorToInt((float)componentInParent.m_maxFuel - componentInParent.GetFuel()); } return 0; } CookingStation componentInParent2 = ((Component)sw).GetComponentInParent<CookingStation>(); if ((Object)(object)componentInParent2 != (Object)null && componentInParent2.m_nview.IsValid() && (Object)(object)sw == (Object)(object)componentInParent2.m_addFuelSwitch) { return Mathf.FloorToInt((float)componentInParent2.m_maxFuel - componentInParent2.GetFuel()); } ShieldGenerator componentInParent3 = ((Component)sw).GetComponentInParent<ShieldGenerator>(); if ((Object)(object)componentInParent3 != (Object)null && componentInParent3.m_nview.IsValid() && (Object)(object)sw == (Object)(object)componentInParent3.m_addFuelSwitch) { return Mathf.FloorToInt((float)componentInParent3.m_maxFuel - componentInParent3.GetFuel()); } return 0; } } [HarmonyPatch(typeof(Fireplace), "Interact")] public static class FireplaceInteractPatch { private static bool filling; private static bool Prefix(Fireplace __instance, Humanoid user, bool hold, ref bool alt, ref bool __result) { if (filling || hold || !Fill.IsModifierHeld()) { return true; } alt = true; if (!__instance.m_canRefill || __instance.m_infiniteFuel || !__instance.m_nview.IsValid()) { return true; } float num = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f); int num2 = Mathf.FloorToInt(__instance.m_maxFuel) - Mathf.CeilToInt(num); if (num2 <= 0) { return true; } filling = true; try { __result = Fill.Repeat(() => __instance.Interact(user, false, true), num2); } finally { filling = false; } return false; } } [HarmonyPatch(typeof(Player), "FindHoverObject")] public static class StationHoverPatch { private static void Postfix(Player __instance, ref GameObject hover) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hover == (Object)null || (Object)(object)hover.GetComponentInParent<Switch>() != (Object)null) { return; } Hoverable componentInParent = hover.GetComponentInParent<Hoverable>(); Smelter componentInParent2 = hover.GetComponentInParent<Smelter>(); CookingStation componentInParent3 = hover.GetComponentInParent<CookingStation>(); ShieldGenerator componentInParent4 = hover.GetComponentInParent<ShieldGenerator>(); Switch first; Switch second; bool vertical; if ((Object)(object)componentInParent2 != (Object)null && componentInParent == null) { first = componentInParent2.m_addOreSwitch; second = componentInParent2.m_addWoodSwitch; vertical = false; } else if ((Object)(object)componentInParent3 != (Object)null && (Object)(object)componentInParent3.m_addFoodSwitch != (Object)null && (object)componentInParent == componentInParent3) { first = componentInParent3.m_addFoodSwitch; second = componentInParent3.m_addFuelSwitch; vertical = true; } else { if (!((Object)(object)componentInParent4 != (Object)null) || componentInParent4.m_enableAttack || (object)componentInParent != componentInParent4) { return; } first = componentInParent4.m_addFuelSwitch; second = null; vertical = false; } if (GetHitPoint(__instance, out var point)) { Switch val = PickSwitch(first, second, point, hover.transform.up, vertical); if ((Object)(object)val != (Object)null) { hover = ((Component)val).gameObject; } } } private static bool GetHitPoint(Player player, out Vector3 point) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) RaycastHit[] raycastHoverHits = player.m_raycastHoverHits; for (int i = 0; i < raycastHoverHits.Length; i++) { RaycastHit val = raycastHoverHits[i]; if ((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) { break; } if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody) || !((Object)(object)((Component)((RaycastHit)(ref val)).collider.attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject)) { point = ((RaycastHit)(ref val)).point; return true; } } point = Vector3.zero; return false; } private static Switch PickSwitch(Switch first, Switch second, Vector3 point, Vector3 up, bool vertical) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) bool flag = IsUsable(first); bool flag2 = IsUsable(second); if (!flag || !flag2) { if (!flag) { if (!flag2) { return null; } return second; } return first; } Vector3 position = ((Component)first).transform.position; Vector3 position2 = ((Component)second).transform.position; Vector3 val = position2 - position; Vector3 val2 = (vertical ? Vector3.Project(val, up) : Vector3.ProjectOnPlane(val, up)); if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = val; } Vector3 val3 = (position + position2) / 2f; if (!(Vector3.Dot(point - val3, val2) < 0f)) { return second; } return first; } private static bool IsUsable(Switch sw) { if ((Object)(object)sw != (Object)null) { return ((Component)sw).gameObject.activeInHierarchy; } return false; } } [BepInPlugin("kriona.QuickFill", "Quick Fill", "1.5.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "kriona.QuickFill"; public const string PluginName = "Quick Fill"; public const string PluginVersion = "1.5.0"; public static ConfigEntry<KeyboardShortcut> ModifierKey; private Harmony harmony; private ConfigWatcher watcher; private void Awake() { //IL_001a: 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_005a: Expected O, but got Unknown ModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ModifierKey", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "Key to hold while pressing the use key to fill a station - a Unity KeyCode name, e.g. LeftShift, LeftControl or LeftAlt. Either side of Ctrl, Shift, Alt and Command counts, and None turns the fill off"); watcher = new ConfigWatcher(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, "Quick Fill"); harmony = new Harmony("kriona.QuickFill"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Quick Fill 1.5.0 loaded"); } private void Update() { watcher.Update(); } private void OnDestroy() { watcher?.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } internal static class Tooltip { public static string FillLine(string action) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.ModifierKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0) { return ""; } return Localization.instance.Localize("\n[<color=yellow><b>" + Fill.GetModifierName() + " + $KEY_Use</b></color>] " + action); } } [HarmonyPatch(typeof(Smelter), "OnHoverAddOre")] public static class SmelterOreTooltipPatch { private static void Postfix(ref string __result) { __result += Tooltip.FillLine("Fill"); } } [HarmonyPatch(typeof(Smelter), "OnHoverAddFuel")] public static class SmelterFuelTooltipPatch { private static void Postfix(Smelter __instance, ref string __result) { __result += Tooltip.FillLine("Fill with " + __instance.m_fuelItem.m_itemData.m_shared.m_name); } } [HarmonyPatch(typeof(CookingStation), "OnHoverFuelSwitch")] public static class CookingStationFuelTooltipPatch { private static void Postfix(CookingStation __instance, ref string __result) { __result += Tooltip.FillLine("Fill with " + __instance.m_fuelItem.m_itemData.m_shared.m_name); } } [HarmonyPatch(typeof(ShieldGenerator), "OnHoverAddFuel")] public static class ShieldGeneratorFuelTooltipPatch { private static void Postfix(ref string __result) { __result += Tooltip.FillLine("Fill with $piece_shieldgenerator_fuelname"); } } [HarmonyPatch(typeof(Fireplace), "GetHoverText")] public static class FireplaceTooltipPatch { private static void Postfix(Fireplace __instance, ref string __result) { if (__instance.m_canRefill && !__instance.m_infiniteFuel && __instance.m_nview.IsValid()) { __result += Tooltip.FillLine("Fill with " + __instance.m_fuelItem.m_itemData.m_shared.m_name); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace Kriona.Shared { internal class ConfigMirror { private readonly ConfigFile config; private readonly Action changed; private bool syncing; public ConfigMirror(ConfigFile config, Action changed) { this.config = config; this.changed = changed; config.SaveOnConfigSet = false; config.SettingChanged += OnSettingChanged; } public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, AcceptableValueBase acceptableValues, int? order, string displayName) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); configurationManagerAttributes.Order = order; configurationManagerAttributes.DispName = displayName; return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, new object[1] { configurationManagerAttributes })); } public void Remove(ConfigEntryBase entry) { config.Remove(entry.Definition); } public void Sync(Action apply) { syncing = true; try { apply(); } finally { syncing = false; } } public static void SetDisplayName(ConfigEntryBase entry, string displayName) { object[] tags = entry.Description.Tags; for (int i = 0; i < tags.Length; i++) { if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes) { configurationManagerAttributes.DispName = displayName; } } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { if (!syncing) { changed(); } } } internal sealed class ConfigurationManagerAttributes { public int? Order; public string DispName; } internal class ConfigWatcher : IDisposable { private const float ReloadDelay = 0.5f; private readonly string path; private readonly Action reload; private readonly ManualLogSource log; private readonly string pluginName; private readonly FileSystemWatcher watcher; private string knownContents; private volatile bool fileChanged; private float reloadTime = -1f; public ConfigWatcher(string path, Action reload, ManualLogSource log, string pluginName) { this.path = path; this.reload = reload; this.log = log; this.pluginName = pluginName; Remember(); try { watcher = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path)); watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite; watcher.Changed += delegate { fileChanged = true; }; watcher.Created += delegate { fileChanged = true; }; watcher.Renamed += delegate { fileChanged = true; }; watcher.EnableRaisingEvents = true; } catch (Exception ex) { watcher = null; log.LogWarning((object)("Couldn't watch " + path + " for changes, so changes made to it while Valheim is running aren't read: " + ex.Message)); } } public ConfigWatcher(ConfigFile config, ManualLogSource log, string pluginName) : this(config.ConfigFilePath, delegate { ReloadConfig(config); }, log, pluginName) { } private static void ReloadConfig(ConfigFile config) { bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { config.Reload(); } finally { config.SaveOnConfigSet = saveOnConfigSet; } if (saveOnConfigSet && !MatchesFile(config)) { config.Save(); } } private static bool MatchesFile(ConfigFile config) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown Dictionary<ConfigDefinition, string> dictionary = new Dictionary<ConfigDefinition, string>(); string text = string.Empty; string[] array = File.ReadAllLines(config.ConfigFilePath); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.StartsWith("#")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2); continue; } string[] array2 = text2.Split(new char[1] { '=' }, 2); if (array2.Length == 2) { dictionary[new ConfigDefinition(text, array2[0].Trim())] = array2[1].Trim(); } } foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config) { if (!dictionary.TryGetValue(item.Key, out var value)) { return false; } try { if (!object.Equals(TomlTypeConverter.ConvertToValue(value, item.Value.SettingType), item.Value.BoxedValue)) { return false; } } catch (Exception) { return false; } } return true; } public void Update() { if (fileChanged) { fileChanged = false; reloadTime = Time.realtimeSinceStartup + 0.5f; } if (reloadTime < 0f || Time.realtimeSinceStartup < reloadTime) { return; } reloadTime = -1f; string text; try { text = File.ReadAllText(path); } catch (FileNotFoundException) { return; } catch (IOException) { reloadTime = Time.realtimeSinceStartup + 0.5f; return; } if (text == knownContents) { return; } reload(); Remember(); if (pluginName != null) { log.LogInfo((object)("Reloaded " + Path.GetFileName(path))); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, pluginName + ": config reloaded", 0, (Sprite)null, false, true); } } } public void Remember() { try { knownContents = File.ReadAllText(path); } catch (IOException) { knownContents = null; } } public void Dispose() { watcher?.Dispose(); } } internal class StateEntries { public const string Inherit = "inherit"; private static readonly AcceptableValueList<string> values = new AcceptableValueList<string>(new string[3] { "inherit", "true", "false" }); private readonly ConfigMirror mirror; private readonly string help; private readonly Dictionary<string, ConfigEntry<string>> entries = new Dictionary<string, ConfigEntry<string>>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> set = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public StateEntries(ConfigMirror mirror, string help) { this.mirror = mirror; this.help = help; } public void Set(string section, string key, string displayName, bool? state) { string entryName = GetEntryName(key, displayName); if (entries.TryGetValue(key, out var value) && ((ConfigEntryBase)value).Definition.Section != section) { mirror.Remove((ConfigEntryBase)(object)value); entries.Remove(key); value = null; } if (value == null) { try { value = mirror.Bind(section, key, "inherit", "Prefab " + key + " - " + help, (AcceptableValueBase)(object)values, null, entryName); } catch (ArgumentException) { return; } entries[key] = value; } else { ConfigMirror.SetDisplayName((ConfigEntryBase)(object)value, entryName); } value.Value = Format(state); set.Add(key); } public void RemoveUnset() { List<string> list = new List<string>(); foreach (KeyValuePair<string, ConfigEntry<string>> entry in entries) { if (!set.Contains(entry.Key)) { mirror.Remove((ConfigEntryBase)(object)entry.Value); list.Add(entry.Key); } } foreach (string item in list) { entries.Remove(item); } set.Clear(); } public bool TryGetState(string key, out bool? state) { state = null; if (!entries.TryGetValue(key, out var value)) { return false; } if (bool.TryParse(value.Value, out var result)) { state = result; } return true; } public static string Format(bool? state) { if (!state.HasValue) { return "inherit"; } if (!state.Value) { return "false"; } return "true"; } private static string GetEntryName(string key, string displayName) { string text = displayName.Trim(); if (text.Length == 0 || text.Equals(key, StringComparison.OrdinalIgnoreCase)) { return key; } return text + " (" + key + ")"; } } }