Decompiled source of OdinsBeacon v0.1.0

OdinsBeacon.dll

Decompiled 19 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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 Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("OdinsBeacon")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ce1fe04c1e0d3a2923c660dc5676ceccf87de5a5")]
[assembly: AssemblyProduct("OdinsBeacon")]
[assembly: AssemblyTitle("OdinsBeacon")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace OdinsMissingPatch
{
	[BepInPlugin("rauschekuh.odinsbeacon", "Odin's Beacon", "0.1.0")]
	public class OdinsBeaconPlugin : BaseUnityPlugin
	{
		public const string GUID = "rauschekuh.odinsbeacon";

		public const string NAME = "Odin's Beacon";

		public const string VERSION = "0.1.0";

		private static readonly Tweak[] Tweaks = new Tweak[1] { PlayerMarks.Instance };

		private void Awake()
		{
			TweakHost.Start((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, "rauschekuh.odinsbeacon", Tweaks);
		}
	}
	internal sealed class PlayerMarks : Tweak
	{
		private sealed class Mark
		{
			internal Image Fill;

			internal Image Far;

			internal Image Rings;

			internal readonly List<Image> Sparks = new List<Image>();
		}

		[HarmonyPatch(typeof(EnemyHud), "LateUpdate")]
		private static class DrawMarks
		{
			private static void Postfix(EnemyHud __instance)
			{
				Instance.Draw(__instance);
			}
		}

		internal static readonly PlayerMarks Instance = new PlayerMarks();

		private ConfigEntry<float> hideWithin;

		private ConfigEntry<float> showFrom;

		private ConfigEntry<float> farFrom;

		private ConfigEntry<float> hideBeyond;

		private ConfigEntry<float> size;

		private ConfigEntry<Color> centreColor;

		private ConfigEntry<Color> edgeColor;

		private ConfigEntry<Color> farEdgeColor;

		private ConfigEntry<bool> offScreen;

		private ConfigEntry<bool> sparks;

		private static int blockMask;

		private const float SelfHit = 0.75f;

		private readonly List<Vector3> targets = new List<Vector3>();

		private readonly List<PlayerInfo> publicPlayers = new List<PlayerInfo>();

		private readonly HashSet<ZDOID> loaded = new HashSet<ZDOID>();

		private readonly List<Mark> dots = new List<Mark>();

		private Sprite ringSprite;

		private Sprite nearSprite;

		private Sprite farSprite;

		private Sprite sparkSprite;

		private Color[] spriteColors;

		private static int sparkCount = 5;

		private static float sparkRate = 0.7f;

		private static float sparkTravel = 0.9f;

		private static float sparkSize = 0.22f;

		private const float OuterRadius = 0.97f;

		private const float DiscOverlap = 0.04f;

		private static float outlineWidth = 0.21f;

		private static float ringWidth = 0.07f;

		private static float gradientCurve = 1f;

		private static float farScale = 0.75f;

		private static Color ringColor = new Color(0.882f, 0.655f, 0.4f, 1f);

		private static Color outlineColor = new Color(0.19f, 0.13f, 0.08f, 1f);

		private static bool shapeChanged;

		private static float ruggedness = 0.2f;

		private static int bumps = 5;

		internal override string Section => "Player Marks";

		protected override string Summary => "A small round mark shows where every other player is, once they are out of sight or far enough away.";

		private PlayerMarks()
		{
		}

		protected override void Bind(ConfigFile config)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			hideWithin = config.Bind<float>(Section, "HideWithin", 10f, "Metres within which a player never gets a mark, seen or not.");
			showFrom = config.Bind<float>(Section, "ShowFrom", 50f, "Metres from which a player always gets a mark. Between HideWithin and this, only a player hidden behind terrain or a building gets one.");
			farFrom = config.Bind<float>(Section, "FarFrom", 400f, "Metres at which the mark has turned FarEdgeColor and shrunk to its smallest size.");
			hideBeyond = config.Bind<float>(Section, "HideBeyond", 0f, "Metres beyond which a player gets no mark at all. 0 shows every player, however far.");
			size = config.Bind<float>(Section, "MarkSize", 16f, new ConfigDescription("Diameter of the whole mark, rings included, in HUD units (about pixels at 1080p). Everything in it scales together.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 64f), Array.Empty<object>()));
			centreColor = config.Bind<Color>(Section, "CentreColor", new Color(0.667f, 0.502f, 0.318f, 1f), "Colour at the centre of the mark, fading out to EdgeColor.");
			edgeColor = config.Bind<Color>(Section, "EdgeColor", new Color(1f, 0.557f, 0f, 1f), "Colour at the edge of the mark, inside the rings. For a far player it moves to the centre.");
			farEdgeColor = config.Bind<Color>(Section, "FarEdgeColor", new Color(0.553f, 0.776f, 0.894f, 1f), "Colour at the edge of the mark for a player at FarFrom and beyond.");
			offScreen = config.Bind<bool>(Section, "ShowOffScreen", true, "Keep the mark of a player off screen or behind you on the screen's edge, in their direction.");
			sparks = config.Bind<bool>(Section, "Sparks", true, "Little sparks drift outward from every mark, in its edge colour.");
		}

		private void CollectTargets(Player local)
		{
			//IL_0044: 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_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_00d0: 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_00dc: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			targets.Clear();
			loaded.Clear();
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if (!((Object)(object)allPlayer == (Object)null) && !((Object)(object)allPlayer == (Object)(object)local))
				{
					loaded.Add(((Character)allPlayer).GetZDOID());
					if (!((Character)allPlayer).IsDead())
					{
						targets.Add(((Character)allPlayer).GetHeadPoint() + Vector3.up * 0.6f);
					}
				}
			}
			if (!((Object)(object)ZNet.instance != (Object)null))
			{
				return;
			}
			publicPlayers.Clear();
			ZNet.instance.GetOtherPublicPlayers(publicPlayers);
			foreach (PlayerInfo publicPlayer in publicPlayers)
			{
				if (!loaded.Contains(publicPlayer.m_characterID))
				{
					targets.Add(publicPlayer.m_position + Vector3.up * 2.4f);
				}
			}
		}

		private void Draw(EnemyHud hud)
		{
			//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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			int num = 0;
			UpdateSprites();
			Player localPlayer = Player.m_localPlayer;
			Camera mainCamera = Utils.GetMainCamera();
			if (base.On && !((Object)(object)localPlayer == (Object)null) && !((Object)(object)mainCamera == (Object)null) && !((Object)(object)hud.m_hudRoot == (Object)null) && !Minimap.IsOpen() && !InventoryGui.IsVisible())
			{
				CollectTargets(localPlayer);
				Vector3 position = ((Component)localPlayer).transform.position;
				foreach (Vector3 target in targets)
				{
					if (Place(hud, mainCamera, position, target, num))
					{
						num++;
					}
				}
			}
			for (int i = num; i < dots.Count; i++)
			{
				if (dots[i] != null && (Object)(object)dots[i].Fill != (Object)null)
				{
					((Component)dots[i].Fill).gameObject.SetActive(false);
				}
			}
		}

		private bool Place(EnemyHud hud, Camera camera, Vector3 from, Vector3 target, int index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_010d: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Distance(from, target);
			if (num < hideWithin.Value || (hideBeyond.Value > 0f && num > hideBeyond.Value))
			{
				return false;
			}
			if (num < showFrom.Value && !Blocked(((Component)camera).transform.position, target))
			{
				return false;
			}
			Vector3 val = Utils.WorldToScreenPointScaled(camera, target);
			float num2 = Mathf.InverseLerp(Mathf.Max(showFrom.Value, hideWithin.Value), farFrom.Value, num);
			float num3 = size.Value * Mathf.Lerp(1f, farScale, num2);
			Vector2 val2 = new Vector2((float)Screen.width, (float)Screen.height) * 0.5f;
			Vector2 val3 = new Vector2(val.x, val.y) - val2;
			bool num4 = val.z < 0f;
			if (num4)
			{
				val3 = -val3;
			}
			Vector2 val4 = val2 - Vector2.one * num3;
			if (num4 || Mathf.Abs(val3.x) > val4.x || Mathf.Abs(val3.y) > val4.y)
			{
				if (!offScreen.Value)
				{
					return false;
				}
				if (((Vector2)(ref val3)).sqrMagnitude < 1f)
				{
					val3 = Vector2.down;
				}
				float num5 = Mathf.Min((val3.x != 0f) ? (val4.x / Mathf.Abs(val3.x)) : float.MaxValue, (val3.y != 0f) ? (val4.y / Mathf.Abs(val3.y)) : float.MaxValue);
				val3 *= num5;
			}
			Mark mark = Dot(hud, index);
			((Graphic)mark.Far).color = new Color(1f, 1f, 1f, num2);
			((Graphic)mark.Fill).rectTransform.sizeDelta = new Vector2(num3, num3);
			((Component)mark.Fill).transform.position = Vector2.op_Implicit(val2 + val3);
			((Component)mark.Fill).gameObject.SetActive(true);
			Spark(mark, index, num3, Color.Lerp(edgeColor.Value, farEdgeColor.Value, num2));
			return true;
		}

		private void Spark(Mark mark, int index, float diameter, Color color)
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			int num = (sparks.Value ? sparkCount : 0);
			while (mark.Sparks.Count < num)
			{
				Image val = NewImage("Spark", ((Component)mark.Fill).transform, sparkSprite);
				((Component)val).transform.SetAsFirstSibling();
				mark.Sparks.Add(val);
			}
			for (int i = 0; i < mark.Sparks.Count; i++)
			{
				Image val2 = mark.Sparks[i];
				((Component)val2).gameObject.SetActive(i < num);
				if (i < num)
				{
					float num2 = Time.time * sparkRate + Hash(index * 31 + i);
					float num3 = Mathf.Floor(num2);
					float num4 = num2 - num3;
					float num5 = Hash((float)(index * 7919 + i * 131) + num3) * (float)Math.PI * 2f;
					float num6 = diameter * (0.485f + sparkTravel * num4);
					((Graphic)val2).rectTransform.anchoredPosition = new Vector2(Mathf.Cos(num5), Mathf.Sin(num5)) * num6;
					((Graphic)val2).rectTransform.sizeDelta = Vector2.one * diameter * sparkSize * (1f - 0.5f * num4);
					val2.sprite = sparkSprite;
					color.a = Step01(num4 * 6f) * (1f - num4);
					((Graphic)val2).color = color;
				}
			}
		}

		private static float Hash(float n)
		{
			float num = Mathf.Sin(n * 12.9898f) * 43758.547f;
			return num - Mathf.Floor(num);
		}

		private static bool Blocked(Vector3 eye, Vector3 target)
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (blockMask == 0)
			{
				blockMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
			}
			Vector3 val = target - eye;
			float magnitude = ((Vector3)(ref val)).magnitude;
			RaycastHit val2 = default(RaycastHit);
			if (magnitude > 0.75f && Physics.Raycast(eye, val / magnitude, ref val2, magnitude, blockMask))
			{
				return ((RaycastHit)(ref val2)).distance < magnitude - 0.75f;
			}
			return false;
		}

		private Mark Dot(EnemyHud hud, int index)
		{
			while (dots.Count <= index)
			{
				dots.Add(null);
			}
			if (dots[index] == null || (Object)(object)dots[index].Fill == (Object)null)
			{
				Image val = NewImage("OdinsMissingPatch_PlayerMark", hud.m_hudRoot.transform, nearSprite);
				((Component)val).transform.SetAsFirstSibling();
				dots[index] = new Mark
				{
					Fill = val,
					Far = Stretched(NewImage("Far", ((Component)val).transform, farSprite)),
					Rings = Stretched(NewImage("Rings", ((Component)val).transform, ringSprite))
				};
			}
			Mark mark = dots[index];
			mark.Fill.sprite = nearSprite;
			mark.Far.sprite = farSprite;
			mark.Rings.sprite = ringSprite;
			return mark;
		}

		private static Image Stretched(Image image)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)image).rectTransform.anchorMin = Vector2.zero;
			((Graphic)image).rectTransform.anchorMax = Vector2.one;
			((Graphic)image).rectTransform.sizeDelta = Vector2.zero;
			return image;
		}

		private static Image NewImage(string name, Transform parent, Sprite sprite)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private void UpdateSprites()
		{
			//IL_0014: 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_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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[3] { centreColor.Value, edgeColor.Value, farEdgeColor.Value };
			if ((Object)(object)sparkSprite == (Object)null)
			{
				sparkSprite = Draw((float r, float edge) => new Color(1f, 1f, 1f, 1f - Step01(r)), rugged: false);
			}
			if (shapeChanged || !((Object)(object)nearSprite != (Object)null) || !((Object)(object)farSprite != (Object)null) || !((Object)(object)ringSprite != (Object)null) || spriteColors == null || !(array[0] == spriteColors[0]) || !(array[1] == spriteColors[1]) || !(array[2] == spriteColors[2]))
			{
				shapeChanged = false;
				float ringRadius = 0.97f - outlineWidth;
				float hole = ringRadius - ringWidth;
				float radius = hole + 0.04f;
				Destroy(nearSprite);
				Destroy(farSprite);
				Destroy(ringSprite);
				nearSprite = Disc(array[0], array[1], radius);
				farSprite = Disc(array[1], array[2], radius);
				ringSprite = Draw(delegate(float r, float edge)
				{
					//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_0017: 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_003e: Unknown result type (might be due to invalid IL or missing references)
					Color result = Color.Lerp(outlineColor, ringColor, Inside(r, ringRadius, edge));
					result.a = Inside(r, 0.97f, edge) - Inside(r, hole, edge);
					return result;
				}, rugged: true);
				spriteColors = array;
			}
		}

		private static Sprite Disc(Color centre, Color edge, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			return Draw(delegate(float r, float width)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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_003d: Unknown result type (might be due to invalid IL or missing references)
				Color result = Color.Lerp(centre, edge, Step01(Mathf.Pow(r / radius, gradientCurve)));
				result.a = Inside(r, radius, width);
				return result;
			}, rugged: true);
		}

		private static void Destroy(Sprite sprite)
		{
			if ((Object)(object)sprite != (Object)null)
			{
				Object.Destroy((Object)(object)sprite.texture);
				Object.Destroy((Object)(object)sprite);
			}
		}

		private static float Inside(float r, float radius, float edge)
		{
			return 1f - Step01((r - radius + edge) / (2f * edge));
		}

		private static float Step01(float t)
		{
			t = Mathf.Clamp01(t);
			return t * t * (3f - 2f * t);
		}

		private static float Outline(float angle)
		{
			float num = 0.5f * Mathf.Sin((float)bumps * angle + 1.3f) + 0.3f * Mathf.Sin((float)(2 * bumps + 1) * angle + 0.4f) + 0.2f * Mathf.Sin((float)(3 * bumps + 2) * angle + 2.1f);
			return (1f + ruggedness * num) / (1f + ruggedness);
		}

		private static Sprite Draw(Func<float, float, Color> pixel, bool rugged = false)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, true);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)2;
			Vector2 val2 = default(Vector2);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					((Vector2)(ref val2))..ctor((float)j + 0.5f - 32f, (float)i + 0.5f - 32f);
					float num = ((Vector2)(ref val2)).magnitude / 32f;
					if (rugged)
					{
						num /= Outline(Mathf.Atan2(val2.y, val2.x));
					}
					val.SetPixel(j, i, pixel(num, 1f / 32f));
				}
			}
			val.Apply(true);
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}
	}
	internal static class Danger
	{
		[HarmonyPatch(typeof(Player), "RPC_OnTargeted")]
		[Serves(new Type[] { typeof(Danger) })]
		private static class NoticeEnragedEnemy
		{
			private static void Postfix(Player __instance, bool alerted)
			{
				if (alerted && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					lastEnraged = Time.time;
				}
			}
		}

		private const float CheckInterval = 0.25f;

		private const float EnragedMemory = 1.5f;

		internal const string Section = "General";

		internal static ConfigEntry<float> ThreatRadius;

		internal static ConfigEntry<bool> EnragedEnemies;

		internal static ConfigEntry<bool> BossFights;

		private static float lastCheck = float.NegativeInfinity;

		private static bool inDanger;

		private static float lastEnraged = float.NegativeInfinity;

		internal static void Bind(ConfigFile config, string effect)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			ThreatRadius = config.Bind<float>("General", "ThreatRadius", 25f, new ConfigDescription("Metres. A hostile creature closer than this puts you in combat, whether it has noticed you or not: " + effect, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			EnragedEnemies = config.Bind<bool>("General", "EnragedEnemies", true, "An enemy that has noticed you and is coming for you puts you in combat at any distance, not only inside ThreatRadius. Off means only the radius counts.");
			BossFights = config.Bind<bool>("General", "BossFights", true, "A boss health bar on screen puts you in combat, whoever the boss is after and however far away it is.");
		}

		internal static bool Near(Player player)
		{
			if (Time.time - lastCheck < 0.25f)
			{
				return inDanger;
			}
			lastCheck = Time.time;
			inDanger = Enraged() || BossBarShowing() || HostileWithin(player, ThreatRadius.Value);
			return inDanger;
		}

		private static bool Enraged()
		{
			if (EnragedEnemies.Value)
			{
				return Time.time - lastEnraged < 1.5f;
			}
			return false;
		}

		private static bool BossBarShowing()
		{
			if (BossFights.Value && (Object)(object)EnemyHud.instance != (Object)null)
			{
				return EnemyHud.instance.ShowingBossHud();
			}
			return false;
		}

		private static bool HostileWithin(Player player, float radius)
		{
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)player).transform.position;
			float num = radius * radius;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)player, allCharacter))
				{
					Vector3 val = ((Component)allCharacter).transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	internal static class FavoriteMark
	{
		internal const string Key = "OMP_Favorite";

		internal static bool IsSet(ItemData item)
		{
			if (item != null && item.m_customData != null && item.m_customData.TryGetValue("OMP_Favorite", out var value))
			{
				return value == "1";
			}
			return false;
		}
	}
	internal static class Hotkeys
	{
		internal static bool Pressed(KeyboardShortcut shortcut)
		{
			//IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			return ModifiersHeld(shortcut);
		}

		internal static bool Held(KeyboardShortcut shortcut)
		{
			//IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			return ModifiersHeld(shortcut);
		}

		internal static string Describe(params KeyboardShortcut[] chord)
		{
			//IL_000e: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			for (int i = 0; i < chord.Length; i++)
			{
				KeyboardShortcut val = chord[i];
				if ((int)((KeyboardShortcut)(ref val)).MainKey == 0)
				{
					continue;
				}
				foreach (KeyCode modifier in ((KeyboardShortcut)(ref val)).Modifiers)
				{
					list.Add(KeyName(modifier));
				}
				list.Add(KeyName(((KeyboardShortcut)(ref val)).MainKey));
			}
			return string.Join(" + ", list.ToArray());
		}

		private unsafe static string KeyName(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			string text = ZInput.KeyCodeToDisplayName(key);
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$"))
			{
				return text;
			}
			return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
		}

		private static bool ModifiersHeld(KeyboardShortcut shortcut)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class LegacyConfig
	{
		private const string OldFile = "rauschekuh.odinsmissingpatch.cfg";

		internal static HashSet<string> Sections(string path)
		{
			HashSet<string> hashSet = new HashSet<string>();
			try
			{
				if (File.Exists(path))
				{
					foreach (ConfigDefinition key in Read(path).Keys)
					{
						hashSet.Add(key.Section);
					}
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not read " + path + ": " + ex.Message));
			}
			return hashSet;
		}

		internal static void Import(ConfigFile config, HashSet<string> known)
		{
			try
			{
				string path = Path.Combine(Paths.ConfigPath, "rauschekuh.odinsmissingpatch.cfg");
				if (!File.Exists(path))
				{
					return;
				}
				Dictionary<ConfigDefinition, string> dictionary = Read(path);
				int num = 0;
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config)
				{
					if (!known.Contains(item.Key.Section) && dictionary.TryGetValue(item.Key, out var value))
					{
						item.Value.SetSerializedValue(value);
						num++;
					}
				}
				if (num > 0)
				{
					config.Save();
					TweakHost.Log.LogInfo((object)("took " + num + " setting(s) over from rauschekuh.odinsmissingpatch.cfg"));
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not read the settings of rauschekuh.odinsmissingpatch.cfg: " + ex.Message));
			}
		}

		private static Dictionary<ConfigDefinition, string> Read(string path)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> dictionary = new Dictionary<ConfigDefinition, string>();
			string text = "";
			string[] array = File.ReadAllLines(path);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2.StartsWith("#"))
				{
					continue;
				}
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					text = text2.Substring(1, text2.Length - 2);
					continue;
				}
				int num = text2.IndexOf('=');
				if (num > 0 && text.Length > 0)
				{
					dictionary[new ConfigDefinition(text, text2.Substring(0, num).Trim())] = text2.Substring(num + 1).Trim();
				}
			}
			return dictionary;
		}
	}
	internal static class Palette
	{
		internal static readonly Color Gold = new Color(1f, 0.8f, 0.3f, 1f);

		internal static readonly Color ChestYellow = new Color(1f, 0.84f, 0.3f, 1f);

		internal const string ChestYellowTag = "<color=#ffd64d>";
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class ServesAttribute : Attribute
	{
		internal readonly Type[] Tweaks;

		public bool Optional { get; set; }

		public ServesAttribute(params Type[] tweaks)
		{
			Tweaks = tweaks;
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class AlwaysAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class)]
	internal sealed class LoadHookAttribute : Attribute
	{
	}
	internal static class Patcher
	{
		private sealed class PatchClass
		{
			internal Type Type;

			internal Tweak[] Serves;

			internal bool Optional;

			internal bool LoadHook;

			internal bool Applied;

			internal bool Failed;
		}

		private static readonly List<PatchClass> classes = new List<PatchClass>();

		private static Harmony harmony;

		private static ManualLogSource log;

		internal static void Map(IList<Tweak> tweaks, ManualLogSource logSource)
		{
			log = logSource;
			Dictionary<Type, Tweak> byType = tweaks.ToDictionary((Tweak t) => t.GetType());
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (!type.IsDefined(typeof(HarmonyPatch), inherit: false))
				{
					continue;
				}
				Tweak[] array = Owners(type, byType);
				if (array != null)
				{
					classes.Add(new PatchClass
					{
						Type = type,
						Serves = array,
						Optional = type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).Cast<ServesAttribute>().Any((ServesAttribute s) => s.Optional),
						LoadHook = type.IsDefined(typeof(LoadHookAttribute), inherit: false)
					});
				}
			}
		}

		private static Tweak[] Owners(Type type, Dictionary<Type, Tweak> byType)
		{
			if (type.IsDefined(typeof(AlwaysAttribute), inherit: false))
			{
				return new Tweak[0];
			}
			ServesAttribute servesAttribute = (ServesAttribute)type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).FirstOrDefault();
			if (servesAttribute != null)
			{
				List<Tweak> list = new List<Tweak>();
				Type[] tweaks = servesAttribute.Tweaks;
				foreach (Type tweak in tweaks)
				{
					if (byType.TryGetValue(tweak, out var value))
					{
						list.Add(value);
						continue;
					}
					if (typeof(Tweak).IsAssignableFrom(tweak))
					{
						log.LogWarning((object)(type.FullName + " serves " + tweak.Name + ", which is not in the Tweaks list"));
						continue;
					}
					list.AddRange(byType.Values.Where((Tweak t) => t.Uses.Contains(tweak)));
				}
				if (list.Count <= 0)
				{
					return null;
				}
				return list.Distinct().ToArray();
			}
			Type declaringType = type.DeclaringType;
			while (declaringType != null)
			{
				if (byType.TryGetValue(declaringType, out var value2))
				{
					return new Tweak[1] { value2 };
				}
				declaringType = declaringType.DeclaringType;
			}
			log.LogWarning((object)(type.FullName + " belongs to no tweak and names none, so it is always applied"));
			return new Tweak[0];
		}

		internal static bool AnyServedOn(Type patchClass)
		{
			foreach (PatchClass @class in classes)
			{
				if (@class.Type != patchClass)
				{
					continue;
				}
				Tweak[] serves = @class.Serves;
				for (int i = 0; i < serves.Length; i++)
				{
					if (serves[i].On)
					{
						return true;
					}
				}
				return false;
			}
			return false;
		}

		internal static bool MayNeedRestart(Tweak tweak)
		{
			return classes.Any((PatchClass c) => c.LoadHook && c.Serves.Contains(tweak));
		}

		internal static void Apply(Harmony instance, IList<Tweak> tweaks)
		{
			harmony = instance;
			foreach (PatchClass @class in classes)
			{
				if (@class.Serves.Length == 0 || @class.Serves.Any((Tweak t) => t.Wanted && !t.Broken))
				{
					TryApply(@class);
				}
			}
			foreach (Tweak tweak in tweaks)
			{
				if (tweak.Wanted && !tweak.Broken)
				{
					GoLive(tweak);
				}
				tweak.Enabled.SettingChanged += delegate
				{
					SwitchedOn(tweak);
				};
			}
		}

		private static void SwitchedOn(Tweak tweak)
		{
			if (!tweak.Wanted || tweak.Patched || tweak.Broken)
			{
				return;
			}
			List<PatchClass> list = classes.Where((PatchClass c) => c.Serves.Contains(tweak) && !c.Applied && !c.Failed).ToList();
			if (list.Any((PatchClass c) => c.LoadHook))
			{
				log.LogInfo((object)(tweak.Section + " was off at launch and takes effect at the next start of the game"));
				return;
			}
			foreach (PatchClass item in list)
			{
				TryApply(item);
			}
			if (!tweak.Broken)
			{
				GoLive(tweak);
				log.LogInfo((object)(tweak.Section + " switched on"));
			}
		}

		private static void GoLive(Tweak tweak)
		{
			tweak.Patched = true;
			tweak.Refresh();
		}

		private static void TryApply(PatchClass patch)
		{
			try
			{
				harmony.CreateClassProcessor(patch.Type).Patch();
				patch.Applied = true;
			}
			catch (Exception ex)
			{
				patch.Failed = true;
				Unpatch(patch);
				string message = (ex.InnerException ?? ex).Message;
				if (patch.Serves.Length == 0 || patch.Optional)
				{
					log.LogError((object)(patch.Type.FullName + " could not be patched, carrying on without it: " + message));
					return;
				}
				Tweak[] serves = patch.Serves;
				for (int i = 0; i < serves.Length; i++)
				{
					Break(serves[i], patch.Type, message);
				}
			}
		}

		private static void Break(Tweak tweak, Type failed, string cause)
		{
			if (tweak.Broken)
			{
				return;
			}
			tweak.Broken = true;
			tweak.Patched = false;
			log.LogError((object)(tweak.Section + " is switched off: " + failed.FullName + " could not be patched, most likely because a game update changed it. " + cause));
			foreach (PatchClass @class in classes)
			{
				if (@class.Applied && @class.Serves.Contains(tweak) && !@class.Serves.Any((Tweak t) => !t.Broken && (t.Patched || t.Wanted)))
				{
					Unpatch(@class);
					@class.Applied = false;
				}
			}
			tweak.Refresh();
		}

		private static void Unpatch(PatchClass patch)
		{
			try
			{
				foreach (MethodBase item in harmony.GetPatchedMethods().ToList())
				{
					Patches patchInfo = Harmony.GetPatchInfo(item);
					if (patchInfo == null)
					{
						continue;
					}
					foreach (Patch item2 in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers)
						.Concat(patchInfo.ILManipulators)
						.ToList())
					{
						if (item2.owner == harmony.Id && item2.PatchMethod.DeclaringType == patch.Type)
						{
							harmony.Unpatch(item, item2.PatchMethod);
						}
					}
				}
			}
			catch (Exception ex)
			{
				log.LogError((object)("could not take out " + patch.Type.FullName + ": " + ex.Message));
			}
		}
	}
	internal static class Translations
	{
		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		[Always]
		private static class Load
		{
			private static void Postfix(Localization __instance, string language)
			{
				if (__instance == null || !Read() || !Reader())
				{
					return;
				}
				object obj = null;
				try
				{
					obj = textAsset.Invoke(new object[1] { csv });
					loadCsv.Invoke(__instance, new object[2]
					{
						obj,
						Has(language) ? language : "English"
					});
					Revision++;
				}
				catch (Exception ex)
				{
					TweakHost.Log.LogWarning((object)("could not load translations.csv: " + ex.Message));
				}
				finally
				{
					Object val = (Object)((obj is Object) ? obj : null);
					if (val != (Object)null)
					{
						Object.Destroy(val);
					}
				}
			}
		}

		private const string FileName = "translations.csv";

		private const string Fallback = "English";

		private static string csv;

		private static string[] languages;

		private static ConstructorInfo textAsset;

		private static MethodInfo loadCsv;

		private static bool looked;

		internal static int Revision { get; private set; }

		private static bool Read()
		{
			if (languages != null)
			{
				return csv != null;
			}
			languages = new string[0];
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "translations.csv");
				if (!File.Exists(text))
				{
					TweakHost.Log.LogDebug((object)("no translations.csv beside the DLL: " + text));
					return false;
				}
				csv = File.ReadAllText(text);
				using (StringReader stringReader = new StringReader(csv))
				{
					string text2 = stringReader.ReadLine();
					languages = ((text2 != null) ? text2.Split(new char[1] { ',' }) : new string[0]);
				}
				for (int i = 0; i < languages.Length; i++)
				{
					languages[i] = languages[i].Trim().Trim(new char[1] { '"' });
				}
			}
			catch (Exception ex)
			{
				csv = null;
				TweakHost.Log.LogWarning((object)("could not read translations.csv: " + ex.Message));
			}
			return csv != null;
		}

		private static bool Has(string language)
		{
			string[] array = languages;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] == language)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Reader()
		{
			if (looked)
			{
				if (loadCsv != null)
				{
					return textAsset != null;
				}
				return false;
			}
			looked = true;
			Type type = Type.GetType("UnityEngine.TextAsset, UnityEngine.CoreModule");
			if (type != null)
			{
				textAsset = type.GetConstructor(new Type[1] { typeof(string) });
				loadCsv = typeof(Localization).GetMethod("LoadCSV", new Type[2]
				{
					type,
					typeof(string)
				});
			}
			if (loadCsv == null || textAsset == null)
			{
				TweakHost.Log.LogWarning((object)"Localization.LoadCSV not found; the mod's words stay untranslated");
				return false;
			}
			return true;
		}
	}
	internal abstract class Tweak
	{
		private const float MinMultiplier = 0.1f;

		private const float MaxMultiplier = 20f;

		private const string RestartNote = " If it was off when the game started, switching it on may only take effect after a restart.";

		private ConfigEntry<bool> enabled;

		private readonly List<Action> settingHandlers = new List<Action>();

		internal abstract string Section { get; }

		protected abstract string Summary { get; }

		internal virtual Type[] Uses => Type.EmptyTypes;

		internal bool On
		{
			get
			{
				if (Patched)
				{
					return Wanted;
				}
				return false;
			}
		}

		internal bool Wanted
		{
			get
			{
				if (enabled != null)
				{
					return enabled.Value;
				}
				return false;
			}
		}

		internal ConfigEntry<bool> Enabled => enabled;

		internal bool Patched { get; set; }

		internal bool Broken { get; set; }

		protected virtual void Bind(ConfigFile config)
		{
		}

		internal void Setup(ConfigFile config, bool mayNeedRestart)
		{
			enabled = config.Bind<bool>(Section, "Enabled", true, Summary + (mayNeedRestart ? " If it was off when the game started, switching it on may only take effect after a restart." : ""));
			Bind(config);
		}

		internal void Refresh()
		{
			foreach (Action settingHandler in settingHandlers)
			{
				settingHandler();
			}
		}

		protected ConfigEntry<float> BindMultiplier(ConfigFile config, string key, float value, string description)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return config.Bind<float>(Section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
		}

		protected ConfigEntry<string> BindList(ConfigFile config, string key, string value, string description, Action<List<string>> apply)
		{
			ConfigEntry<string> entry = config.Bind<string>(Section, key, value, description);
			entry.SettingChanged += delegate
			{
				apply(Items(entry.Value));
			};
			apply(Items(entry.Value));
			return entry;
		}

		internal static List<string> Items(string list)
		{
			List<string> list2 = new List<string>();
			string[] array = (list ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					list2.Add(text);
				}
			}
			return list2;
		}

		protected void OnSettingChanged(ConfigFile config, Action handler)
		{
			settingHandlers.Add(handler);
			config.SettingChanged += delegate(object sender, SettingChangedEventArgs args)
			{
				if (args.ChangedSetting.Definition.Section == Section)
				{
					handler();
				}
			};
		}
	}
	internal static class TweakHost
	{
		internal static ManualLogSource Log;

		internal static BaseUnityPlugin Plugin;

		internal static void Start(BaseUnityPlugin plugin, ManualLogSource logger, ConfigFile config, string guid, Tweak[] tweaks, Action<ConfigFile> bindShared = null)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			Plugin = plugin;
			Log = logger;
			HashSet<string> known = LegacyConfig.Sections(config.ConfigFilePath);
			bindShared?.Invoke(config);
			Patcher.Map(tweaks, logger);
			foreach (Tweak tweak in tweaks)
			{
				tweak.Setup(config, Patcher.MayNeedRestart(tweak));
			}
			LegacyConfig.Import(config, known);
			Patcher.Apply(new Harmony(guid), tweaks);
			string text = string.Join(", ", (from t in tweaks
				where t.On
				select t.Section).ToArray());
			logger.LogInfo((object)((text.Length > 0) ? ("tweaks on: " + text) : "every tweak is switched off"));
		}
	}
	internal static class UiAssets
	{
		private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>();

		private static MethodInfo loadImage;

		internal static Sprite Icon(string name)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (icons.TryGetValue(name, out var value))
			{
				return value;
			}
			value = null;
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				string text = IconPath(directoryName, name);
				if (text != null)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
					if (LoadPng(val, File.ReadAllBytes(text)))
					{
						((Texture)val).filterMode = (FilterMode)1;
						value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					}
				}
				else
				{
					TweakHost.Log.LogWarning((object)("icon missing: " + name + ".png, looked in " + Path.Combine(directoryName, "icons") + " and " + directoryName));
				}
			}
			catch (Exception ex)
			{
				TweakHost.Log.LogWarning((object)("could not load icon " + name + ": " + ex.Message));
			}
			icons[name] = value;
			return value;
		}

		private static string IconPath(string dir, string name)
		{
			string path = name + ".png";
			string[] array = new string[2]
			{
				Path.Combine(Path.Combine(dir, "icons"), path),
				Path.Combine(dir, path)
			};
			foreach (string text in array)
			{
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		private static bool LoadPng(Texture2D texture, byte[] png)
		{
			if (loadImage == null)
			{
				Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
				loadImage = ((type != null) ? type.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				}) : null);
				if (loadImage == null)
				{
					TweakHost.Log.LogWarning((object)"ImageConversion.LoadImage not found; icons stay blank");
					return false;
				}
			}
			return (bool)loadImage.Invoke(null, new object[2] { texture, png });
		}

		internal static GameObject TooltipPrefab(InventoryGui gui)
		{
			InventoryGrid playerGrid = gui.m_playerGrid;
			GameObject val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.m_elementPrefab : null);
			InventoryElement val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<InventoryElement>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_tooltip != (Object)null && (Object)(object)val2.m_tooltip.m_tooltipPrefab != (Object)null)
			{
				return val2.m_tooltip.m_tooltipPrefab;
			}
			UITooltip[] componentsInChildren = ((Component)gui).GetComponentsInChildren<UITooltip>(true);
			foreach (UITooltip val3 in componentsInChildren)
			{
				if ((Object)(object)val3.m_tooltipPrefab != (Object)null)
				{
					return val3.m_tooltipPrefab;
				}
			}
			return null;
		}
	}
}