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 WeightDisplay v1.3.1
BepInEx/plugins/WeightDisplay/WeightDisplay.dll
Decompiled 4 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 TMPro; using UnityEngine; using UnityEngine.UI; [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.3.1.0")] [assembly: AssemblyInformationalVersion("1.3.1")] [assembly: AssemblyProduct("Weight Display")] [assembly: AssemblyTitle("Weight Display")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.1.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 WeightDisplay { [BepInPlugin("kriona.WeightDisplay", "Weight Display", "1.3.1")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "kriona.WeightDisplay"; public const string PluginName = "Weight Display"; public const string PluginVersion = "1.3.1"; private ConfigEntry<int> fontSize; private ConfigEntry<int> margin; private ConfigEntry<bool> showWeight; private ConfigEntry<bool> showSlots; private WarningSettings warnings; private readonly WeightLabel label = new WeightLabel(); private Harmony harmony; private ConfigWatcher watcher; private void Awake() { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown showWeight = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowWeight", true, "Show your current and maximum carry weight"); showSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowSlots", true, "Show how many inventory slots are in use"); fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "FontSize", 18, "Size of the weight text"); margin = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Margin", 6, "Gap between the minimap (or the screen corner when there is no minimap) and the text"); warnings = new WarningSettings(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; watcher = new ConfigWatcher(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, "Weight Display"); harmony = new Harmony("kriona.WeightDisplay"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Weight Display 1.3.1 loaded"); } private void Update() { watcher.Update(); } private void LateUpdate() { label.Update(fontSize.Value, margin.Value, showWeight.Value, showSlots.Value, warnings); } private void OnSettingChanged(object sender, SettingChangedEventArgs e) { label.Refresh(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; label.Destroy(); watcher?.Dispose(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } public class WarningSettings { private const string ColorHint = " - a name (black, blue, green, orange, purple, red, white, yellow) or #RRGGBB, left empty for no color"; public readonly ConfigEntry<int> WeightWarningPercent; public readonly ConfigEntry<string> WeightWarningColor; public readonly ConfigEntry<string> OverburdenedColor; public readonly ConfigEntry<int> SlotWarningOpenSlots; public readonly ConfigEntry<string> SlotWarningColor; public readonly ConfigEntry<string> FullSlotsColor; public WarningSettings(ConfigFile config) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown WeightWarningPercent = config.Bind<int>("Warnings", "WeightWarningPercent", 80, new ConfigDescription("Percentage of your maximum carry weight at which the weight takes WeightWarningColor", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); WeightWarningColor = config.Bind<string>("Warnings", "WeightWarningColor", "yellow", "Color of the weight at or above WeightWarningPercent - a name (black, blue, green, orange, purple, red, white, yellow) or #RRGGBB, left empty for no color"); OverburdenedColor = config.Bind<string>("Warnings", "OverburdenedColor", "red", "Color of the weight when you're overburdened - a name (black, blue, green, orange, purple, red, white, yellow) or #RRGGBB, left empty for no color"); SlotWarningOpenSlots = config.Bind<int>("Warnings", "SlotWarningOpenSlots", 3, new ConfigDescription("Number of open inventory slots at or below which the slot count takes SlotWarningColor", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); SlotWarningColor = config.Bind<string>("Warnings", "SlotWarningColor", "", "Color of the slot count when SlotWarningOpenSlots or fewer slots are open - a name (black, blue, green, orange, purple, red, white, yellow) or #RRGGBB, left empty for no color"); FullSlotsColor = config.Bind<string>("Warnings", "FullSlotsColor", "yellow", "Color of the slot count when every slot is in use - a name (black, blue, green, orange, purple, red, white, yellow) or #RRGGBB, left empty for no color"); } } public class WeightLabel { private const string WeightIconName = "weight_icon_32"; private TextMeshProUGUI text; private Image icon; private Sprite weightSprite; private bool iconSearched; private int shownWeight = -1; private int shownMax = -1; private int shownUsedSlots = -1; private int shownSlots = -1; public void Update(int fontSize, int margin, bool showWeight, bool showSlots, WarningSettings warnings) { Player localPlayer = Player.m_localPlayer; Hud instance = Hud.instance; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null)) { if ((Object)(object)text == (Object)null) { Create(instance); } if (!iconSearched && (Object)(object)InventoryGui.instance != (Object)null) { iconSearched = true; weightSprite = FindWeightSprite(InventoryGui.instance); Refresh(); } bool flag = (showWeight || showSlots) && !InventoryGui.IsVisible() && !Minimap.IsOpen(); if (((Component)text).gameObject.activeSelf != flag) { ((Component)text).gameObject.SetActive(flag); } if (flag) { ((TMP_Text)text).fontSize = fontSize; SetText(localPlayer, showWeight, showSlots, warnings); Position(margin); } } } public void Refresh() { shownWeight = -1; shownMax = -1; shownUsedSlots = -1; shownSlots = -1; } public void Destroy() { if ((Object)(object)text != (Object)null) { Object.Destroy((Object)(object)((Component)text).gameObject); } } private void Create(Hud hud) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("WeightDisplay", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(hud.m_rootObject.transform, false); text = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)text).font = hud.m_healthText.font; ((TMP_Text)text).fontSharedMaterial = hud.m_healthText.fontSharedMaterial; ((TMP_Text)text).alignment = (TextAlignmentOptions)260; ((TMP_Text)text).textWrappingMode = (TextWrappingModes)0; ((Graphic)text).raycastTarget = false; RectTransform rectTransform = ((TMP_Text)text).rectTransform; rectTransform.anchorMin = new Vector2(1f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(1f, 1f); rectTransform.sizeDelta = new Vector2(200f, 30f); GameObject val2 = new GameObject("WeightIcon", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); val2.SetActive(false); icon = val2.AddComponent<Image>(); icon.preserveAspect = true; ((Graphic)icon).raycastTarget = false; RectTransform rectTransform2 = ((Graphic)icon).rectTransform; rectTransform2.anchorMin = new Vector2(1f, 1f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(1f, 0.5f); Refresh(); } private static Sprite FindWeightSprite(InventoryGui gui) { Image[] componentsInChildren = ((Component)gui).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { if ((Object)(object)val.sprite != (Object)null && ((Object)val.sprite).name == "weight_icon_32") { return val.sprite; } } return null; } private void SetText(Player player, bool showWeight, bool showSlots, WarningSettings warnings) { Inventory inventory = ((Humanoid)player).GetInventory(); int num = Mathf.CeilToInt(inventory.GetTotalWeight()); int num2 = Mathf.CeilToInt(player.GetMaxCarryWeight()); int num3 = CountGridItems(inventory); int num4 = inventory.GetWidth() * inventory.GetHeight(); if (num != shownWeight || num2 != shownMax || num3 != shownUsedSlots || num4 != shownSlots) { shownWeight = num; shownMax = num2; shownUsedSlots = num3; shownSlots = num4; bool flag = showWeight && (Object)(object)weightSprite != (Object)null; string text = (flag ? "" : "Weight ") + ColorWeight(num, num2, warnings) + "/" + num2; string text2 = "⬜ " + ColorSlots(num3, num4, warnings) + "/" + num4; if (showWeight && showSlots) { ((TMP_Text)this.text).text = text + " " + text2; } else { ((TMP_Text)this.text).text = (showWeight ? text : text2); } PlaceIcon(flag); } } private static int CountGridItems(Inventory inventory) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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: Unknown result type (might be due to invalid IL or missing references) int width = inventory.GetWidth(); int height = inventory.GetHeight(); int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { Vector2i gridPos = allItem.m_gridPos; if (gridPos.x >= 0 && gridPos.y >= 0 && gridPos.x < width && gridPos.y < height) { num++; } } return num; } private void PlaceIcon(bool useIcon) { //IL_004b: 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_006b: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (!useIcon) { if (((Component)icon).gameObject.activeSelf) { ((Component)icon).gameObject.SetActive(false); } return; } icon.sprite = weightSprite; ((TMP_Text)text).ForceMeshUpdate(false, false); Bounds textBounds = ((TMP_Text)text).textBounds; float fontSize = ((TMP_Text)text).fontSize; RectTransform rectTransform = ((Graphic)icon).rectTransform; rectTransform.sizeDelta = new Vector2(fontSize, fontSize); rectTransform.anchoredPosition = new Vector2(((Bounds)(ref textBounds)).min.x - fontSize * 0.2f, ((Bounds)(ref textBounds)).center.y); if (!((Component)icon).gameObject.activeSelf) { ((Component)icon).gameObject.SetActive(true); } } private static string ColorWeight(int weight, int max, WarningSettings warnings) { if (weight > max) { return Colorize(weight, warnings.OverburdenedColor.Value); } if (weight * 100 >= max * warnings.WeightWarningPercent.Value) { return Colorize(weight, warnings.WeightWarningColor.Value); } return weight.ToString(); } private static string ColorSlots(int usedSlots, int slots, WarningSettings warnings) { if (usedSlots >= slots) { return Colorize(usedSlots, warnings.FullSlotsColor.Value); } if (slots - usedSlots <= warnings.SlotWarningOpenSlots.Value) { return Colorize(usedSlots, warnings.SlotWarningColor.Value); } return usedSlots.ToString(); } private static string Colorize(int number, string color) { if (string.IsNullOrWhiteSpace(color)) { return number.ToString(); } return "<color=" + color.Trim() + ">" + number + "</color>"; } private void Position(int margin) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0072: Expected O, but got Unknown //IL_0074: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = ((TMP_Text)text).rectTransform; Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || !instance.m_smallRoot.activeInHierarchy) { rectTransform.anchoredPosition = new Vector2((float)(-margin), (float)(-margin)); return; } Vector3[] array = (Vector3[])(object)new Vector3[4]; RectTransform rectTransform2 = ((Graphic)instance.m_mapImageSmall).rectTransform; rectTransform2.GetWorldCorners(array); Vector2 val = RectTransformUtility.WorldToScreenPoint(GetCamera((Transform)(object)rectTransform2), array[3]); RectTransform val2 = (RectTransform)((Transform)rectTransform).parent; Vector2 val3 = default(Vector2); if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, val, GetCamera((Transform)(object)val2), ref val3)) { ((Transform)rectTransform).localPosition = new Vector3(val3.x, val3.y - (float)margin, 0f); } } private static Camera GetCamera(Transform element) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)element).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) { return null; } return componentInParent.worldCamera; } } } 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 + ")"; } } }