Decompiled source of VisualImpairmentSupport v1.2.0

VisualImpairmentSupport.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemAnnouncer;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VisualImpairmentSupport")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+ad5f0e68f16641c8e5d16faf9fdc8e611eb7cb53")]
[assembly: AssemblyProduct("VisualImpairmentSupport")]
[assembly: AssemblyTitle("VisualImpairmentSupport")]
[assembly: AssemblyVersion("1.2.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 ItemAnnouncer
{
	internal static class Announcer
	{
		private const int DuplicateWindowMs = 400;

		private static string _lastText;

		private static int _lastTick;

		internal static void OnMiddleClick(InventoryGrid grid, ItemData item)
		{
			try
			{
				if (Plugin.Ativar != null && Plugin.Ativar.Value && item != null && item.m_shared != null)
				{
					string text = BuildText(item);
					if (!string.IsNullOrWhiteSpace(text))
					{
						Speak(text);
					}
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogError((object)("ItemAnnouncer erro ao anunciar: " + ex));
				}
			}
		}

		internal static void OnRecipeMiddleClick(Recipe recipe, ItemData item)
		{
			try
			{
				if (Plugin.Ativar != null && Plugin.Ativar.Value && !((Object)(object)recipe == (Object)null))
				{
					string text = BuildRecipeText(recipe, item);
					if (!string.IsNullOrWhiteSpace(text))
					{
						Speak(text);
					}
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogError((object)("ItemAnnouncer erro ao anunciar receita: " + ex));
				}
			}
		}

		private static string BuildText(ItemData item)
		{
			string itemName = GetItemName(item);
			return Format(Plugin.Formato.Value, itemName, item.m_stack);
		}

		private static string BuildRecipeText(Recipe recipe, ItemData item)
		{
			ItemData val = item ?? (((Object)(object)recipe.m_item == (Object)null) ? null : recipe.m_item.m_itemData);
			if (val == null || val.m_shared == null)
			{
				return null;
			}
			StringBuilder stringBuilder = new StringBuilder(GetItemName(val));
			Requirement[] resources = recipe.m_resources;
			if (resources == null || resources.Length == 0)
			{
				return stringBuilder.ToString();
			}
			stringBuilder.Append(": ");
			bool flag = false;
			int num = Math.Max(1, val.m_quality);
			CraftingStation val2 = (((Object)(object)Player.m_localPlayer == (Object)null) ? null : Player.m_localPlayer.GetCurrentCraftingStation());
			bool flag2 = (Object)(object)val2 != (Object)null && val2.m_upgrader;
			Requirement[] array = resources;
			foreach (Requirement val3 in array)
			{
				if (val3 == null || (Object)(object)val3.m_resItem == (Object)null || val3.m_resItem.m_itemData == null || val3.m_upgraderResource != flag2)
				{
					continue;
				}
				int amount = val3.GetAmount(num);
				if (amount > 0)
				{
					if (flag)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append(GetItemName(val3.m_resItem.m_itemData));
					stringBuilder.Append(' ');
					stringBuilder.Append(amount);
					flag = true;
				}
			}
			return stringBuilder.ToString();
		}

		private static void Speak(string text)
		{
			int tickCount = Environment.TickCount;
			if (!(text == _lastText) || tickCount - _lastTick >= 400)
			{
				_lastText = text;
				_lastTick = tickCount;
				TtsClient.Speak(text);
			}
		}

		private static string Format(string template, string name, int count)
		{
			if (string.IsNullOrWhiteSpace(template))
			{
				template = "{name}: {count}";
			}
			return template.Replace("{name}", name).Replace("{count}", count.ToString());
		}

		private static string GetItemName(ItemData item)
		{
			string name = item.m_shared.m_name;
			string text = name;
			try
			{
				Localization instance = Localization.instance;
				if (instance != null)
				{
					text = instance.Localize(name);
				}
			}
			catch
			{
				text = name;
			}
			if (string.IsNullOrEmpty(text))
			{
				text = name;
			}
			if (!string.IsNullOrEmpty(text) && text[0] == '$')
			{
				text = text.Substring(1);
				int num = text.IndexOf('_');
				if (num >= 0 && text.StartsWith("item_", StringComparison.Ordinal))
				{
					text = text.Substring(num + 1);
				}
				text = text.Replace('_', ' ');
			}
			return text;
		}
	}
	internal static class Plugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Ativar;

		internal static ConfigEntry<string> Formato;

		internal static ConfigEntry<string> Voz;

		internal static ConfigEntry<int> Velocidade;

		internal static ConfigEntry<int> Volume;

		private static ConfigFile _config;

		internal static void Initialize(BaseUnityPlugin host, ManualLogSource logger)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			_config = host.Config;
			Log = logger;
			Ativar = host.Config.Bind<bool>("Voice", "Enabled", true, "Enable or disable voice announcements.");
			Formato = host.Config.Bind<string>("Voice", "Text", "{name}: {count}", "Spoken text. Placeholders: {name} = item name, {count} = stack quantity.");
			string[] availableVoices = TtsClient.GetAvailableVoices(logger);
			Voz = host.Config.Bind<string>("Voice", "Speech voice", "Automatic (Portuguese if available)", new ConfigDescription("Select an installed Windows speech voice. Automatic prefers Portuguese (Brazil), then uses the system default.", (AcceptableValueBase)(object)new AcceptableValueList<string>(availableVoices), Array.Empty<object>()));
			Velocidade = host.Config.Bind<int>("Voice", "Speed", 0, new ConfigDescription("Speech speed, from -10 (slow) to 10 (fast).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 10), Array.Empty<object>()));
			Volume = host.Config.Bind<int>("Voice", "Volume", 100, new ConfigDescription("Speech volume, from 0 to 100.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			TtsClient.Initialize(Log, Velocidade.Value, Volume.Value, Voz.Value);
			_config.SettingChanged += OnSettingChanged;
		}

		private static void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			TtsClient.ApplySettings(Velocidade.Value, Volume.Value, Voz.Value);
		}

		internal static void Shutdown()
		{
			if (_config != null)
			{
				_config.SettingChanged -= OnSettingChanged;
				_config = null;
			}
			TtsClient.Shutdown();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	internal static class MiddleClickItemPatch
	{
		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance)
		{
			if (Input.GetMouseButtonDown(2) && !TryAnnounceHoveredItem(Traverse.Create((object)__instance).Field("m_playerGrid").GetValue<InventoryGrid>()) && !TryAnnounceHoveredItem(Traverse.Create((object)__instance).Field("m_containerGrid").GetValue<InventoryGrid>()))
			{
				TryAnnounceHoveredRecipe(__instance);
			}
		}

		private static bool TryAnnounceHoveredItem(InventoryGrid grid)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)grid == (Object)null)
			{
				return false;
			}
			List<InventoryElement> value = Traverse.Create((object)grid).Field("m_elements").GetValue<List<InventoryElement>>();
			if (value == null)
			{
				return false;
			}
			foreach (InventoryElement item2 in value)
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					RectTransform elementRectTransform = item2.GetElementRectTransform();
					if (!((Object)(object)elementRectTransform == (Object)null) && ((Component)elementRectTransform).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(elementRectTransform, Vector2.op_Implicit(Input.mousePosition)))
					{
						Inventory inventory = grid.GetInventory();
						ItemData item = ((inventory == null) ? null : inventory.GetItemAt(item2.Position.x, item2.Position.y));
						Announcer.OnMiddleClick(grid, item);
						return true;
					}
				}
			}
			return false;
		}

		private static void TryAnnounceHoveredRecipe(InventoryGui gui)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable value = Traverse.Create((object)gui).Field("m_availableRecipes").GetValue<IEnumerable>();
			if (value == null)
			{
				return;
			}
			foreach (object item in value)
			{
				if (item != null)
				{
					GameObject value2 = Traverse.Create(item).Property("InterfaceElement", (object[])null).GetValue<GameObject>();
					RectTransform val = (RectTransform)(((Object)(object)value2 == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
					if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(val, Vector2.op_Implicit(Input.mousePosition)))
					{
						Recipe value3 = Traverse.Create(item).Property("Recipe", (object[])null).GetValue<Recipe>();
						ItemData value4 = Traverse.Create(item).Property("ItemData", (object[])null).GetValue<ItemData>();
						Announcer.OnRecipeMiddleClick(value3, value4);
						break;
					}
				}
			}
		}
	}
	internal static class TtsClient
	{
		private const string HostScriptName = "ItemAnnouncer.Speaker.ps1";

		internal const string AutomaticVoice = "Automatic (Portuguese if available)";

		private const int MaxStartFailures = 5;

		private static readonly object IoLock = new object();

		private static ManualLogSource _log;

		private static string _scriptPath;

		private static Process _process;

		private static Stream _stdin;

		private static int _startFailures;

		internal static string[] GetAvailableVoices(ManualLogSource log)
		{
			_log = log;
			SetScriptPath();
			List<string> list = new List<string> { "Automatic (Portuguese if available)" };
			if (string.IsNullOrEmpty(_scriptPath) || !File.Exists(_scriptPath))
			{
				return list.ToArray();
			}
			string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
			string text = Path.Combine(folderPath, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
			if (!File.Exists(text))
			{
				LogWarning("Windows PowerShell 5.1 was not found; using automatic voice selection only.");
				return list.ToArray();
			}
			try
			{
				ProcessStartInfo startInfo = new ProcessStartInfo
				{
					FileName = text,
					Arguments = "-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -STA -File \"" + _scriptPath + "\" -ListVoices",
					WorkingDirectory = Path.GetDirectoryName(_scriptPath),
					UseShellExecute = false,
					CreateNoWindow = true,
					RedirectStandardOutput = true,
					RedirectStandardError = true
				};
				using Process process = new Process
				{
					StartInfo = startInfo
				};
				process.Start();
				Task<string> task = process.StandardOutput.ReadToEndAsync();
				Task<string> task2 = process.StandardError.ReadToEndAsync();
				if (!process.WaitForExit(15000))
				{
					process.Kill();
					LogWarning("Timed out while listing Windows speech voices.");
					return list.ToArray();
				}
				string result = task.GetAwaiter().GetResult();
				string result2 = task2.GetAwaiter().GetResult();
				if (process.ExitCode != 0)
				{
					LogWarning("Could not list Windows speech voices: " + result2.Trim());
					return list.ToArray();
				}
				string[] array = result.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text2 in array)
				{
					try
					{
						string text3 = Encoding.UTF8.GetString(Convert.FromBase64String(text2.Trim()));
						if (!string.IsNullOrWhiteSpace(text3) && !list.Contains(text3))
						{
							list.Add(text3);
						}
					}
					catch (FormatException)
					{
						LogWarning("Ignored an invalid voice entry returned by Windows Speech.");
					}
				}
			}
			catch (Exception ex2)
			{
				LogWarning("Could not list Windows speech voices: " + ex2.Message);
			}
			return list.ToArray();
		}

		internal static void Initialize(ManualLogSource log, int rate, int volume, string voice)
		{
			_log = log;
			SetScriptPath();
			if (_scriptPath == null || !File.Exists(_scriptPath))
			{
				LogError("Script do alto-falante nao encontrado: " + (_scriptPath ?? "?"));
			}
			else if (EnsureProcess())
			{
				ApplySettings(rate, volume, voice);
			}
		}

		internal static void ApplySettings(int rate, int volume, string voice)
		{
			if (!EnsureProcess())
			{
				return;
			}
			try
			{
				SendRaw("VOICE " + CleanArgument(voice));
				SendRaw("RATE " + Clamp(rate, -10, 10));
				SendRaw("VOLUME " + Clamp(volume, 0, 100));
			}
			catch (Exception ex)
			{
				HandleFailure(ex);
			}
		}

		internal static void Speak(string text)
		{
			if (string.IsNullOrWhiteSpace(text) || !EnsureProcess())
			{
				return;
			}
			try
			{
				SendRaw("SAY " + text.Replace('\r', ' ').Replace('\n', ' '));
			}
			catch (Exception ex)
			{
				HandleFailure(ex);
			}
		}

		internal static void Shutdown()
		{
			Process process = _process;
			_process = null;
			if (process == null)
			{
				return;
			}
			try
			{
				SendRaw("QUIT");
				if (!process.WaitForExit(1200))
				{
					process.Kill();
				}
			}
			catch
			{
				try
				{
					process.Kill();
				}
				catch
				{
				}
			}
			finally
			{
				_stdin = null;
				process.Dispose();
			}
		}

		private static bool EnsureProcess()
		{
			if (_process != null && !_process.HasExited)
			{
				return true;
			}
			return StartProcess();
		}

		private static void SetScriptPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			string text = (string.IsNullOrEmpty(location) ? null : Path.GetDirectoryName(location));
			_scriptPath = (string.IsNullOrEmpty(text) ? null : Path.Combine(text, "ItemAnnouncer.Speaker.ps1"));
		}

		private static bool StartProcess()
		{
			if (_startFailures >= 5 || string.IsNullOrEmpty(_scriptPath))
			{
				return false;
			}
			string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
			string text = Path.Combine(folderPath, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
			if (!File.Exists(text))
			{
				LogError("Windows PowerShell 5.1 nao foi encontrado.");
				return false;
			}
			try
			{
				ProcessStartInfo startInfo = new ProcessStartInfo
				{
					FileName = text,
					Arguments = "-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -STA -File \"" + _scriptPath + "\"",
					WorkingDirectory = Path.GetDirectoryName(_scriptPath),
					UseShellExecute = false,
					CreateNoWindow = true,
					RedirectStandardInput = true,
					RedirectStandardOutput = true,
					RedirectStandardError = true
				};
				Process process = new Process();
				process.StartInfo = startInfo;
				process.EnableRaisingEvents = true;
				process.Exited += OnProcessExited;
				process.Start();
				_process = process;
				_stdin = process.StandardInput.BaseStream;
				StartReadLoop(process.StandardOutput.BaseStream, isError: false);
				StartReadLoop(process.StandardError.BaseStream, isError: true);
				LogInfo("Host de fala do Windows iniciado.");
				return true;
			}
			catch (Exception ex)
			{
				_startFailures++;
				_process = null;
				_stdin = null;
				LogError("Falha ao iniciar o host de fala: " + ex.Message);
				return false;
			}
		}

		private static void OnProcessExited(object sender, EventArgs e)
		{
			_process = null;
			_stdin = null;
			LogWarning("O host de fala foi encerrado; sera reiniciado no proximo anuncio.");
		}

		private static void HandleFailure(Exception ex)
		{
			LogError("Erro ao falar: " + ex.Message);
			Process process = _process;
			_process = null;
			_stdin = null;
			try
			{
				if (process != null && !process.HasExited)
				{
					process.Kill();
				}
			}
			catch
			{
			}
		}

		private static void SendRaw(string line)
		{
			lock (IoLock)
			{
				if (_stdin == null)
				{
					throw new IOException("O host de fala nao esta conectado.");
				}
				byte[] bytes = Encoding.UTF8.GetBytes(line + "\n");
				_stdin.Write(bytes, 0, bytes.Length);
				_stdin.Flush();
			}
		}

		private static string CleanArgument(string value)
		{
			return (value ?? string.Empty).Replace('\r', ' ').Replace('\n', ' ');
		}

		private static void StartReadLoop(Stream stream, bool isError)
		{
			Task.Run(delegate
			{
				try
				{
					using StreamReader streamReader = new StreamReader(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
					string text;
					while ((text = streamReader.ReadLine()) != null)
					{
						if (isError)
						{
							LogWarning("[PowerShell] " + text);
						}
						else
						{
							LogInfo("[PowerShell] " + text);
						}
					}
				}
				catch
				{
				}
			});
		}

		private static int Clamp(int value, int min, int max)
		{
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		private static void LogInfo(string message)
		{
			if (_log != null)
			{
				_log.LogInfo((object)message);
			}
		}

		private static void LogWarning(string message)
		{
			if (_log != null)
			{
				_log.LogWarning((object)message);
			}
		}

		private static void LogError(string message)
		{
			if (_log != null)
			{
				_log.LogError((object)message);
			}
		}
	}
}
namespace VisualImpairmentSupport
{
	[HarmonyPatch]
	internal static class InventoryGridUpdateGuiPatch
	{
		private const string BorderObjectName = "VisualImpairmentSupportBorder";

		private static IEnumerable<MethodBase> TargetMethods()
		{
			foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeof(InventoryGrid)))
			{
				if (declaredMethod.Name == "UpdateGui" || declaredMethod.Name == "UpdateInventory")
				{
					yield return declaredMethod;
				}
			}
		}

		[HarmonyPostfix]
		private static void Postfix(InventoryGrid __instance)
		{
			//IL_0046: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			List<InventoryElement> value = Traverse.Create((object)__instance).Field("m_elements").GetValue<List<InventoryElement>>();
			if (value == null)
			{
				return;
			}
			Inventory inventory = __instance.GetInventory();
			foreach (InventoryElement item2 in value)
			{
				if ((Object)(object)item2 == (Object)null)
				{
					continue;
				}
				ItemData item = ((inventory == null) ? null : inventory.GetItemAt(item2.Position.x, item2.Position.y));
				RectTransform elementRectTransform = item2.GetElementRectTransform();
				if (!((Object)(object)elementRectTransform == (Object)null))
				{
					Transform val = ((Transform)elementRectTransform).Find("VisualImpairmentSupportBorder");
					SlotBorderGraphic slotBorderGraphic = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponent<SlotBorderGraphic>());
					if ((Object)(object)slotBorderGraphic == (Object)null)
					{
						GameObject val2 = new GameObject("VisualImpairmentSupportBorder", new Type[3]
						{
							typeof(RectTransform),
							typeof(CanvasRenderer),
							typeof(SlotBorderGraphic)
						});
						RectTransform component = val2.GetComponent<RectTransform>();
						((Transform)component).SetParent((Transform)(object)elementRectTransform, false);
						component.anchorMin = Vector2.zero;
						component.anchorMax = Vector2.one;
						component.offsetMin = Vector2.zero;
						component.offsetMax = Vector2.zero;
						slotBorderGraphic = val2.GetComponent<SlotBorderGraphic>();
						((Graphic)slotBorderGraphic).raycastTarget = false;
					}
					((Component)slotBorderGraphic).transform.SetAsLastSibling();
					if (TryGetColor(item))
					{
						((Graphic)slotBorderGraphic).color = Color32.op_Implicit(new Color32((byte)VisualImpairmentSupportPlugin.HighlightRed.Value, (byte)VisualImpairmentSupportPlugin.HighlightGreen.Value, (byte)VisualImpairmentSupportPlugin.HighlightBlue.Value, byte.MaxValue));
						((Behaviour)slotBorderGraphic).enabled = true;
						((Graphic)slotBorderGraphic).SetVerticesDirty();
					}
					else
					{
						((Behaviour)slotBorderGraphic).enabled = false;
					}
				}
			}
		}

		private static bool TryGetColor(ItemData item)
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected I4, but got Unknown
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			switch (itemType - 3)
			{
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
			case 6:
			case 8:
			case 9:
			case 11:
			case 14:
			case 15:
			case 16:
			case 19:
			case 20:
				return true;
			default:
				return false;
			}
		}
	}
	internal sealed class SlotBorderGraphic : MaskableGraphic
	{
		private const float BorderThickness = 4f;

		protected override void OnPopulateMesh(VertexHelper vertexHelper)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			vertexHelper.Clear();
			Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
			float num = Mathf.Min(4f, Mathf.Min(((Rect)(ref pixelAdjustedRect)).width, ((Rect)(ref pixelAdjustedRect)).height) / 2f);
			UIVertex[] quad = (UIVertex[])(object)new UIVertex[4];
			AddQuad(vertexHelper, quad, ((Rect)(ref pixelAdjustedRect)).xMin, ((Rect)(ref pixelAdjustedRect)).yMax - num, ((Rect)(ref pixelAdjustedRect)).xMax, ((Rect)(ref pixelAdjustedRect)).yMax);
			AddQuad(vertexHelper, quad, ((Rect)(ref pixelAdjustedRect)).xMin, ((Rect)(ref pixelAdjustedRect)).yMin, ((Rect)(ref pixelAdjustedRect)).xMax, ((Rect)(ref pixelAdjustedRect)).yMin + num);
			AddQuad(vertexHelper, quad, ((Rect)(ref pixelAdjustedRect)).xMin, ((Rect)(ref pixelAdjustedRect)).yMin + num, ((Rect)(ref pixelAdjustedRect)).xMin + num, ((Rect)(ref pixelAdjustedRect)).yMax - num);
			AddQuad(vertexHelper, quad, ((Rect)(ref pixelAdjustedRect)).xMax - num, ((Rect)(ref pixelAdjustedRect)).yMin + num, ((Rect)(ref pixelAdjustedRect)).xMax, ((Rect)(ref pixelAdjustedRect)).yMax - num);
		}

		private void AddQuad(VertexHelper vertexHelper, UIVertex[] quad, float xMin, float yMin, float xMax, float yMax)
		{
			//IL_0001: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0033: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Color32 vertexColor = Color32.op_Implicit(((Graphic)this).color);
			quad[0] = CreateVertex(xMin, yMin, vertexColor);
			quad[1] = CreateVertex(xMin, yMax, vertexColor);
			quad[2] = CreateVertex(xMax, yMax, vertexColor);
			quad[3] = CreateVertex(xMax, yMin, vertexColor);
			vertexHelper.AddUIVertexQuad(quad);
		}

		private static UIVertex CreateVertex(float x, float y, Color32 vertexColor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			UIVertex simpleVert = UIVertex.simpleVert;
			simpleVert.position = new Vector3(x, y, 0f);
			simpleVert.color = vertexColor;
			return simpleVert;
		}
	}
	[BepInPlugin("com.visualimpairmentsupport.plugin", "Visual Impairment Support", "1.2.0")]
	public sealed class VisualImpairmentSupportPlugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.visualimpairmentsupport.plugin";

		private const string PluginName = "Visual Impairment Support";

		private const string PluginVersion = "1.2.0";

		private Harmony _harmony;

		internal static ConfigEntry<int> HighlightRed;

		internal static ConfigEntry<int> HighlightGreen;

		internal static ConfigEntry<int> HighlightBlue;

		private ConfigEntry<int> _highlightPreview;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 255);
			HighlightRed = ((BaseUnityPlugin)this).Config.Bind<int>("Important Item Highlight", "Red", 255, new ConfigDescription("Red channel of the outline color (0-255).", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			HighlightGreen = ((BaseUnityPlugin)this).Config.Bind<int>("Important Item Highlight", "Green", 31, new ConfigDescription("Green channel of the outline color (0-255).", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			HighlightBlue = ((BaseUnityPlugin)this).Config.Bind<int>("Important Item Highlight", "Blue", 31, new ConfigDescription("Blue channel of the outline color (0-255).", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			_highlightPreview = ((BaseUnityPlugin)this).Config.Bind<int>("Important Item Highlight", "Color preview", 0, new ConfigDescription("Live preview of the current outline color.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = DrawHighlightPreview,
					HideDefaultButton = true,
					Order = -1
				}
			}));
			Plugin.Initialize((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("com.visualimpairmentsupport.plugin");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Installed inventory item slot color outlines and item/recipe announcements.");
		}

		private void OnDestroy()
		{
			Plugin.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void DrawHighlightPreview(ConfigEntryBase setting)
		{
			//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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(72f, 24f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			GUI.Box(rect, GUIContent.none);
			Rect val = new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 4f, ((Rect)(ref rect)).height - 4f);
			Color color = GUI.color;
			GUI.color = Color32.op_Implicit(new Color32((byte)HighlightRed.Value, (byte)HighlightGreen.Value, (byte)HighlightBlue.Value, byte.MaxValue));
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;

		public bool? HideDefaultButton;

		public int? Order;
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "VisualImpairmentSupport";

		public const string PLUGIN_NAME = "VisualImpairmentSupport";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}