Decompiled source of WeightDisplay v1.3.1

BepInEx/plugins/WeightDisplay/WeightDisplay.dll

Decompiled 4 days ago
using 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 + ")";
		}
	}
}