Decompiled source of Potega Light v0.1.0

BepInEx/plugins/k942-MassFarming/MassFarming.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MassFarming")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MassFarming")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e1da477d-c14c-4355-be8f-c043e789791a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MassFarming;

[BepInPlugin("xeio.MassFarming", "MassFarming", "1.9")]
public class MassFarming : BaseUnityPlugin
{
	public static ConfigEntry<KeyboardShortcut> MassActionHotkey { get; private set; }

	public static ConfigEntry<KeyboardShortcut> ControllerPickupHotkey { get; private set; }

	public static ConfigEntry<float> MassInteractRange { get; private set; }

	public static ConfigEntry<int> PlantGridWidth { get; private set; }

	public static ConfigEntry<int> PlantGridLength { get; private set; }

	public static ConfigEntry<bool> IgnoreStamina { get; private set; }

	public static ConfigEntry<bool> IgnoreDurability { get; private set; }

	public static ConfigEntry<bool> GridAnchorWidth { get; private set; }

	public static ConfigEntry<bool> GridAnchorLength { get; private set; }

	public void Awake()
	{
		//IL_001a: 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)
		MassActionHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "MassActionHotkey", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "Mass activation hotkey for multi-pickup/multi-plant.");
		ControllerPickupHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "ControllerPickupHotkey", new KeyboardShortcut((KeyCode)334, Array.Empty<KeyCode>()), "Mass activation hotkey for multi-pickup/multi-plant for controller.");
		MassInteractRange = ((BaseUnityPlugin)this).Config.Bind<float>("Pickup", "MassInteractRange", 5f, "Range of auto-pickup.");
		PlantGridWidth = ((BaseUnityPlugin)this).Config.Bind<int>("PlantGrid", "PlantGridWidth", 5, "Grid width of auto-plant. Recommend odd-number, default is '5' so (5x5).");
		PlantGridLength = ((BaseUnityPlugin)this).Config.Bind<int>("PlantGrid", "PlantGridLength", 5, "Grid length of auto-plant. Recommend odd-number, default is '5' so (5x5).");
		IgnoreStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Plant", "IgnoreStamina", false, "Ignore stamina requirements when planting extra rows.");
		IgnoreDurability = ((BaseUnityPlugin)this).Config.Bind<bool>("Plant", "IgnoreDurability", false, "Ignore durability when planting extra rows.");
		GridAnchorWidth = ((BaseUnityPlugin)this).Config.Bind<bool>("PlantGrid", "GridAnchorWidth", true, "Planting grid anchor point (width). Default is 'enabled' so the grid will extend left and right from the crosshairs. Disable to set the anchor to the side of the grid. Disable both anchors to set to corner.");
		GridAnchorLength = ((BaseUnityPlugin)this).Config.Bind<bool>("PlantGrid", "GridAnchorLength", true, "Planting grid anchor point (length). Default is 'enabled' so the grid will extend forward and backward from the crosshairs. Disable to set the anchor to the side of the grid. Disable both anchors to set to corner.");
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}
}
[HarmonyPatch]
public static class MassPickup
{
	private static FieldInfo m_interactMaskField = AccessTools.Field(typeof(Player), "m_interactMask");

	private static MethodInfo _ExtractMethod = AccessTools.Method(typeof(Beehive), "Extract", (Type[])null, (Type[])null);

	[HarmonyPatch(typeof(Player), "Interact")]
	public static void Prefix(Player __instance, GameObject go, bool hold, bool alt)
	{
		//IL_001a: 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_0022: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: 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_016d: Unknown result type (might be due to invalid IL or missing references)
		if (((Character)__instance).InAttack() || ((Character)__instance).InDodge() || hold)
		{
			return;
		}
		KeyboardShortcut value = MassFarming.ControllerPickupHotkey.Value;
		if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
		{
			value = MassFarming.MassActionHotkey.Value;
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return;
			}
		}
		Interactable componentInParent = go.GetComponentInParent<Interactable>();
		Pickable val = (Pickable)(object)((componentInParent is Pickable) ? componentInParent : null);
		Collider[] array;
		if (val != null)
		{
			int num = (int)m_interactMaskField.GetValue(__instance);
			array = Physics.OverlapSphere(go.transform.position, MassFarming.MassInteractRange.Value, num);
			foreach (Collider obj in array)
			{
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					GameObject gameObject = ((Component)obj).gameObject;
					obj2 = ((gameObject != null) ? gameObject.GetComponentInParent<Pickable>() : null);
				}
				Pickable val2 = (Pickable)obj2;
				if (val2 != null && (Object)(object)val2 != (Object)(object)val && ((Object)val2.m_itemPrefab).name == ((Object)val.m_itemPrefab).name)
				{
					val2.Interact((Humanoid)(object)__instance, false, alt);
				}
			}
			return;
		}
		Beehive val3 = (Beehive)(object)((componentInParent is Beehive) ? componentInParent : null);
		if (val3 == null)
		{
			return;
		}
		int num2 = (int)m_interactMaskField.GetValue(__instance);
		array = Physics.OverlapSphere(go.transform.position, MassFarming.MassInteractRange.Value, num2);
		foreach (Collider obj3 in array)
		{
			object obj4;
			if (obj3 == null)
			{
				obj4 = null;
			}
			else
			{
				GameObject gameObject2 = ((Component)obj3).gameObject;
				obj4 = ((gameObject2 != null) ? gameObject2.GetComponentInParent<Beehive>() : null);
			}
			Beehive val4 = (Beehive)obj4;
			if (val4 != null && (Object)(object)val4 != (Object)(object)val3 && PrivateArea.CheckAccess(((Component)val4).transform.position, 0f, true, false))
			{
				_ExtractMethod.Invoke(val4, null);
			}
		}
	}
}
[HarmonyPatch]
public static class MassPlant
{
	private static readonly FieldInfo m_noPlacementCostField = AccessTools.Field(typeof(Player), "m_noPlacementCost");

	private static readonly FieldInfo m_placementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

	private static readonly FieldInfo m_buildPiecesField = AccessTools.Field(typeof(Player), "m_buildPieces");

	private static readonly MethodInfo _GetRightItemMethod = AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null);

	private static Vector3 placedPosition;

	private static Quaternion placedRotation;

	private static Piece placedPiece;

	private static bool placeSuccessful = false;

	private static int? massFarmingRotation = null;

	private static readonly int _plantSpaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });

	private static GameObject[] _placementGhosts = (GameObject[])(object)new GameObject[1];

	private static readonly Piece _fakeResourcePiece;

	private static bool IsHotKeyPressed
	{
		get
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = MassFarming.ControllerPickupHotkey.Value;
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				value = MassFarming.MassActionHotkey.Value;
				return Input.GetKey(((KeyboardShortcut)(ref value)).MainKey);
			}
			return true;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	public static void PlacePiecePrefix(int ___m_placeRotation)
	{
		if (IsHotKeyPressed)
		{
			int? num = massFarmingRotation;
			if (!num.HasValue)
			{
				massFarmingRotation = ___m_placeRotation;
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "PlacePiece")]
	public static void PlacePiecePostfix(Player __instance, ref bool __result, Piece piece, ref int ___m_placeRotation)
	{
		//IL_0016: 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_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)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		placeSuccessful = __result;
		if (__result)
		{
			GameObject val = (GameObject)m_placementGhostField.GetValue(__instance);
			placedPosition = val.transform.position;
			placedRotation = val.transform.rotation;
			placedPiece = piece;
		}
		if (IsHotKeyPressed)
		{
			___m_placeRotation = massFarmingRotation.Value;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	public static void UpdatePlacementPrefix(bool takeInput, float dt, ref int ___m_placeRotation)
	{
		placeSuccessful = false;
		if (IsHotKeyPressed && massFarmingRotation.HasValue)
		{
			___m_placeRotation = massFarmingRotation.Value;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "UpdatePlacement")]
	public static void UpdatePlacementPostfix(Player __instance, bool takeInput, float dt, int ___m_placeRotation)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: 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_016c: 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)
		if (IsHotKeyPressed)
		{
			massFarmingRotation = ___m_placeRotation;
		}
		if (!placeSuccessful)
		{
			return;
		}
		Plant component = ((Component)placedPiece).gameObject.GetComponent<Plant>();
		if (!Object.op_Implicit((Object)(object)component) || !IsHotKeyPressed)
		{
			return;
		}
		Heightmap val = Heightmap.FindHeightmap(placedPosition);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return;
		}
		foreach (Vector3 item in BuildPlantingGridPositions(placedPosition, component, placedRotation))
		{
			if ((placedPiece.m_cultivatedGroundOnly && !val.IsCultivated(item)) || placedPosition == item)
			{
				continue;
			}
			object? obj = _GetRightItemMethod.Invoke(__instance, Array.Empty<object>());
			ItemData val2 = (ItemData)((obj is ItemData) ? obj : null);
			if (val2 == null)
			{
				continue;
			}
			if (!MassFarming.IgnoreStamina.Value && !((Character)__instance).HaveStamina(val2.m_shared.m_attack.m_attackStamina))
			{
				Hud.instance.StaminaBarUppgradeFlash();
				break;
			}
			if (!(bool)m_noPlacementCostField.GetValue(__instance) && !__instance.HaveRequirements(placedPiece, (RequirementMode)0))
			{
				break;
			}
			if (!HasGrowSpace(item, ((Component)placedPiece).gameObject))
			{
				continue;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)placedPiece).gameObject, item, placedRotation);
			Piece component2 = val3.GetComponent<Piece>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				component2.SetCreator(__instance.GetPlayerID());
			}
			placedPiece.m_placeEffect.Create(item, placedRotation, val3.transform, 1f, -1);
			Game.instance.IncrementPlayerStat((PlayerStatType)2, 1f);
			__instance.ConsumeResources(placedPiece.m_resources, 0, -1);
			if (!MassFarming.IgnoreStamina.Value)
			{
				((Character)__instance).UseStamina(val2.m_shared.m_attack.m_attackStamina, false);
			}
			if (!MassFarming.IgnoreDurability.Value && val2.m_shared.m_useDurability)
			{
				val2.m_durability -= val2.m_shared.m_useDurabilityDrain;
				if (val2.m_durability <= 0f)
				{
					break;
				}
			}
		}
	}

	private static List<Vector3> BuildPlantingGridPositions(Vector3 originPos, Plant placedPlant, Quaternion rotation)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_005b: 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)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
		float num = placedPlant.m_growRadius * 2f;
		List<Vector3> list = new List<Vector3>(MassFarming.PlantGridWidth.Value * MassFarming.PlantGridLength.Value);
		Vector3 val = rotation * Vector3.left * num;
		Vector3 val2 = rotation * Vector3.forward * num;
		Vector3 val3 = originPos;
		if (MassFarming.GridAnchorLength.Value)
		{
			val3 -= val2 * (float)(MassFarming.PlantGridLength.Value / 2);
		}
		if (MassFarming.GridAnchorWidth.Value)
		{
			val3 -= val * (float)(MassFarming.PlantGridWidth.Value / 2);
		}
		for (int i = 0; i < MassFarming.PlantGridLength.Value; i++)
		{
			Vector3 val4 = val3;
			for (int j = 0; j < MassFarming.PlantGridWidth.Value; j++)
			{
				val4.y = ZoneSystem.instance.GetGroundHeight(val4);
				list.Add(val4);
				val4 += val;
			}
			val3 += val2;
		}
		return list;
	}

	private static bool HasGrowSpace(Vector3 newPos, GameObject go)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		Plant component = go.GetComponent<Plant>();
		if (component != null)
		{
			return Physics.OverlapSphere(newPos, component.m_growRadius, _plantSpaceMask).Length == 0;
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
	public static void SetupPlacementGhostPrefix(Player __instance, int ___m_placeRotation)
	{
		if (IsHotKeyPressed)
		{
			int? num = massFarmingRotation;
			if (!num.HasValue)
			{
				massFarmingRotation = ___m_placeRotation;
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
	public static void SetupPlacementGhostPostfix(Player __instance, ref int ___m_placeRotation)
	{
		if (IsHotKeyPressed && massFarmingRotation.HasValue)
		{
			___m_placeRotation = massFarmingRotation.Value;
		}
		DestroyGhosts();
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	public static void UpdatePlacementGhostPostfix(Player __instance, bool flashGuardStone)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_002d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (GameObject)m_placementGhostField.GetValue(__instance);
		if (!Object.op_Implicit((Object)(object)val) || !val.activeSelf)
		{
			SetGhostsActive(active: false);
			return;
		}
		KeyboardShortcut value = MassFarming.ControllerPickupHotkey.Value;
		if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
		{
			value = MassFarming.MassActionHotkey.Value;
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				SetGhostsActive(active: false);
				return;
			}
		}
		Plant component = val.GetComponent<Plant>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			SetGhostsActive(active: false);
			return;
		}
		if (!EnsureGhostsBuilt(__instance))
		{
			SetGhostsActive(active: false);
			return;
		}
		Requirement val2 = ((IEnumerable<Requirement>)val.GetComponent<Piece>().m_resources).FirstOrDefault((Func<Requirement, bool>)((Requirement r) => Object.op_Implicit((Object)(object)r.m_resItem) && r.m_amount > 0));
		_fakeResourcePiece.m_resources[0].m_resItem = val2.m_resItem;
		_fakeResourcePiece.m_resources[0].m_amount = val2.m_amount;
		float num = __instance.GetStamina();
		object? obj = _GetRightItemMethod.Invoke(__instance, Array.Empty<object>());
		ItemData val3 = (ItemData)((obj is ItemData) ? obj : null);
		if (val3 == null)
		{
			return;
		}
		Heightmap val4 = Heightmap.FindHeightmap(val.transform.position);
		List<Vector3> list = BuildPlantingGridPositions(val.transform.position, component, val.transform.rotation);
		for (int i = 0; i < _placementGhosts.Length; i++)
		{
			Vector3 val5 = list[i];
			if (val.transform.position == val5)
			{
				_placementGhosts[i].SetActive(false);
				continue;
			}
			Requirement obj2 = _fakeResourcePiece.m_resources[0];
			obj2.m_amount += val2.m_amount;
			_placementGhosts[i].transform.position = val5;
			_placementGhosts[i].transform.rotation = val.transform.rotation;
			_placementGhosts[i].SetActive(true);
			bool invalidPlacementHeightlight = false;
			if (val.GetComponent<Piece>().m_cultivatedGroundOnly && !val4.IsCultivated(val5))
			{
				invalidPlacementHeightlight = true;
			}
			else if (!HasGrowSpace(val5, val.gameObject))
			{
				invalidPlacementHeightlight = true;
			}
			else if (!MassFarming.IgnoreStamina.Value && num < val3.m_shared.m_attack.m_attackStamina)
			{
				Hud.instance.StaminaBarUppgradeFlash();
				invalidPlacementHeightlight = true;
			}
			else if (!(bool)m_noPlacementCostField.GetValue(__instance) && !__instance.HaveRequirements(_fakeResourcePiece, (RequirementMode)0))
			{
				invalidPlacementHeightlight = true;
			}
			num -= val3.m_shared.m_attack.m_attackStamina;
			_placementGhosts[i].GetComponent<Piece>().SetInvalidPlacementHeightlight(invalidPlacementHeightlight);
		}
	}

	private static bool EnsureGhostsBuilt(Player player)
	{
		int num = MassFarming.PlantGridWidth.Value * MassFarming.PlantGridLength.Value;
		if (!Object.op_Implicit((Object)(object)_placementGhosts[0]) || _placementGhosts.Length != num)
		{
			DestroyGhosts();
			if (_placementGhosts.Length != num)
			{
				_placementGhosts = (GameObject[])(object)new GameObject[num];
			}
			object? value = m_buildPiecesField.GetValue(player);
			PieceTable val = (PieceTable)((value is PieceTable) ? value : null);
			if (val != null)
			{
				GameObject selectedPrefab = val.GetSelectedPrefab();
				if (selectedPrefab != null)
				{
					if (selectedPrefab.GetComponent<Piece>().m_repairPiece)
					{
						return false;
					}
					for (int i = 0; i < _placementGhosts.Length; i++)
					{
						_placementGhosts[i] = SetupMyGhost(player, selectedPrefab);
					}
					goto IL_00a1;
				}
			}
			return false;
		}
		goto IL_00a1;
		IL_00a1:
		return true;
	}

	private static void DestroyGhosts()
	{
		for (int i = 0; i < _placementGhosts.Length; i++)
		{
			if (Object.op_Implicit((Object)(object)_placementGhosts[i]))
			{
				Object.Destroy((Object)(object)_placementGhosts[i]);
				_placementGhosts[i] = null;
			}
		}
	}

	private static void SetGhostsActive(bool active)
	{
		GameObject[] placementGhosts = _placementGhosts;
		foreach (GameObject obj in placementGhosts)
		{
			if (obj != null)
			{
				obj.SetActive(active);
			}
		}
	}

	private static GameObject SetupMyGhost(Player player, GameObject prefab)
	{
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Expected O, but got Unknown
		ZNetView.m_forceDisableInit = true;
		GameObject val = Object.Instantiate<GameObject>(prefab);
		ZNetView.m_forceDisableInit = false;
		((Object)val).name = ((Object)prefab).name;
		Joint[] componentsInChildren = val.GetComponentsInChildren<Joint>();
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren[i]);
		}
		Rigidbody[] componentsInChildren2 = val.GetComponentsInChildren<Rigidbody>();
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren2[i]);
		}
		int layer = LayerMask.NameToLayer("ghost");
		Transform[] componentsInChildren3 = val.GetComponentsInChildren<Transform>();
		for (int i = 0; i < componentsInChildren3.Length; i++)
		{
			((Component)componentsInChildren3[i]).gameObject.layer = layer;
		}
		TerrainModifier[] componentsInChildren4 = val.GetComponentsInChildren<TerrainModifier>();
		for (int i = 0; i < componentsInChildren4.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren4[i]);
		}
		GuidePoint[] componentsInChildren5 = val.GetComponentsInChildren<GuidePoint>();
		for (int i = 0; i < componentsInChildren5.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren5[i]);
		}
		Light[] componentsInChildren6 = val.GetComponentsInChildren<Light>();
		for (int i = 0; i < componentsInChildren6.Length; i++)
		{
			Object.Destroy((Object)(object)componentsInChildren6[i]);
		}
		Transform val2 = val.transform.Find("_GhostOnly");
		if (Object.op_Implicit((Object)(object)val2))
		{
			((Component)val2).gameObject.SetActive(true);
		}
		MeshRenderer[] componentsInChildren7 = val.GetComponentsInChildren<MeshRenderer>();
		foreach (MeshRenderer val3 in componentsInChildren7)
		{
			if (!((Object)(object)((Renderer)val3).sharedMaterial == (Object)null))
			{
				Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val4 = new Material(sharedMaterials[j]);
					val4.SetFloat("_RippleDistance", 0f);
					val4.SetFloat("_ValueNoise", 0f);
					sharedMaterials[j] = val4;
				}
				((Renderer)val3).sharedMaterials = sharedMaterials;
				((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
			}
		}
		return val;
	}

	static MassPlant()
	{
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Expected O, but got Unknown
		Piece val = new Piece();
		val.m_dlc = string.Empty;
		val.m_resources = (Requirement[])(object)new Requirement[1]
		{
			new Requirement()
		};
		_fakeResourcePiece = val;
	}
}

BepInEx/plugins/mchangrh-InstantMonsterDropFork/InstantMonsterDrop.dll

Decompiled 6 months ago
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Updated Fork of InstantMonsterDrop")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace InstantMonsterDrop;

[BepInPlugin("mchangrh.InstantMonsterDrop", "Instant Monster Drop", "0.6.0")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Ragdoll), "Awake")]
	private static class Ragdoll_Awake_Patch
	{
		private static void Postfix(Ragdoll __instance, ZNetView ___m_nview, EffectList ___m_removeEffect)
		{
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				((MonoBehaviour)context).StartCoroutine(DropNow(__instance, ___m_nview, ___m_removeEffect));
			}
		}
	}

	[HarmonyPatch(typeof(Ragdoll), "DestroyNow")]
	private static class Ragdoll_DestroyNow_Patch
	{
		private static bool Prefix(Ragdoll __instance)
		{
			return !modEnabled.Value;
		}
	}

	private static BepInExPlugin context;

	private static ConfigEntry<bool> modEnabled;

	private static ConfigEntry<float> dropDelay;

	private static ConfigEntry<float> destroyDelay;

	private void Awake()
	{
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		dropDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DropDelay", 0.01f, "Delay before dropping loot");
		destroyDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DestroyDelay", 0.05f, "Delay before destroying ragdoll");
		((BaseUnityPlugin)this).Config.Save();
		if (modEnabled.Value)
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}
	}

	private static IEnumerator DropNow(Ragdoll ragdoll, ZNetView nview, EffectList removeEffect)
	{
		if (dropDelay.Value < 0f)
		{
			((MonoBehaviour)context).StartCoroutine(DestroyNow(ragdoll, nview, removeEffect));
			yield break;
		}
		yield return (object)new WaitForSeconds(dropDelay.Value);
		if (modEnabled.Value && nview.IsValid() && nview.IsOwner())
		{
			Vector3 averageBodyPosition = ragdoll.GetAverageBodyPosition();
			Traverse.Create((object)ragdoll).Method("SpawnLoot", new object[1] { averageBodyPosition }).GetValue();
			((MonoBehaviour)context).StartCoroutine(DestroyNow(ragdoll, nview, removeEffect));
		}
	}

	private static IEnumerator DestroyNow(Ragdoll ragdoll, ZNetView nview, EffectList m_removeEffect)
	{
		yield return (object)new WaitForSeconds(Mathf.Max(destroyDelay.Value - dropDelay.Value, 0f));
		if (modEnabled.Value && nview.IsValid() && nview.IsOwner())
		{
			Vector3 averageBodyPosition = ragdoll.GetAverageBodyPosition();
			m_removeEffect.Create(averageBodyPosition, Quaternion.identity, (Transform)null, 1f, -1);
			ZNetScene.instance.Destroy(((Component)ragdoll).gameObject);
		}
	}
}

BepInEx/plugins/Neobotics-HUDCompass/HUDCompass.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HUDCompass")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HUDCompass")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace neobotics.ValheimMods;

internal class DebugUtils
{
	public static void ObjectInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		PropertyInfo[] properties = type.GetProperties(bindingAttr);
		foreach (PropertyInfo propertyInfo in properties)
		{
			Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}");
		}
		FieldInfo[] fields = type.GetFields(bindingAttr);
		foreach (FieldInfo field in fields)
		{
			FieldPrinter(o, type, field);
		}
	}

	public static void MethodInspector(object o)
	{
		if (o == null)
		{
			Debug.Log((object)"Object is null");
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
		Type type = o.GetType();
		Debug.Log((object)(o.ToString() + " Type " + type.Name));
		MethodInfo[] methods = type.GetMethods(bindingAttr);
		foreach (MethodInfo methodInfo in methods)
		{
			methodInfo.GetParameters();
			string arg = string.Join(", ", (from x in methodInfo.GetParameters()
				select x.ParameterType?.ToString() + " " + x.Name).ToArray());
			Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})");
		}
	}

	private static void ItemDataInspector(ItemData item)
	{
		ObjectInspector(item);
		ObjectInspector(item.m_shared);
	}

	private static void FieldPrinter(object o, Type t, FieldInfo field)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		try
		{
			if (field.FieldType == typeof(ItemData))
			{
				ItemData val = (ItemData)field.GetValue(o);
				if (val != null)
				{
					ItemDataInspector(val);
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(Transform))
			{
				Transform val2 = (Transform)field.GetValue(o);
				if ((Object)(object)val2 != (Object)null)
				{
					Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name));
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else if (field.FieldType == typeof(EffectList))
			{
				EffectList val3 = (EffectList)field.GetValue(o);
				if (val3 != null)
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:");
					EffectData[] effectPrefabs = val3.m_effectPrefabs;
					foreach (EffectData val4 in effectPrefabs)
					{
						Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name));
					}
				}
				else
				{
					Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]");
				}
			}
			else
			{
				Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}");
			}
		}
		catch (Exception)
		{
			Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name));
		}
	}

	public static void GameObjectInspector(GameObject go)
	{
		Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name));
		ObjectInspector(go);
		Component[] componentsInChildren = go.GetComponentsInChildren<Component>();
		foreach (Component val in componentsInChildren)
		{
			try
			{
				string obj = ((val != null) ? ((Object)val).name : null);
				object obj2;
				if (val == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = val.transform;
					if (transform == null)
					{
						obj2 = null;
					}
					else
					{
						Transform parent = transform.parent;
						obj2 = ((parent != null) ? ((Object)parent).name : null);
					}
				}
				Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2));
				ObjectInspector(val);
			}
			catch (Exception)
			{
			}
		}
	}

	public static void ComponentInspector(Component c)
	{
		Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name));
		ObjectInspector(c);
	}

	public static void EffectsInspector(EffectList e)
	{
		EffectData[] effectPrefabs = e.m_effectPrefabs;
		Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}");
		EffectData[] array = effectPrefabs;
		foreach (EffectData val in array)
		{
			Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}");
		}
	}

	public static void PrintInventory()
	{
		foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
		{
			Debug.Log((object)allItem.m_shared.m_name);
		}
	}

	public static void PrintAllObjects()
	{
		ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x)
		{
			Debug.Log((object)("GameObject " + ((Object)x).name));
		});
	}

	public static void PrintAllCharacters()
	{
		Character.GetAllCharacters().ForEach(delegate(Character x)
		{
			Debug.Log((object)("Character " + ((Object)x).name));
		});
	}
}
public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase
{
	private ConfigEntry<T> _entry;

	private EventHandler rootHandler;

	private Action<object, EventArgs> clientDelegate;

	private Logging Log;

	public ConfigEntry<T> ConfigEntry
	{
		get
		{
			return _entry;
		}
		set
		{
			_entry = value;
			if (_entry != null && rootHandler != null)
			{
				_entry.SettingChanged += rootHandler;
			}
			Name = ((ConfigEntryBase)_entry).Definition.Key;
			Section = ((ConfigEntryBase)_entry).Definition.Section;
			ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
			Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue);
		}
	}

	public T Value
	{
		get
		{
			return _entry.Value;
		}
		set
		{
			_entry.Value = value;
		}
	}

	public DelegatedConfigEntry(bool useServerDelegate = false)
		: this((Action<object, EventArgs>)null, useServerDelegate)
	{
	}

	public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false)
	{
		Log = Logging.GetLogger();
		Log.Trace("DelegatedConfigEntry");
		if (delegateHandler != null)
		{
			clientDelegate = delegateHandler;
		}
		if (useServerDelegate)
		{
			Log.Trace("Configuring server delegate");
			rootHandler = delegate(object s, EventArgs e)
			{
				ServerDelegate(s, e);
			};
			ServerConfiguration.ServerDelegatedEntries.Add(this);
		}
		else if (clientDelegate != null)
		{
			rootHandler = delegate(object s, EventArgs e)
			{
				clientDelegate(s, e);
			};
		}
	}

	private void ServerDelegate(object sender, EventArgs args)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		Logging.GetLogger().Trace("ServerDelegate");
		_entry.SettingChanged -= rootHandler;
		ZNet instance = ZNet.instance;
		bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null);
		if (flag.HasValue)
		{
			if (flag == false)
			{
				if (ServerValue != null)
				{
					((ConfigEntryBase)_entry).SetSerializedValue(ServerValue);
				}
			}
			else
			{
				ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue();
				ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args);
			}
		}
		if (clientDelegate != null)
		{
			clientDelegate(sender, args);
		}
		_entry.SettingChanged += rootHandler;
	}

	public void EnableHandler(bool setActive)
	{
		if (setActive)
		{
			_entry.SettingChanged += rootHandler;
		}
		else
		{
			_entry.SettingChanged -= rootHandler;
		}
	}

	public bool IsKeyPressed()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyDown()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}

	public bool IsKeyReleased()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if (ConfigEntry is ConfigEntry<KeyboardShortcut> val)
		{
			KeyboardShortcut value = val.Value;
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!Input.GetKeyUp(modifier))
				{
					return false;
				}
			}
			if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				return false;
			}
			return true;
		}
		Log.Error("Keyboard read attempted on non-KeyboardShortcut config.");
		return false;
	}
}
public class DelegatedConfigEntryBase
{
	public string Name;

	public string Section;

	public string ServerValue;
}
internal class HarmonyHelper
{
	public enum PatchType
	{
		Prefix,
		Postfix,
		Transpiler,
		Finalizer
	}

	private static Dictionary<string, string> detectionSet = new Dictionary<string, string>();

	private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>();

	public static void GetDetectionSet(Dictionary<string, string> harmonyIds)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> harmonyId in harmonyIds)
		{
			if (Harmony.HasAnyPatches(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from Harmony");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
			else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key))
			{
				logger.Debug("Detected " + harmonyId.Value + " from BepInEx");
				if (!detectionSet.ContainsKey(harmonyId.Key))
				{
					detectionSet.Add(harmonyId.Key, harmonyId.Value);
				}
			}
		}
	}

	public static void AddExclusion(string key)
	{
		if (detectionSet.ContainsKey(key))
		{
			unpatchMods.Add(key, detectionSet[key]);
		}
	}

	public static void UnpatchMods(Harmony harmony)
	{
		Logging logger = Logging.GetLogger();
		foreach (KeyValuePair<string, string> unpatchMod in unpatchMods)
		{
			logger.Warning("Not compatible with " + unpatchMod.Value);
			harmony.UnpatchAll(unpatchMod.Key);
			detectionSet.Remove(unpatchMod.Key);
			logger.Warning("Disabled " + unpatchMod.Value);
		}
	}

	public static bool IsModDetected(string key)
	{
		return detectionSet.ContainsKey(key);
	}

	public static bool IsModNameDetected(string value)
	{
		return detectionSet.ContainsValue(value);
	}

	public static bool TryGetDetectedModName(string key, out string mod)
	{
		return detectionSet.TryGetValue(key, out mod);
	}

	public static bool TryGetDetectedModKey(string value, out string key)
	{
		key = null;
		foreach (string key2 in detectionSet.Keys)
		{
			if (detectionSet[key2] == value)
			{
				key = key2;
				return true;
			}
		}
		return false;
	}

	public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null)
	{
		string text = null;
		int num = 0;
		Logging logger = Logging.GetLogger();
		foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
		{
			MethodBaseExtensions.HasMethodBody(item);
			Patches patchInfo = Harmony.GetPatchInfo(item);
			ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes;
			switch (patchType)
			{
			case PatchType.Postfix:
				readOnlyCollection = patchInfo.Postfixes;
				break;
			case PatchType.Prefix:
				readOnlyCollection = patchInfo.Prefixes;
				break;
			case PatchType.Transpiler:
				readOnlyCollection = patchInfo.Transpilers;
				break;
			case PatchType.Finalizer:
				readOnlyCollection = patchInfo.Finalizers;
				break;
			}
			foreach (Patch item2 in readOnlyCollection)
			{
				if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName))
				{
					continue;
				}
				if (patchMethodName != null)
				{
					if (item2.PatchMethod.Name == patchMethodName)
					{
						num++;
						text = item2.owner;
					}
				}
				else
				{
					num++;
					text = item2.owner;
				}
			}
			if (num == 1)
			{
				detectionSet.Add(text, modName);
				logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}");
			}
			else if (num > 1)
			{
				text = null;
				logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify.");
			}
		}
		if (num == 0)
		{
			logger.Info("No patch found for " + modName);
		}
		return text;
	}
}
public class IterativeStopwatch : Stopwatch
{
	private double startMillis;

	private Logging Log = Logging.GetLogger();

	public long Iterations { get; private set; }

	public double IterationMicroseconds { get; private set; }

	public double TotalElapsedMicroseconds { get; private set; }

	public double AverageMicroseconds { get; private set; }

	public IterativeStopwatch()
	{
		Iterations = 0L;
	}

	public new void Start()
	{
		startMillis = base.Elapsed.TotalMilliseconds;
		base.Start();
	}

	public new void Stop()
	{
		base.Stop();
		Iterations++;
		IterationMicroseconds = (base.Elapsed.TotalMilliseconds - startMillis) * 1000.0;
		TotalElapsedMicroseconds = base.Elapsed.TotalMilliseconds * 1000.0;
		AverageMicroseconds = TotalElapsedMicroseconds / (double)Iterations;
	}

	public new void Reset()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Reset();
	}

	public new void Restart()
	{
		startMillis = 0.0;
		Iterations = 0L;
		base.Restart();
	}
}
public class Logging
{
	public enum LogLevels
	{
		Critical,
		Error,
		Warning,
		Info,
		Debug,
		Trace
	}

	private static Logging _logger;

	public LogLevels LogLevel { get; set; }

	public string ModName { get; set; }

	private Logging(LogLevels level, string name)
	{
		LogLevel = level;
		ModName = name;
	}

	public static Logging GetLogger(LogLevels level, string name)
	{
		if (_logger == null)
		{
			_logger = new Logging(level, name);
		}
		return _logger;
	}

	public static Logging GetLogger()
	{
		if (_logger == null)
		{
			throw new NullReferenceException("Logger not initialized");
		}
		return _logger;
	}

	public void Trace(string msg)
	{
		if (LogLevel >= LogLevels.Trace)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Debug(string msg)
	{
		if (LogLevel >= LogLevels.Debug)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Info(string msg)
	{
		if (LogLevel >= LogLevels.Info)
		{
			Debug.Log((object)Message(msg));
		}
	}

	public void Warning(string msg)
	{
		if (LogLevel >= LogLevels.Warning)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(string msg)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Debug.LogWarning((object)Message(msg));
		}
	}

	public void Error(Exception e)
	{
		Error(e, stackTrace: false);
	}

	public void Error(Exception e, bool stackTrace)
	{
		if (LogLevel >= LogLevels.Error)
		{
			Warning(Message(e.Message));
			if (stackTrace)
			{
				Warning(e.StackTrace);
			}
		}
	}

	public void Critical(Exception e)
	{
		if (LogLevel >= LogLevels.Critical)
		{
			Debug(Message(e.Message));
			Error(e.StackTrace);
		}
	}

	private string Message(string msg)
	{
		return ModName + ": " + msg;
	}

	public static void ChangeLogging(object s, EventArgs e)
	{
		SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
		GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}");
		GetLogger().LogLevel = Cfg.debugLevel.Value;
	}
}
public class ServerConfiguration
{
	[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
	private static class ZNet_OnNewConnection_Patch
	{
		private static void Postfix(ZNet __instance, ZNetPeer peer)
		{
			Log.Debug("ZNet OnNewConnection postfix");
			if (!__instance.IsServer())
			{
				try
				{
					Log.Debug("PlayerChoice registered RPC_ClientConfigReceiver");
					peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)RPC_ClientConfigReceiver);
					return;
				}
				catch (Exception)
				{
					Log.Warning("Failed to register RPC");
					return;
				}
			}
			try
			{
				SendConfigToClient(peer);
			}
			catch (Exception)
			{
				Log.Warning("Error sending server configuration to client");
			}
		}
	}

	public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>();

	private static ConfigFile LocalConfig;

	private static BaseUnityPlugin Mod;

	private static string ConfigFileName;

	private static ServerConfiguration _instance;

	private static Logging Log;

	public static bool IsSetup = false;

	private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first.";

	public static ServerConfiguration Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ServerConfiguration();
			}
			return _instance;
		}
	}

	private ServerConfiguration()
	{
	}

	public void Setup(ConfigFile config, BaseUnityPlugin modInstance)
	{
		LocalConfig = config;
		Log = Logging.GetLogger();
		Log.Trace("ServerConfiguration Setup");
		Mod = modInstance;
		ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		IsSetup = true;
	}

	public void CreateConfigWatcher()
	{
		string configFilePath = LocalConfig.ConfigFilePath;
		string fileName = Path.GetFileName(LocalConfig.ConfigFilePath);
		Log.Trace("Configuration File Watcher Setup");
		FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(configFilePath.Substring(0, configFilePath.Length - fileName.Length), fileName);
		fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
		fileSystemWatcher.Changed += LoadConfig;
		fileSystemWatcher.Created += LoadConfig;
		fileSystemWatcher.IncludeSubdirectories = false;
		fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
		fileSystemWatcher.EnableRaisingEvents = true;
	}

	private void LoadConfig(object sender, FileSystemEventArgs e)
	{
		if (!File.Exists(LocalConfig.ConfigFilePath))
		{
			return;
		}
		try
		{
			Log.Debug($"Loading configuration {e.ChangeType}");
			LocalConfig.Reload();
		}
		catch
		{
			Log.Error("Error loading configuration file " + ConfigFileName);
		}
	}

	public static string GetPluginGuid()
	{
		return Mod.Info.Metadata.GUID;
	}

	public static void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package)
	{
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ClientConfigReceiver");
		string section;
		string name;
		while (package.GetPos() < package.Size())
		{
			section = package.ReadString();
			name = package.ReadString();
			string text = package.ReadString();
			Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage");
			DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section);
			if (delegatedConfigEntryBase != null)
			{
				Log.Trace("Found DCEB on client and setting to server value " + text);
				delegatedConfigEntryBase.ServerValue = text;
			}
			ConfigEntryBase val = LocalConfig[section, name];
			if (val != null)
			{
				Log.Trace("Found local CEB and setting underlying config value " + text);
				val.SetSerializedValue(text);
			}
		}
	}

	internal static void WriteConfigEntries(ZPackage zpkg)
	{
		foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries)
		{
			Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage");
			zpkg.Write(serverDelegatedEntry.Section);
			zpkg.Write(serverDelegatedEntry.Name);
			zpkg.Write(serverDelegatedEntry.ServerValue);
		}
	}

	internal static void SendConfigToClient(ZNetPeer peer)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
			return;
		}
		Log.Debug("ServerSendConfigToClient");
		ZPackage val = new ZPackage();
		WriteConfigEntries(val);
		peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val });
	}

	public void SendConfigToAllClients(object o, SettingChangedEventArgs e)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		if (!IsSetup)
		{
			Log.Error("ServerConfiguration not initialized. Setup first.");
		}
		else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0)
		{
			Log.Debug("SendConfigToAllClients");
			ZPackage zpkg = new ZPackage();
			WriteConfigEntries(zpkg);
			((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg));
		}
	}

	private IEnumerator Co_BroadcastConfig(ZPackage zpkg)
	{
		Log.Debug("Co_BroadcastConfig");
		List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
		foreach (ZNetPeer item in connectedPeers)
		{
			if (item != ZNet.instance.GetServerPeer())
			{
				item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg });
			}
			yield return null;
		}
	}
}
internal class Utils
{
	public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct
	{
		if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result))
		{
			return result;
		}
		return enumDefault;
	}

	public static int Guardrails(int value, int lbound, int ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static float Guardrails(float value, float lbound, float ubound)
	{
		if (value < lbound)
		{
			return lbound;
		}
		if (value > ubound)
		{
			return ubound;
		}
		return value;
	}

	public static string UnClonifiedName(string name)
	{
		if (name == null)
		{
			return null;
		}
		int num = name.IndexOf("(Clone)");
		if (num < 1)
		{
			return name;
		}
		return name.Substring(0, num);
	}

	public static void SetTranslator(int id, string idText)
	{
		typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2]
		{
			"skill_" + id,
			idText
		});
	}

	public static string GetTranslated(int id)
	{
		Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id)));
		return Localization.instance.Localize("$skill_" + id);
	}

	public static Sprite GetPrefabIcon(string prefabName)
	{
		Sprite result = null;
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
		ItemDrop val = default(ItemDrop);
		if ((Object)(object)itemPrefab != (Object)null && itemPrefab.TryGetComponent<ItemDrop>(ref val))
		{
			result = val.m_itemData.GetIcon();
		}
		return result;
	}

	public static Player GetPlayerByZDOID(ZDOID zid)
	{
		//IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			ZDOID zDOID = ((Character)allPlayer).GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(zid))
			{
				return allPlayer;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(string cid)
	{
		//IL_0016: 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)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static Character GetCharacterByZDOID(ZDOID cid)
	{
		//IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			ZDOID zDOID = allCharacter.GetZDOID();
			if (((ZDOID)(ref zDOID)).Equals(cid))
			{
				return allCharacter;
			}
		}
		return null;
	}

	public static ZNetPeer GetPeerByRPC(ZRpc rpc)
	{
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer.m_rpc == rpc)
			{
				return peer;
			}
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfType(Type t)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		List<GameObject> list = new List<GameObject>();
		Object[] array = Object.FindObjectsOfType(t);
		foreach (Object val in array)
		{
			list.Add(((Component)val).gameObject);
		}
		return list;
	}

	public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0];
	}

	public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius)
	{
		//IL_0007: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>();
		List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius);
		if (gameObjectsOfTypeInRange.Count > 0)
		{
			foreach (GameObject item in gameObjectsOfTypeInRange)
			{
				list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point)));
			}
			list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value));
			return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key);
		}
		return null;
	}

	public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		return (from x in GetGameObjectsOfType(t)
			where Vector3.Distance(x.transform.position, point) < radius
			select x).ToList();
	}

	public static float GetPointDepth(Vector3 p)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p);
	}

	public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter)
	{
		List<string> list = new List<string>();
		string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			list.Add(text.Trim());
		}
		return list;
	}

	public static float GetSolidHeight(Vector3 p)
	{
		//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_004b: Unknown result type (might be due to invalid IL or missing references)
		int solidRayMask = ZoneSystem.instance.m_solidRayMask;
		float result = 0f;
		p.y += 1000f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody))
		{
			result = ((RaycastHit)(ref val)).point.y;
		}
		return result;
	}

	public static Transform FindChild(Transform aParent, string aName)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		foreach (Transform item in aParent)
		{
			Transform val = item;
			if (((Object)val).name == aName)
			{
				return val;
			}
			Transform val2 = FindChild(val, aName);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
		}
		return null;
	}

	public static Transform FindParent(Transform go)
	{
		while ((Object)(object)go.parent != (Object)null)
		{
			go = go.parent;
		}
		return go;
	}

	public static GameObject GetPrefabByHash(int prefabHash)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found prefab in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabHash) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found prefab in Scene");
			}
		}
		return val;
	}

	public static GameObject GetPrefab(string prefabName)
	{
		GameObject val = ObjectDB.instance.GetItemPrefab(prefabName);
		Logging logger = Logging.GetLogger();
		if ((Object)(object)val != (Object)null)
		{
			logger.Debug("Found " + prefabName + " in ObjectDB");
		}
		else
		{
			ZNetScene instance = ZNetScene.instance;
			val = ((instance != null) ? instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				logger.Debug("Found " + prefabName + " in Scene");
			}
		}
		return val;
	}

	public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return null;
		}
		IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp)
		{
			KeyValuePair<K, V> keyValuePair = kvp;
			string? obj = keyValuePair.Key?.ToString();
			string text = delimc;
			keyValuePair = kvp;
			return obj + text + keyValuePair.Value;
		});
		return string.Join(delimp, values);
	}

	public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict)
	{
		if (dict == null)
		{
			return;
		}
		dict.Clear();
		string[] separator = new string[1] { delimp };
		string[] separator2 = new string[1] { delimc };
		string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries);
			if (array2.Length == 2)
			{
				dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1]));
			}
		}
	}

	public static T TypedValue<T>(object a)
	{
		return (T)Convert.ChangeType(a, typeof(T));
	}

	public static bool CopyComponentToGameObject(Component original, ref GameObject destination)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		Logging logger = Logging.GetLogger();
		Type type = ((object)original).GetType();
		logger.Debug($"Original Type is {type}");
		GameObject obj = destination;
		logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null));
		Component val = destination.GetComponent(type);
		if ((Object)(object)val == (Object)null)
		{
			val = destination.AddComponent(type);
		}
		if ((Object)(object)val == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		Component val2 = (Component)Activator.CreateInstance(type);
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Destination component is null");
			return false;
		}
		if ((Object)(object)val2 == (Object)null)
		{
			logger.Debug("Boxed component is null");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(val2, fieldInfo.GetValue(original));
		}
		val = val2;
		return true;
	}

	public static bool CopyObject(object original, object target)
	{
		Logging logger = Logging.GetLogger();
		Type type = original.GetType();
		Type type2 = target.GetType();
		if (type == null)
		{
			logger.Warning("Copy Object: Source object is null");
			Activator.CreateInstance(type);
			return false;
		}
		if (type2 == null)
		{
			logger.Warning("Copy Object: Destination object is null");
			return false;
		}
		if (type2 != type)
		{
			logger.Warning("Copy Object: Source and destination components are different types");
			return false;
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			fieldInfo.SetValue(target, fieldInfo.GetValue(original));
		}
		return true;
	}
}
public class ImageHelper
{
	private string resources;

	private bool isEmbedded;

	private Logging logger;

	public ImageHelper(string resourceLocation, bool embedded)
	{
		resources = resourceLocation;
		logger = Logging.GetLogger();
		isEmbedded = embedded;
	}

	public Sprite LoadSprite(string name, int width, int height, bool linear = false, float pixelsPerUnit = 100f)
	{
		logger.Debug("Reading image and creating sprite " + name);
		if (TryLoadImage(name, width, height, linear, out var image))
		{
			return LoadSprite(image, pixelsPerUnit);
		}
		return null;
	}

	public Sprite LoadSprite(Texture2D texture, float pixelsPerUnit = 100f)
	{
		return LoadSprite(texture, ((Object)texture).name, ((Texture)texture).width, ((Texture)texture).height, pixelsPerUnit);
	}

	public Sprite LoadSprite(Texture2D texture, string name, float width, float height, float pixelsPerUnit = 100f)
	{
		//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)
		if ((Object)(object)texture == (Object)null)
		{
			return null;
		}
		if (Utility.IsNullOrWhiteSpace(name))
		{
			name = ((Object)texture).name;
		}
		logger.Debug("Creating sprite " + name + " from existing texture");
		Sprite obj = Sprite.Create(texture, new Rect(0f, 0f, width, height), Vector2.zero, pixelsPerUnit);
		if ((Object)(object)obj == (Object)null)
		{
			throw new ApplicationException("Can't create sprite " + name);
		}
		((Object)obj).name = name;
		return obj;
	}

	public bool TryLoadImage(string name, int width, int height, bool linear, out Texture2D image)
	{
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		image = null;
		logger.Debug("Loading image from " + resources + "." + name);
		Stream stream = null;
		if (isEmbedded)
		{
			stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resources + "." + name);
		}
		else
		{
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string text = string.Empty;
			if (!Utility.IsNullOrWhiteSpace(resources))
			{
				text = resources;
				text.Replace('\\', '/');
				text.Replace('/', directorySeparatorChar);
			}
			if (!text.EndsWith("/"))
			{
				text += directorySeparatorChar;
			}
			stream = new FileStream(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + text + name, FileMode.Open, FileAccess.Read);
		}
		if (stream == null)
		{
			throw new FileNotFoundException("Can't find " + name + " in " + resources);
		}
		byte[] array = new byte[stream.Length];
		stream.Read(array, 0, (int)stream.Length);
		Texture2D val = new Texture2D(width, height, (TextureFormat)4, true, linear);
		logger.Debug("Loading image " + name);
		if (ImageConversion.LoadImage(val, array, false))
		{
			image = val;
			return true;
		}
		throw new FileLoadException("Can't load " + name);
	}
}
internal class Cfg
{
	public static DelegatedConfigEntry<bool> enableCompass;

	public static DelegatedConfigEntry<bool> showHideCompass;

	public static DelegatedConfigEntry<KeyboardShortcut> compassToggle;

	public static ConfigEntry<Color> colorCompass = null;

	public static ConfigEntry<Color> colorPins = null;

	public static ConfigEntry<Color> colorCenterMark = null;

	public static ConfigEntry<bool> compassUsePlayerDirection = null;

	public static ConfigEntry<int> compassYOffset = null;

	public static ConfigEntry<float> compassScale = null;

	public static ConfigEntry<float> scalePinsMin = null;

	public static ConfigEntry<float> scalePins = null;

	public static ConfigEntry<bool> compassShowCenterMark = null;

	public static ConfigEntry<bool> useDynamicColorsOnCompass = null;

	public static DelegatedConfigEntry<string> ignoredPinNames;

	public static DelegatedConfigEntry<string> ignoredPinTypes;

	public static DelegatedConfigEntry<string> alwaysVisible;

	public static DelegatedConfigEntry<int> distancePinsMin;

	public static DelegatedConfigEntry<int> distancePinsMax;

	public static DelegatedConfigEntry<HUDCompass.PlayerPinBehavior> playerPinBehavior;

	public static DelegatedConfigEntry<bool> compassShowMyPlayerPin;

	public static DelegatedConfigEntry<bool> showShips;

	public static DelegatedConfigEntry<bool> showCarts;

	public static DelegatedConfigEntry<bool> showPortals;

	public static DelegatedConfigEntry<bool> showDynamicPinsOnMap;

	public static DelegatedConfigEntry<bool> showDynamicPinsOnCompass;

	public static DelegatedConfigEntry<float> playerPinUpdateInterval;

	public static ConfigEntry<bool> showTypeOnMinimap = null;

	public static ConfigEntry<bool> showPortalNamesOnMinimap = null;

	public static ConfigEntry<Color> activePortalColor = null;

	public static ConfigEntry<Color> portalColor = null;

	public static ConfigEntry<Color> shipColor = null;

	public static ConfigEntry<Color> cartColor = null;

	public static ConfigEntry<bool> useExternalImages = null;

	public static DelegatedConfigEntry<Logging.LogLevels> debugLevel;

	private static KeyCode[] keyModifiers = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };

	public static KeyboardShortcut keyConfigItemDefault = new KeyboardShortcut((KeyCode)99, keyModifiers);

	public static void BepInExConfig(BaseUnityPlugin _instance)
	{
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Expected O, but got Unknown
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Expected O, but got Unknown
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Expected O, but got Unknown
		//IL_056c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0655: Unknown result type (might be due to invalid IL or missing references)
		enableCompass = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_EnableCompass, useServerDelegate: true);
		showHideCompass = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_ShowCompass);
		compassToggle = new DelegatedConfigEntry<KeyboardShortcut>();
		ignoredPinNames = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_IgnoredNames, useServerDelegate: true);
		ignoredPinTypes = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_IgnoredTypes, useServerDelegate: true);
		alwaysVisible = new DelegatedConfigEntry<string>(HUDCompass.SettingChanged_VisibleBehavior, useServerDelegate: true);
		distancePinsMin = new DelegatedConfigEntry<int>(useServerDelegate: true);
		distancePinsMax = new DelegatedConfigEntry<int>(useServerDelegate: true);
		playerPinBehavior = new DelegatedConfigEntry<HUDCompass.PlayerPinBehavior>(HUDCompass.SettingChanged_PlayerPinBehavior, useServerDelegate: true);
		compassShowMyPlayerPin = new DelegatedConfigEntry<bool>(HUDCompass.SettingChanged_ShowMyPlayerPin);
		showShips = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showCarts = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showPortals = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showDynamicPinsOnMap = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		showDynamicPinsOnCompass = new DelegatedConfigEntry<bool>(useServerDelegate: true);
		playerPinUpdateInterval = new DelegatedConfigEntry<float>(useServerDelegate: true);
		debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(Logging.ChangeLogging);
		debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Z - Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log");
		Logging.GetLogger().LogLevel = debugLevel.Value;
		useExternalImages = _instance.Config.Bind<bool>("Z - Utility", "Use External Images", false, "Compass and dynamic markers will use images located in the mod folder, which can be customized");
		enableCompass.ConfigEntry = _instance.Config.Bind<bool>("A - HUD Compass", "Enable Compass", true, "Enable or Disable the Compass HUD.@");
		showHideCompass.ConfigEntry = _instance.Config.Bind<bool>("A - HUD Compass", "Show Compass", true, "Show or Hide the HUD compass. Use the Toggle Compass key to change in-game.");
		compassUsePlayerDirection = _instance.Config.Bind<bool>("B - Compass Display", "Use Player Direction", false, "Orient the compass based on the direction the player is facing, rather than the middle of the screen.");
		compassScale = _instance.Config.Bind<float>("B - Compass Display", "Compass Scale", 0.75f, new ConfigDescription("Sets the overall scale of the compass on the screen", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
		compassYOffset = _instance.Config.Bind<int>("B - Compass Display", "Offset (Y)", 0, "Offset from the top of the screen in pixels.");
		distancePinsMin.ConfigEntry = _instance.Config.Bind<int>("B - Compass Display", "Distance (Minimum)", 1, "Minimum distance from pin to show on compass.@");
		distancePinsMax.ConfigEntry = _instance.Config.Bind<int>("B - Compass Display", "Distance (Maximum)", 300, "Maximum distance from pin to show on compass.@");
		playerPinBehavior.ConfigEntry = _instance.Config.Bind<HUDCompass.PlayerPinBehavior>("B - Compass Display", "Player Pin Visibility", HUDCompass.PlayerPinBehavior.PlayerChoice, "Force player pins (multiplayer) to appear or not appear on the compass and map, or let the player decide. Overrides Show My Player Pin if not set to PlayerChoice.@");
		compassShowMyPlayerPin.ConfigEntry = _instance.Config.Bind<bool>("B - Compass Display", "Show My Player Pin", true, "Shows or hides your player pin (multiplayer) on the compass if playing no-map where visibility setting is not available. Overriden by server if Player Pin Behavior is not set to PlayerChoice.");
		scalePins = _instance.Config.Bind<float>("B - Compass Display", "Pins Scale", 1f, new ConfigDescription("Sets the overall scale of the pins on the on the screen", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
		scalePinsMin = _instance.Config.Bind<float>("B - Compass Display", "Minimum Pin Size", 0.25f, "Enlarge or shrink the scale of the pins at their furthest visible distance.");
		compassShowCenterMark = _instance.Config.Bind<bool>("B - Compass Display", "Show Center Mark", false, "(Optional) Show center mark graphic.");
		ignoredPinNames.ConfigEntry = _instance.Config.Bind<string>("C - Ignore", "Pin Names", "Silver,Obsidian,Copper,Tin", "Ignore location pins with these names (comma separated, no spaces). End a string with asterisk (*) to denote a prefix.@");
		ignoredPinTypes.ConfigEntry = _instance.Config.Bind<string>("C - Ignore", "Pin Types", "Shout,Ping", "Ignore location pins of these types (comma separated, no spaces). Types include: Icon0,Icon1,Icon2,Icon3,Icon4,Death,Bed,Shout,None,Boss,Player,RandomEvent,Ping,EventArea.@");
		colorCompass = _instance.Config.Bind<Color>("E - Compass Colors", "Compass Color", Color.white, "(Optional) Adjust the main color of the compass.");
		colorPins = _instance.Config.Bind<Color>("E - Compass Colors", "Pin Color", Color.white, "(Optional) Adjust the color of the location pins on the compass.");
		colorCenterMark = _instance.Config.Bind<Color>("E - Compass Colors", "Center Mark Color", Color.yellow, "(Optional) Adjust the color of the center mark graphic.");
		showDynamicPinsOnMap.ConfigEntry = _instance.Config.Bind<bool>("F - Dynamic Pins", "Show dynamic pins on map", true, "Display pins for ships, carts and portals on the main and minimap. Controlled individually below.@");
		showDynamicPinsOnCompass.ConfigEntry = _instance.Config.Bind<bool>("F - Dynamic Pins", "Show dynamic pins on compass", true, "Display pins for ships, carts and portals on the compass. Controlled individually below.@");
		playerPinUpdateInterval.ConfigEntry = _instance.Config.Bind<float>("F - Dynamic Pins", "Player pin refresh pin interval", 2f, new ConfigDescription("Interval in seconds between refresh of player pins on map and compass. Decrease for 'smoother' updates of player pins. Zero refreshes every frame. NOTE: Valheim default for Player pin refresh is 2 seconds. Decreasing can reduce multiplayer performance.@", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		showShips.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Ships", true, "Show ships on the map and compass.@");
		showCarts.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Carts", true, "Show carts on the map and compass.@");
		showPortals.ConfigEntry = _instance.Config.Bind<bool>("G - Dynamic Types", "Show Portals", true, "Show portals on the map and compass.@");
		showTypeOnMinimap = _instance.Config.Bind<bool>("H - Dynamic Names", "Show dynamic types on minimap", false, "Show boat and cart types (i.e., Raft, Karve, Longship) on the Minimap.");
		showPortalNamesOnMinimap = _instance.Config.Bind<bool>("H - Dynamic Names", "Show portal names on minimap", false, "Show portal names on the Minimap.");
		activePortalColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Active portal color on map", new Color(255f, 153f, 51f), "Color of portal icons with active connections.");
		portalColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Portal color", Color.white, "Color of portal icons on map.");
		shipColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Ship color", Color.yellow, "Color of ship icons on map.");
		cartColor = _instance.Config.Bind<Color>("I - Dynamic Map Colors", "Cart color", Color.cyan, "Color of cart icons on map.");
		useDynamicColorsOnCompass = _instance.Config.Bind<bool>("I - Dynamic Map Colors", "Use colors on compass", false, "Use colors for dynamic pins on the compass");
		alwaysVisible.ConfigEntry = _instance.Config.Bind<string>("J - Visibility", "Always Visible", "", "Always display pins of these types or names (comma separated, no spaces) at full size regardless of distance.@");
		compassToggle = new DelegatedConfigEntry<KeyboardShortcut>();
		compassToggle.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("A - HUD Compass", "Toggle Compass Key", keyConfigItemDefault, "Key used in-game to toggle the compass visibility.");
	}
}
public enum MarkerGroup
{
	Ship,
	Cart,
	Portal,
	ActivePortal
}
public class DynamicMapMarkers
{
	[HarmonyPatch(typeof(ZNetScene), "OnZDODestroyed")]
	private static class ZNetScene_OnZDODestroyed_Patch
	{
		[HarmonyPrefix]
		private static void ZNetScene_OnZDODestroyed_Prefix(ZDO zdo)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("ZNetScene_OnZDODestroyed_Patch_Prefix");
			if (s_dmm.Markers.ContainsKey(zdo.m_uid))
			{
				MarkerData markerData = s_dmm.Markers[zdo.m_uid];
				markerData.ZDO = null;
				markerData.Type = null;
				if ((Object)(object)markerData.Marker != (Object)null)
				{
					Object.Destroy((Object)(object)markerData.Marker);
				}
				if ((Object)(object)markerData.Nametag != (Object)null)
				{
					Object.Destroy((Object)(object)markerData.Nametag);
				}
				s_dmm.Markers.Remove(zdo.m_uid);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class Player_OnSpawned_Patch
	{
		[HarmonyPostfix]
		private static void Player_OnSpawned_Postfix(Player __instance)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Debug("Player_OnSpawned_Patch_Postfix");
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			BuildDynamicMarkerTypes();
			s_dmm.DestroyMarkers();
			List<ZDO> list = new List<ZDO>();
			foreach (MarkerType markerType in s_dmm.MarkerTypes)
			{
				GetAllZDOsWithPrefab(markerType.Prefab, list);
				foreach (ZDO item in list)
				{
					MarkerData markerData = new MarkerData();
					markerData.ZDO = item;
					markerData.Type = markerType;
					markerData.Creator = item.GetLong(ZDOVars.s_creator, 0L);
					markerData.IsActivePortal = false;
					if (!s_dmm.Markers.ContainsKey(item.m_uid))
					{
						s_dmm.Markers.Add(item.m_uid, markerData);
					}
				}
				list.Clear();
			}
		}
	}

	[HarmonyPatch(typeof(ZNetScene), "AddInstance")]
	private static class ZNetScene_AddInstance_Patch
	{
		[HarmonyPostfix]
		private static void ZNetScene_AddInstance_Postfix(ZDO zdo)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("ZNetScene_AddInstance_Patch_Postfix");
			foreach (MarkerType markerType in s_dmm.MarkerTypes)
			{
				if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode(markerType.Prefab) && !s_dmm.Markers.ContainsKey(zdo.m_uid))
				{
					MarkerData markerData = new MarkerData();
					markerData.ZDO = zdo;
					markerData.Type = markerType;
					markerData.IsActivePortal = false;
					markerData.Creator = zdo.GetLong(ZDOVars.s_creator, HUDCompass.s_localPlayerID);
					if (!s_dmm.Markers.ContainsKey(zdo.m_uid))
					{
						s_dmm.Markers.Add(zdo.m_uid, markerData);
					}
					break;
				}
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "SendPeriodicData")]
	private static class ZNet_SendPeriodicData_Patch
	{
		[HarmonyPrefix]
		private static bool ZNet_SendPeriodicData_Prefix(ZNet __instance, float dt)
		{
			HUDCompass.Log.Trace("ZNet_SendPeriodicData_Patch_Prefix");
			dmm_playerPinPeriodicTimer += dt;
			if (dmm_playerPinPeriodicTimer < Cfg.playerPinUpdateInterval.Value)
			{
				return true;
			}
			dmm_playerPinPeriodicTimer = 0f;
			if (__instance.IsServer())
			{
				__instance.SendNetTime();
				__instance.SendPlayerList();
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Minimap), "UpdatePins")]
	private static class Minimap_UpdatePins_Patch
	{
		[HarmonyPostfix]
		private static void Minimap_UpdatePins_Postfix(Minimap __instance, float ___m_largeZoom)
		{
			//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)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Trace("Minimap_UpdatePins_Patch_Postfix");
			s_dmm.PinData.Clear();
			if (s_dmm.Markers.Count <= 0 || !((Object)(object)Minimap.instance?.m_largeRoot != (Object)null))
			{
				return;
			}
			RawImage val = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_mapImageLarge : Minimap.instance.m_mapImageSmall);
			float size = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_pinSizeLarge : Minimap.instance.m_pinSizeSmall);
			RectTransform parent = (Minimap.instance.m_largeRoot.activeSelf ? Minimap.instance.m_pinRootLarge : Minimap.instance.m_pinRootSmall);
			foreach (MarkerData value in s_dmm.Markers.Values)
			{
				bool flag = IsInControlByPlayer(value.ZDO);
				Vector3 position = value.ZDO.GetPosition();
				value.IsActivePortal = value.Type.Prefab == "portal_wood" && value.ZDO.GetConnectionZDOID((ConnectionType)1) != ZDOID.None;
				if (Cfg.showDynamicPinsOnCompass.Value && value.Type.Show && !flag)
				{
					PinData item = s_dmm.MarkerToPinData(value);
					if (!s_dmm.PinData.Contains(item))
					{
						s_dmm.PinData.Add(item);
					}
				}
				if (Cfg.showDynamicPinsOnMap.Value && value.Type.Show && !flag && IsPointVisible(position, val))
				{
					DrawMarker(value, size, parent, val, ___m_largeZoom, Minimap.instance.m_largeRoot.activeSelf);
				}
				else
				{
					MarkerData.Destroy(value);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Minimap), "Start")]
	private static class Minimap_Start_Patch
	{
		[HarmonyPostfix]
		private static void Minimap_Start_Postfix(Minimap __instance)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			HUDCompass.Log.Debug("Minimap_Start_Patch_Postfix");
			if (!((Object)(object)s_dmm.PortalMarkerSprite == (Object)null))
			{
				return;
			}
			foreach (SpriteData icon in Minimap.instance.m_icons)
			{
				if (((Object)icon.m_icon).name == "mapicon_portal")
				{
					HUDCompass.Log.Debug("Found portal map icon");
					s_dmm.PortalMarkerSprite = icon.m_icon;
					break;
				}
			}
		}
	}

	public List<MarkerType> MarkerTypes;

	public Dictionary<ZDOID, MarkerData> Markers;

	public Sprite PortalMarkerSprite;

	public List<PinData> PinData;

	private Sprite ShipMarkerSprite;

	private Sprite CartMarkerSprite;

	private static DynamicMapMarkers s_dmm;

	private static float dmm_playerPinPeriodicTimer;

	private static float dmm_dynamicPinPeriodicTimer;

	private static float dmm_staticPinPeriodicTimer;

	public DynamicMapMarkers()
	{
		s_dmm = this;
		MarkerTypes = new List<MarkerType>();
		Markers = new Dictionary<ZDOID, MarkerData>();
		PinData = new List<PinData>();
		ShipMarkerSprite = HUDCompass.s_imageHelper.LoadSprite("mapicon_anchor.png", 2, 2, linear: false, 50f);
		CartMarkerSprite = HUDCompass.s_imageHelper.LoadSprite("mapicon_cart.png", 2, 2, linear: false, 50f);
	}

	public PinData MarkerToPinData(MarkerData marker)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: 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_0020: Unknown result type (might be due to invalid IL or missing references)
		//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_0062: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		if (marker != null)
		{
			return new PinData
			{
				m_icon = marker.Type.Sprite,
				m_pos = marker.ZDO.m_position,
				m_name = (marker.IsActivePortal ? MarkerGroup.ActivePortal.ToString() : marker.Type.Group.ToString()),
				m_type = (PinType)8,
				m_ownerID = marker.Creator
			};
		}
		return null;
	}

	public void DestroyMarkers()
	{
		foreach (MarkerData value in Markers.Values)
		{
			MarkerData.Destroy(value);
		}
		Markers.Clear();
	}

	public static bool GetAllZDOsWithPrefab(string prefab, List<ZDO> zdos)
	{
		int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab);
		foreach (ZDO value in ZDOMan.instance.m_objectsByID.Values)
		{
			if (value.GetPrefab() == stableHashCode && !zdos.Contains(value))
			{
				zdos.Add(value);
			}
		}
		zdos.RemoveAll((Predicate<ZDO>)ZDOMan.InvalidZDO);
		return true;
	}

	public static void BuildDynamicMarkerTypes()
	{
		s_dmm.MarkerTypes.Clear();
		s_dmm.MarkerTypes.Add(new MarkerType("portal_wood", s_dmm.PortalMarkerSprite, "$piece_portal", MarkerGroup.Portal, Cfg.showPortals.ConfigEntry));
		Ship val2 = default(Ship);
		Piece val3 = default(Piece);
		Vagon val4 = default(Vagon);
		Piece val5 = default(Piece);
		foreach (GameObject item in ObjectDB.instance.m_items)
		{
			PieceTable val = item.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces;
			if (!((Object)(object)val != (Object)null))
			{
				continue;
			}
			foreach (GameObject piece in val.m_pieces)
			{
				if (piece.TryGetComponent<Ship>(ref val2))
				{
					if (piece.TryGetComponent<Piece>(ref val3))
					{
						s_dmm.MarkerTypes.Add(new MarkerType(((Object)piece).name, s_dmm.ShipMarkerSprite, val3.m_name, MarkerGroup.Ship, Cfg.showShips.ConfigEntry));
						HUDCompass.Log.Debug("Found plans for ship " + ((Object)piece).name);
					}
				}
				else if (piece.TryGetComponent<Vagon>(ref val4) && piece.TryGetComponent<Piece>(ref val5))
				{
					s_dmm.MarkerTypes.Add(new MarkerType(((Object)piece).name, s_dmm.CartMarkerSprite, val5.m_name, MarkerGroup.Cart, Cfg.showCarts.ConfigEntry));
					HUDCompass.Log.Debug("Found plans for cart " + ((Object)piece).name);
				}
			}
		}
	}

	private static bool IsInControlByPlayer(ZDO zdo)
	{
		ZNetView val = ZNetScene.instance.FindInstance(zdo);
		if ((Object)(object)val != (Object)null)
		{
			GameObject gameObject = ((Component)val).gameObject;
			if ((Object)(object)gameObject != (Object)null)
			{
				Ship component = gameObject.GetComponent<Ship>();
				if ((Object)(object)component != (Object)null)
				{
					return component.HaveControllingPlayer();
				}
				Vagon component2 = gameObject.GetComponent<Vagon>();
				object obj;
				if (component2 == null)
				{
					obj = null;
				}
				else
				{
					ConfigurableJoint attachJoin = component2.m_attachJoin;
					obj = ((attachJoin != null) ? ((Joint)attachJoin).connectedBody : null);
				}
				if ((Object)obj != (Object)null)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void DrawMarker(MarkerData data, float size, RectTransform parent, RawImage targetMapRawImage, float largeMapZoom, bool isLargeMap)
	{
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: 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_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = data.Marker;
		GameObject val2 = data.Nametag;
		RectTransform val4;
		if ((Object)(object)val == (Object)null || (Object)(object)val.transform.parent != (Object)(object)parent)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
			val = (data.Marker = Object.Instantiate<GameObject>(Minimap.instance.m_pinPrefab));
			Transform transform = val.transform;
			val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Image component = val.GetComponent<Image>();
			component.sprite = data.Type.Sprite;
			switch (data.Type.Group)
			{
			case MarkerGroup.Portal:
				((Graphic)component).color = (data.IsActivePortal ? Cfg.activePortalColor.Value : Cfg.portalColor.Value);
				break;
			case MarkerGroup.Cart:
				((Graphic)component).color = Cfg.cartColor.Value;
				break;
			case MarkerGroup.Ship:
				((Graphic)component).color = Cfg.shipColor.Value;
				break;
			default:
				((Graphic)component).color = Color.white;
				break;
			}
			_ = Player.m_localPlayer;
			if (data.Creator != HUDCompass.s_localPlayerID)
			{
				float num = ((Graphic)component).color.a / 2f;
				((Graphic)component).color = new Color(((Graphic)component).color.r, ((Graphic)component).color.g, ((Graphic)component).color.b, num);
			}
			((Transform)val4).SetParent((Transform)(object)parent);
			val4.SetSizeWithCurrentAnchors((Axis)0, size);
			val4.SetSizeWithCurrentAnchors((Axis)1, size);
		}
		Transform transform2 = val.transform;
		val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
		WorldToMapPoint(data.ZDO.GetPosition(), out var mx, out var my);
		Vector2 anchoredPosition = (val4.anchoredPosition = MapPointToLocalGuiPos(mx, my, targetMapRawImage));
		Transform val6 = val.transform.Find("Checked");
		if ((Object)(object)val6 != (Object)null)
		{
			((Component)val6).gameObject.SetActive(false);
		}
		if (!isLargeMap && !Cfg.showTypeOnMinimap.Value)
		{
			return;
		}
		RectTransform component2;
		if ((Object)(object)val2 == (Object)null || (Object)(object)val2.transform.parent != (Object)(object)parent)
		{
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)val2);
			}
			if (isLargeMap)
			{
				val2 = Object.Instantiate<GameObject>(Minimap.instance.m_pinNamePrefab, (Transform)(object)parent);
				TMP_Text componentInChildren = val2.GetComponentInChildren<TMP_Text>();
				componentInChildren.text = Localization.instance.Localize(data.Type.Name);
				switch (data.Type.Group)
				{
				case MarkerGroup.Portal:
				{
					string @string = data.ZDO.GetString(ZDOVars.s_tag, "");
					componentInChildren.text = @string;
					((Graphic)componentInChildren).color = (data.IsActivePortal ? Cfg.activePortalColor.Value : Cfg.portalColor.Value);
					break;
				}
				case MarkerGroup.Cart:
					((Graphic)componentInChildren).color = Cfg.cartColor.Value;
					break;
				case MarkerGroup.Ship:
					((Graphic)componentInChildren).color = Cfg.shipColor.Value;
					break;
				default:
					((Graphic)componentInChildren).color = Color.white;
					break;
				}
				component2 = val2.GetComponent<RectTransform>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Transform)component2).SetParent((Transform)(object)parent);
					data.Nametag = val2;
				}
			}
		}
		Transform transform3 = val2.transform;
		component2 = (RectTransform)(object)((transform3 is RectTransform) ? transform3 : null);
		component2.anchoredPosition = anchoredPosition;
	}

	private static bool IsPointVisible(Vector3 p, RawImage map)
	{
		//IL_0000: 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)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: 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_002e: 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_003f: 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)
		WorldToMapPoint(p, out var mx, out var my);
		float num = mx;
		Rect uvRect = map.uvRect;
		if (num > ((Rect)(ref uvRect)).xMin)
		{
			float num2 = mx;
			uvRect = map.uvRect;
			if (num2 < ((Rect)(ref uvRect)).xMax)
			{
				float num3 = my;
				uvRect = map.uvRect;
				if (num3 > ((Rect)(ref uvRect)).yMin)
				{
					float num4 = my;
					uvRect = map.uvRect;
					return num4 < ((Rect)(ref uvRect)).yMax;
				}
			}
		}
		return false;
	}

	private static void WorldToMapPoint(Vector3 p, out float mx, out float my)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		int num = Minimap.instance.m_textureSize / 2;
		mx = p.x / Minimap.instance.m_pixelSize + (float)num;
		my = p.z / Minimap.instance.m_pixelSize + (float)num;
		mx /= Minimap.instance.m_textureSize;
		my /= Minimap.instance.m_textureSize;
	}

	private static Vector2 MapPointToLocalGuiPos(float mx, float my, RawImage img)
	{
		//IL_0002: 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)
		//IL_0011: 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_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		Vector2 result = default(Vector2);
		Rect val = img.uvRect;
		float num = mx - ((Rect)(ref val)).xMin;
		val = img.uvRect;
		result.x = num / ((Rect)(ref val)).width;
		val = img.uvRect;
		float num2 = my - ((Rect)(ref val)).yMin;
		val = img.uvRect;
		result.y = num2 / ((Rect)(ref val)).height;
		ref float x = ref result.x;
		float num3 = x;
		val = ((Graphic)img).rectTransform.rect;
		x = num3 * ((Rect)(ref val)).width;
		ref float y = ref result.y;
		float num4 = y;
		val = ((Graphic)img).rectTransform.rect;
		y = num4 * ((Rect)(ref val)).height;
		return result;
	}
}
[BepInPlugin("neobotics.valheim_mod.hudcompass", "HUDCompass", "1.0.5")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class HUDCompass : BaseUnityPlugin
{
	public enum PlayerPinBehavior
	{
		ForceOn,
		ForceOff,
		PlayerChoice
	}

	[HarmonyPatch(typeof(Minimap), "OnTogglePublicPosition")]
	private static class Minimap_OnTogglePublicPosition_Patch
	{
		[HarmonyPrefix]
		private static bool Minimap_OnTogglePublicPosition_Prefix(Minimap __instance)
		{
			Log.Debug("Minimap_OnTogglePublicPosition_Patch_Prefix");
			if (Cfg.playerPinBehavior.Value != PlayerPinBehavior.PlayerChoice)
			{
				return false;
			}
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
			Cfg.compassShowMyPlayerPin.Value = __instance.m_publicPosition.isOn;
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
			return true;
		}
	}

	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class Player_OnSpawned_Patch
	{
		[HarmonyPostfix]
		private static void Player_OnSpawned_Postfix(Player __instance)
		{
			Log.Debug("Player_OnSpawned_Patch_Postfix");
			s_localPlayerID = Game.instance.GetPlayerProfile().GetPlayerID();
			SetInitialPlayerPinCfgVisibility();
		}
	}

	[HarmonyPatch(typeof(Hud), "Awake")]
	internal static class HudAwakeCompassPatch
	{
		internal static void Postfix(Hud __instance)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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_0177: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Expected O, but got Unknown
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug("Hud_Awake_Postfix");
			if (s_imageHelper.TryLoadImage("compass.png", 2, 2, linear: true, out var image) && ((Texture)image).width > 0)
			{
				float width = (float)((Texture)image).width / 2f;
				s_spriteCompass = s_imageHelper.LoadSprite(image);
				if (s_imageHelper.TryLoadImage("mask.png", 2, 2, linear: true, out var image2) && ((Texture)image2).width > 0)
				{
					s_spriteMask = s_imageHelper.LoadSprite(image2, null, width, ((Texture)image2).height);
					if (s_imageHelper.TryLoadImage("center.png", 2, 2, linear: true, out var image3) && ((Texture)image3).width > 0)
					{
						s_spriteCenter = s_imageHelper.LoadSprite(image3);
					}
				}
				s_objectParent = new GameObject();
				((Object)s_objectParent).name = "Compass";
				((Transform)s_objectParent.AddComponent<RectTransform>()).SetParent(__instance.m_rootObject.transform);
				GameObject val = new GameObject();
				((Object)val).name = "Mask";
				RectTransform obj = val.AddComponent<RectTransform>();
				((Transform)obj).SetParent(s_objectParent.transform);
				Rect rect = s_spriteCompass.rect;
				float width2 = ((Rect)(ref rect)).width;
				rect = s_spriteCompass.rect;
				obj.sizeDelta = new Vector2(width2, ((Rect)(ref rect)).height);
				((Transform)obj).localScale = Vector3.one * Cfg.compassScale.Value;
				obj.anchoredPosition = Vector2.zero;
				Image obj2 = val.AddComponent<Image>();
				obj2.sprite = s_spriteMask;
				obj2.preserveAspect = true;
				val.AddComponent<Mask>().showMaskGraphic = false;
				s_objectCompass = new GameObject();
				((Object)s_objectCompass).name = "Image";
				RectTransform obj3 = s_objectCompass.AddComponent<RectTransform>();
				((Transform)obj3).SetParent(val.transform);
				((Transform)obj3).localScale = Vector3.one;
				obj3.anchoredPosition = Vector2.zero;
				rect = s_spriteCompass.rect;
				float width3 = ((Rect)(ref rect)).width;
				rect = s_spriteCompass.rect;
				obj3.sizeDelta = new Vector2(width3, ((Rect)(ref rect)).height);
				Image obj4 = s_objectCompass.AddComponent<Image>();
				obj4.sprite = s_spriteCompass;
				obj4.preserveAspect = true;
				if ((Object)(object)s_spriteCenter != (Object)null)
				{
					s_objectCenterMark = new GameObject();
					((Object)s_objectCenterMark).name = "CenterMark";
					RectTransform obj5 = s_objectCenterMark.AddComponent<RectTransform>();
					((Transform)obj5).SetParent(val.transform);
					((Transform)obj5).localScale = Vector3.one;
					obj5.anchoredPosition = Vector2.zero;
					rect = s_spriteCenter.rect;
					float width4 = ((Rect)(ref rect)).width;
					rect = s_spriteCenter.rect;
					obj5.sizeDelta = new Vector2(width4, ((Rect)(ref rect)).height);
					Image obj6 = s_objectCenterMark.AddComponent<Image>();
					obj6.sprite = s_spriteCenter;
					obj6.preserveAspect = true;
				}
				s_objectPins = new GameObject();
				((Object)s_objectPins).name = "Pins";
				RectTransform obj7 = s_objectPins.AddComponent<RectTransform>();
				((Transform)obj7).SetParent(val.transform);
				((Transform)obj7).localScale = Vector3.one;
				obj7.anchoredPosition = Vector2.zero;
				rect = s_spriteMask.rect;
				float width5 = ((Rect)(ref rect)).width;
				rect = s_spriteMask.rect;
				obj7.sizeDelta = new Vector2(width5, ((Rect)(ref rect)).height);
			}
			else
			{
				Log.Error("Invalid compass image");
			}
		}
	}

	[HarmonyPatch(typeof(Hud), "Update")]
	internal static class HudUpdateCompassPatch
	{
		internal static void Prefix(Hud __instance)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: 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_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0554: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_0614: Unknown result type (might be due to invalid IL or missing references)
			//IL_0735: Unknown result type (might be due to invalid IL or missing references)
			//IL_0747: Unknown result type (might be due to invalid IL or missing references)
			//IL_074d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Unknown result type (might be due to invalid IL or missing references)
			//IL_0685: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0707: Unknown result type (might be due to invalid IL or missing references)
			//IL_0719: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_06be: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.enableCompass.Value || !Cfg.showHideCompass.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			if ((Object)(object)s_spriteCompass == (Object)null)
			{
				Log.Debug("Compass is null");
				return;
			}
			if ((Object)(object)s_spriteMask == (Object)null)
			{
				Log.Debug("Mask is null");
				return;
			}
			float num = ((!Cfg.compassUsePlayerDirection.Value) ? ((Component)GameCamera.instance).transform.eulerAngles.y : ((Component)Player.m_localPlayer).transform.eulerAngles.y);
			if (num > 180f)
			{
				num -= 360f;
			}
			num *= -(float)Math.PI / 180f;
			Rect rect = s_objectCompass.GetComponent<Image>().sprite.rect;
			float num2 = 1f;
			CanvasScaler val = GuiScaler.m_scalers?.Find((GuiScaler x) => ((Object)x.m_canvasScaler).name == "LoadingGUI")?.m_canvasScaler;
			if ((Object)(object)val != (Object)null)
			{
				num2 = val.scaleFactor;
			}
			((Transform)s_objectCompass.GetComponent<RectTransform>()).localPosition = Vector3.right * (((Rect)(ref rect)).width / 2f) * num / ((float)Math.PI * 2f) - new Vector3(((Rect)(ref rect)).width * 0.125f, 0f, 0f);
			((Graphic)s_objectCompass.GetComponent<Image>()).color = Cfg.colorCompass.Value;
			((Transform)s_objectParent.GetComponent<RectTransform>()).localScale = Vector3.one * Cfg.compassScale.Value;
			s_objectParent.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, ((float)Screen.height / num2 - (float)((Texture)s_objectCompass.GetComponent<Image>().sprite.texture).height * Cfg.compassScale.Value) / 2f) - Vector2.up * (float)Cfg.compassYOffset.Value;
			if ((Object)(object)s_objectCenterMark != (Object)null)
			{
				if (Cfg.compassShowCenterMark.Value)
				{
					((Graphic)s_objectCenterMark.GetComponent<Image>()).color = Cfg.colorCenterMark.Value;
					s_objectCenterMark.SetActive(true);
				}
				else
				{
					s_objectCenterMark.SetActive(false);
				}
			}
			else
			{
				Log.Debug("Center is null");
			}
			_ = s_objectPins.transform.childCount;
			List<string> list = new List<string>();
			foreach (Transform item in s_objectPins.transform)
			{
				Transform val2 = item;
				list.Add(((Object)val2).name);
			}
			List<PinData> list2 = new List<PinData>();
			list2.AddRange(Minimap.instance.m_pins);
			list2.AddRange(Minimap.instance.m_locationPins.Values);
			if (Cfg.playerPinBehavior.Value != PlayerPinBehavior.ForceOff)
			{
				list2.AddRange(Minimap.instance.m_playerPins);
			}
			PinData deathPin = Minimap.instance.m_deathPin;
			if (deathPin != null)
			{
				list2.Add(deathPin);
			}
			if (Cfg.showDynamicPinsOnCompass.Value)
			{
				list2.AddRange(s_dmm.PinData);
			}
			Transform transform = ((Component)Player.m_localPlayer).transform;
			float num3 = 0f;
			if (1f - Cfg.scalePinsMin.Value > 0f)
			{
				num3 = (float)Cfg.distancePinsMax.Value / (1f - Cfg.scalePinsMin.Value);
			}
			Cfg.ignoredPinNames.Value.Contains("*");
			foreach (PinData item2 in list2)
			{
				string text = ((object)(Vector3)(ref item2.m_pos)).ToString();
				list.Remove(text);
				Transform val3 = s_objectPins.transform.Find(text);
				float num4 = Vector3.Distance(transform.position, item2.m_pos);
				bool flag = MatchTypeOrName(s_alwaysVisible, item2);
				bool num5 = MatchType(s_ignoredTypes, item2);
				bool flag2 = MatchNameOrWildcard(s_ignoredNames, s_ignoredWildcardNames, item2.m_name);
				bool flag3 = false;
				if (!num5 && !flag2 && (flag || IsInBounds(num4, Cfg.distancePinsMin.Value, Cfg.distancePinsMax.Value)))
				{
					flag3 = true;
				}
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(flag3);
				}
				if (!flag3)
				{
					continue;
				}
				Vector3 val4 = ((!Cfg.compassUsePlayerDirection.Value) ? ((Component)GameCamera.instance).transform.InverseTransformPoint(item2.m_pos) : transform.InverseTransformPoint(item2.m_pos));
				num = Mathf.Atan2(val4.x, val4.z);
				RectTransform val6;
				Image val7;
				if ((Object)(object)val3 == (Object)null)
				{
					if (Log.LogLevel >= Logging.LogLevels.Trace)
					{
						Logging log = Log;
						object[] obj = new object[5] { item2.m_name, item2.m_type, null, null, null };
						Sprite icon = item2.m_icon;
						obj[2] = ((icon != null) ? ((Object)icon).name : null);
						obj[3] = num4;
						obj[4] = flag;
						log.Trace(string.Format("Adding new pin object for name {0} type {1} icon {2} distance {3} always show {4}", obj));
					}
					GameObject val5 = new GameObject
					{
						name = ((object)(Vector3)(ref item2.m_pos)).ToString()
					};
					val6 = val5.AddComponent<RectTransform>();
					((Transform)val6).SetParent(s_objectPins.transform);
					val6.anchoredPosition = Vector2.zero;
					val7 = val5.AddComponent<Image>();
				}
				else
				{
					_ = ((Component)val3).gameObject;
					val6 = ((Component)val3).GetComponent<RectTransform>();
					val7 = ((Component)val3).GetComponent<Image>();
				}
				float num6 = (flag ? 1f : ((Cfg.scalePinsMin.Value < 1f) ? ((num3 - num4) / num3) : 1f));
				((Transform)val6).localScale = Vector3.one * num6 * 0.5f * Cfg.scalePins.Value;
				((Graphic)val7).color = Cfg.colorPins.Value;
				val7.sprite = item2.m_icon;
				if (Cfg.useDynamicColorsOnCompass.Value)
				{
					switch (item2.m_name)
					{
					case "Ship":
						((Graphic)val7).color = Cfg.shipColor.Value;
						break;
					case "Cart":
						((Graphic)val7).color = Cfg.cartColor.Value;
						break;
					case "Portal":
						((Graphic)val7).color = Cfg.portalColor.Value;
						break;
					case "ActivePortal":
						((Graphic)val7).color = Cfg.activePortalColor.Value;
						break;
					}
				}
				if (item2.m_ownerID != 0L && item2.m_ownerID != s_localPlayerID)
				{
					((Graphic)val7).color = new Color(((Graphic)val7).color.r * 0.7f, ((Graphic)val7).color.b * 0.7f, ((Graphic)val7).color.g * 0.7f, ((Graphic)val7).color.a * 0.8f);
				}
				((Transform)val6).localPosition = Vector3.right * (((Rect)(ref rect)).width / 2f) * num / ((float)Math.PI * 2f);
			}
			foreach (string item3 in list)
			{
				Object.Destroy((Object)(object)((Component)s_objectPins.transform.Find(item3)).gameObject);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	public static class Player_Update_Patch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && OkToKey(__instance) && Cfg.compassToggle.IsKeyPressed())
			{
				Cfg.showHideCompass.Value = !Cfg.showHideCompass.Value;
			}
		}
	}

	internal const string PLUGIN_NAME = "HUDCompass";

	internal const string PLUGIN_VERSION = "1.0.5";

	internal const string PLUGIN_GUID = "neobotics.valheim_mod.hudcompass";

	internal const string FILE_COMPASS = "compass.png";

	internal const string FILE_MASK = "mask.png";

	internal const string FILE_CENTER = "center.png";

	private static HUDCompass s_instance;

	private static Harmony harmony;

	internal static GameObject s_objectCompass;

	internal static GameObject s_objectPins;

	internal static GameObject s_objectParent;

	internal static GameObject s_objectCenterMark;

	internal static List<string> s_ignoredNames = new List<string>();

	internal static List<string> s_ignoredWildcardNames = new List<string>();

	internal static List<string> s_ignoredTypes = new List<string>();

	internal static List<string> s_alwaysVisible = new List<string>();

	internal static Sprite s_spriteCompass = null;

	internal static Sprite s_spriteMask = null;

	internal static Sprite s_spriteCenter = null;

	public static Logging Log;

	public static DynamicMapMarkers s_dmm = null;

	public static long s_localPlayerID = 0L;

	public static ImageHelper s_imageHelper;

	private static Dictionary<string, string> s_typeAlias = new Dictionary<string, string>
	{
		{ "mapicon_fire", "Fire" },
		{ "mapicon_house", "House" },
		{ "mapicon_trader", "Halder" },
		{ "mapicon_hilder", "Hilder" },
		{ "mapicon_start", "Start" },
		{ "mapicon_pin", "Pin" },
		{ "mapicon_portal", "Portal" },
		{ "mapicon_cart", "Cart" },
		{ "mapicon_anchor", "Ship" }
	};

	private void Awake()
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		s_instance = this;
		Log = Logging.GetLogger(Logging.LogLevels.Info, "HUDCompass");
		ServerConfiguration.Instance.Setup(((BaseUnityPlugin)this).Config, (BaseUnityPlugin)(object)s_instance);
		Cfg.BepInExConfig((BaseUnityPlugin)(object)s_instance);
		ServerConfiguration.Instance.CreateConfigWatcher();
		IgnoredNames();
		IgnoredTypes();
		VisibleBehavior();
		ShowMyPlayerPin();
		if (Cfg.useExternalImages.Value)
		{
			s_imageHelper = new ImageHelper("/", embedded: false);
			Log.Info("Using external images");
		}
		else
		{
			s_imageHelper = new ImageHelper("HUDCompass.Resources", embedded: true);
			Log.Info("Using embedded images");
		}
		s_dmm = new DynamicMapMarkers();
		harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		harmony.PatchAll(typeof(DynamicMapMarkers));
		Log.Info("Awake");
	}

	private void Start()
	{
		Game.isModded = true;
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.Save();
		s_dmm.DestroyMarkers();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	private static bool MatchNameOrWildcard(List<string> exact, List<string> wildcard, string name)
	{
		if (exact.Contains(name))
		{
			return true;
		}
		if (wildcard.Count > 0)
		{
			foreach (string item in wildcard)
			{
				if (item == name.Substring(0, item.Length - 1))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool MatchType(List<string> matches, PinData pin)
	{
		if (pin == null)
		{
			return false;
		}
		Sprite icon = pin.m_icon;
		string item = ((((icon != null) ? ((Object)icon).name : null) != null && s_typeAlias.ContainsKey(((Object)pin.m_icon).name)) ? s_typeAlias[((Object)pin.m_icon).name] : ((object)(PinType)(ref pin.m_type)).ToString());
		return matches.Contains(item);
	}

	private static bool MatchTypeOrName(List<string> matches, PinData pin)
	{
		if (pin == null)
		{
			return false;
		}
		if (!MatchType(matches, pin))
		{
			return matches.Contains(pin.m_name);
		}
		return true;
	}

	private static bool IsInBounds(float dist, float min, float max)
	{
		if (dist <= max)
		{
			return dist >= min;
		}
		return false;
	}

	private static bool OkToKey(Player player)
	{
		if (!Chat.instance.HasFocus() && !Console.IsVisible() && (Object)(object)TextViewer.instance != (Object)null && !TextViewer.instance.IsVisible() && !GameCamera.InFreeFly() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !((Character)player).InCutscene() && !((Character)player).InBed() && !((Character)player).IsTeleporting())
		{
			return !((Character)player).IsDead();
		}
		return false;
	}

	private static void SetInitialPlayerPinCfgVisibility()
	{
		if ((Object)(object)Minimap.instance != (Object)null)
		{
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
			Cfg.compassShowMyPlayerPin.Value = Object.op_Implicit((Object)(object)Minimap.instance.m_publicPosition);
			Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
		}
	}

	public static void SettingChanged_PlayerPinBehavior(object sender, EventArgs e)
	{
		ShowMyPlayerPin();
	}

	public static void SettingChanged_ShowMyPlayerPin(object sender, EventArgs e)
	{
		ShowMyPlayerPin();
	}

	public static void ShowMyPlayerPin()
	{
		if ((Object)(object)Minimap.instance?.m_largeRoot != (Object)null && (Object)(object)ZNet.instance != (Object)null)
		{
			bool flag = false;
			switch (Cfg.playerPinBehavior.Value)
			{
			case PlayerPinBehavior.ForceOff:
				flag = false;
				break;
			case PlayerPinBehavior.ForceOn:
				flag = true;
				break;
			case PlayerPinBehavior.PlayerChoice:
				flag = Cfg.compassShowMyPlayerPin.Value;
				break;
			}
			Minimap.instance.m_publicPosition.isOn = flag;
			ZNet.instance.SetPublicReferencePosition(flag);
			if (Cfg.compassShowMyPlayerPin.Value != flag)
			{
				Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged -= SettingChanged_ShowMyPlayerPin;
				Cfg.compassShowMyPlayerPin.Value = flag;
				Cfg.compassShowMyPlayerPin.ConfigEntry.SettingChanged += SettingChanged_ShowMyPlayerPin;
			}
		}
	}

	public static void SettingChanged_ShowCompass(object sender, EventArgs e)
	{
		if (Cfg.enableCompass.Value)
		{
			s_objectParent.SetActive(Cfg.showHideCompass.Value);
		}
	}

	public static void SettingChanged_EnableCompass(object sender, EventArgs e)
	{
		if (Cfg.showHideCompass.Value)
		{
			s_objectParent.SetActive(Cfg.enableCompass.Value);
		}
	}

	public static void SettingChanged_IgnoredNames(object sender, EventArgs e)
	{
		IgnoredNames();
	}

	public static void IgnoredNames()
	{
		s_ignoredNames.Clear();
		s_ignoredWildcardNames.Clear();
		string[] array = Cfg.ignoredPinNames.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.EndsWith("*"))
			{
				s_ignoredWildcardNames.Add(text.Substring(0, text.Length - 1));
			}
			else
			{
				s_ignoredNames.Add(text);
			}
		}
	}

	public static void SettingChanged_IgnoredTypes(object sender, EventArgs e)
	{
		IgnoredTypes();
	}

	public static void IgnoredTypes()
	{
		s_ignoredTypes.Clear();
		string[] array = Cfg.ignoredPinTypes.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			s_ignoredTypes.Add(text.Trim());
		}
	}

	public static void SettingChanged_VisibleBehavior(object sender, EventArgs e)
	{
		VisibleBehavior();
	}

	public static void VisibleBehavior()
	{
		s_alwaysVisible.Clear();
		string[] array = Cfg.alwaysVisible.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			s_alwaysVisible.Add(text.Trim());
		}
	}
}
public class MarkerData
{
	public MarkerType Type { get; set; }

	public GameObject Marker { get; set; }

	public ZDO ZDO { get; set; }

	public GameObject Nametag { get; set; }

	public bool IsActivePortal { get; set; }

	public long Creator { get; set; }

	public static void Destroy(MarkerData md)
	{
		Object.Destroy((Object)(object)md.Marker);
		Object.Destroy((Object)(object)md.Nametag);
	}
}
public class MarkerType
{
	public string Prefab { get; }

	public Sprite Sprite { get; set; }

	public string Name { get; }

	public MarkerGroup Group { get; set; }

	private ConfigEntry<bool> _showConifgEntry { get; }

	public bool Show => _showConifgEntry.Value;

	public MarkerType(string prefab, Sprite sprite, string name, MarkerGroup group, ConfigEntry<bool> show)
	{
		Prefab = prefab;
		Sprite = sprite;
		Name = name;
		Group = group;
		_showConifgEntry = show;
	}
}

BepInEx/plugins/Roses-SmarterContainers/SmartContainers.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SmartContainers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SmartContainers")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6b695573-f20c-49d7-99c3-26f3bd0c12c1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace SmartContainers;

internal sealed class ConfigurationManagerAttributes
{
	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
public static class ContainersTracker
{
	public static ICollection<Container> containerList = new List<Container>();

	public static bool isRearrangingItem = false;

	public static bool teleportingInProgress = false;

	public static List<Container> GetNearbyContainers(Vector3 center, bool all = false)
	{
		//IL_0066: 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)
		List<Container> list = new List<Container>();
		foreach (Container container in containerList)
		{
			int num = (all ? (Mod.range.Value * 2) : Mod.range.Value);
			if ((Object)(object)container != (Object)null && (Object)(object)((Component)container).transform != (Object)null && container.GetInventory() != null && (Object)(object)((Component)container).GetComponentInParent<Piece>() != (Object)null)
			{
				float num2 = Vector3.Distance(center, ((Component)container).transform.position);
				if ((num <= 0 || num2 < (float)num) && container.CheckAccess(Player.m_localPlayer.GetPlayerID()))
				{
					list.Add(container);
				}
			}
		}
		return list;
	}

	public static void Init()
	{
		Container[] array = Object.FindObjectsOfType<Container>();
		Mod.log.LogDebug((object)$"tracking {array.Length} discovered containers.");
		Container[] array2 = array;
		foreach (Container val in array2)
		{
			if (!((Object)val).name.StartsWith("Treasure") && val.GetInventory() != null && val.m_nview.IsValid() && val.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L)
			{
				containerList.Add(val);
			}
		}
	}

	public static void CleanupContainersList()
	{
		Mod.log.LogDebug((object)$"cleanup containerList. size before: {containerList.Count}");
		foreach (Container item in containerList.ToList())
		{
			if (!((Object)(object)item != (Object)null) || !((Object)(object)((Component)item).transform != (Object)null) || item.GetInventory() == null)
			{
				containerList.Remove(item);
			}
		}
		Mod.log.LogDebug((object)$"cleanup containerList. size after: {containerList.Count}");
	}
}
[HarmonyPatch(typeof(Container), "Awake")]
internal static class Container_Awake_Patch
{
	private static void Postfix(Container __instance)
	{
		if (Mod.modEnabled.Value && !((Object)__instance).name.StartsWith("Treasure") && __instance.GetInventory() != null && __instance.m_nview.IsValid() && (__instance.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L || __instance.m_nview.GetZDO().GetOwner() != 0L))
		{
			ContainersTracker.containerList.Add(__instance);
		}
	}
}
[HarmonyPatch(typeof(Container), "OnDestroyed")]
internal static class Container_OnDestroyed_Patch
{
	private static void Prefix(Container __instance)
	{
		if (Mod.modEnabled.Value)
		{
			ContainersTracker.containerList.Remove(__instance);
		}
	}
}
[HarmonyPatch(typeof(Inventory), "StackAll")]
internal static class Container_OnStackAll_Patch
{
	private static void Postfix(Inventory __instance, Inventory fromInventory, bool message)
	{
		if (Mod.unloadAllEnabled.Value && Mod.unloadAllInsteadStackBtn.Value)
		{
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_playerGrid == (Object)null) && !((Object)(object)instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
			{
				UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory());
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "UpdateTeleport")]
public static class PlayerUpdateTeleport_Patch_Cleanup_Containers
{
	public static void Prefix(float dt)
	{
		if (Mod.modEnabled.Value)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && localPlayer.m_teleporting && !ContainersTracker.teleportingInProgress)
			{
				ContainersTracker.teleportingInProgress = true;
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "UpdateTeleport")]
public static class PlayerUpdateTeleport_Postfix
{
	public static void Postfix(float dt)
	{
		if (Mod.modEnabled.Value)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && ContainersTracker.teleportingInProgress && !localPlayer.m_teleporting)
			{
				ContainersTracker.CleanupContainersList();
				ContainersTracker.teleportingInProgress = false;
			}
		}
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
public static class Inventory_Patch
{
	public static void Postfix(Inventory __instance, ItemData item, ref bool __result)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		if (!Mod.modEnabled.Value || __instance == null || (Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting() || ((object)__instance).Equals((object?)((Humanoid)Player.m_localPlayer).GetInventory()) || !((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(item) || (Mod.onlyStackableItems.Value && item.m_shared.m_maxStackSize == 1) || ContainersTracker.isRearrangingItem)
		{
			return;
		}
		if (Input.GetKey((KeyCode)108))
		{
			Console.instance.Print("SmartContainers tracked item [" + item.m_shared.m_name + "]");
		}
		KeyboardShortcut value = Mod.keyModifier.Value;
		if (!((KeyboardShortcut)(ref value)).IsPressed())
		{
			value = Mod.groupingKeyModifier.Value;
			if (!((KeyboardShortcut)(ref value)).IsPressed() && (!Mod.gamepadKey2.Value.MainPressed() || !ZInput.GetButton(Mod.gamepadKey1.Value)))
			{
				return;
			}
		}
		if ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.instance.IsContainerOpen())
		{
			return;
		}
		ContainersTracker.isRearrangingItem = true;
		if (!__result)
		{
			if (TryAddToNearBy(item))
			{
				__result = true;
				Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
			}
		}
		else if (__instance.CountItems(item.m_shared.m_name, -1, true) == item.m_stack && TryAddToNearBy(item))
		{
			__instance.RemoveItem(item);
			Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
		}
		ContainersTracker.isRearrangingItem = false;
	}

	public static bool TryAddToNearBy(ItemData item, bool allowCurrent = false, bool forceGrouping = false)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Unknown result type (might be due to invalid IL or missing references)
		//IL_0408: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Container openedContainer = InventoryGui.instance.m_currentContainer;
			if (Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened() && ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position, all: true).Any((Container c) => ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode() && c.m_nview.GetZDO().GetInt("InUse", 0) == 1))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Cant distribute items: other Player is using containers nearby.", 0, (Sprite)null);
				return false;
			}
			List<Container> list = (from c in ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position)
				where ((object)openedContainer).GetHashCode() == ((object)c).GetHashCode() || (Mod.concurrencyWorkaround.Value.Ignore() && ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode()) || ((Mod.concurrencyWorkaround.Value.SkipOpenedOthers() || Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened()) && c.m_nview.GetZDO().GetInt("InUse", 0) == 0)
				select c).ToList();
			foreach (Container item2 in list)
			{
				if (item2.GetInventory().CanAddItem(item, -1) && (allowCurrent || ((object)openedContainer).GetHashCode() != ((object)item2).GetHashCode()) && item2.GetInventory().HaveItem(item.m_shared.m_name, true))
				{
					Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has same item stack");
					return AddItemToContainer(item, item2, allowCurrent);
				}
			}
			KeyboardShortcut value;
			if (Mod.groupingEnabled.Value)
			{
				if (!forceGrouping)
				{
					value = Mod.groupingKeyModifier.Value;
					if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive())
					{
						goto IL_03ef;
					}
				}
				List<Tuple<string, Container>> list2 = new List<Tuple<string, Container>>();
				foreach (Container item3 in list)
				{
					if (item3.GetInventory().CanAddItem(item, -1))
					{
						string text = ItemGroups.FindMatchingUserGroup(item3, item);
						if (text != null)
						{
							list2.Add(Tuple.Create<string, Container>(text, item3));
						}
					}
				}
				if (list2.Any())
				{
					Tuple<string, Container> tuple = list2.OrderByDescending((Tuple<string, Container> t) => t.Item1).First();
					if (list2.Count > 1)
					{
						Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", list2) + "] found for " + ((Object)item.m_dropPrefab).name + " item. Using " + tuple.Item1));
					}
					Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + tuple.Item1 + " : [" + string.Join(",", ItemGroups.Groups[tuple.Item1]) + "]");
					return AddItemToContainer(item, tuple.Item2, allowCurrent);
				}
				foreach (Container item4 in list)
				{
					if (item4.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_SystemGroupItems(item4, item))
					{
						return AddItemToContainer(item, item4, allowCurrent);
					}
				}
				foreach (Container item5 in list)
				{
					if (item5.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_NamePatternItems(item5, item))
					{
						return AddItemToContainer(item, item5, allowCurrent);
					}
				}
				if (Mod.itemTypeGroupsEnabled.Value)
				{
					foreach (Container item6 in list)
					{
						if (item6.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSameItemType(item6, item))
						{
							return AddItemToContainer(item, item6, allowCurrent);
						}
					}
				}
				goto IL_03ef;
			}
			goto IL_046b;
			IL_03ef:
			if (Mod.fuzzyGroupingEnabled.Value)
			{
				if (!forceGrouping)
				{
					value = Mod.groupingKeyModifier.Value;
					if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive())
					{
						goto IL_046b;
					}
				}
				foreach (Container item7 in list)
				{
					if (item7.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSimilarGroupItems(item7, item))
					{
						return AddItemToContainer(item, item7, allowCurrent);
					}
				}
			}
			goto IL_046b;
			IL_046b:
			return false;
		}
		catch (Exception ex)
		{
			Mod.log.LogError((object)("Failed to rearrange container items: " + ex));
		}
		return false;
	}

	private static bool AddItemToContainer(ItemData item, Container targetContainer, bool allowCurrent = false)
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		Container currentContainer = InventoryGui.instance.m_currentContainer;
		if (allowCurrent || ((object)currentContainer).GetHashCode() != ((object)targetContainer).GetHashCode())
		{
			bool num = targetContainer.GetInventory().AddItem(item);
			if (num)
			{
				targetContainer.Save();
				targetContainer.GetInventory().Changed();
				if (Mod.hudMessageEnabled.Value && !((object)InventoryGui.instance.m_currentContainer).Equals((object?)targetContainer))
				{
					MessageHud.instance.QueueUnlockMsg(item.GetIcon(), item.m_shared.m_name, Mod.hudMessageText.Value);
				}
				Mod.PlayEffect(Mod.effectFeedbackEnabled.Value, "vfx_Potion_health_medium", ((Component)targetContainer).transform.position);
			}
			return num;
		}
		return false;
	}
}
public static class GuiFactory
{
	public static void CreateMrgDialog(out GameObject dialogObj, string dlgUid, string label1, string label2, string label3, UnityAction onFirst, UnityAction onSecond, UnityAction onThird)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: 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)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: 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_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Expected O, but got Unknown
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Expected O, but got Unknown
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Expected O, but got Unknown
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0347: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_040c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: Unknown result type (might be due to invalid IL or missing references)
		//IL_0463: Unknown result type (might be due to invalid IL or missing references)
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0504: Unknown result type (might be due to invalid IL or missing references)
		//IL_0527: Unknown result type (might be due to invalid IL or missing references)
		//IL_0531: Expected O, but got Unknown
		//IL_0533: Unknown result type (might be due to invalid IL or missing references)
		//IL_0547: Expected O, but got Unknown
		//IL_0576: Unknown result type (might be due to invalid IL or missing references)
		//IL_0585: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_05da: Unknown result type (might be due to invalid IL or missing references)
		Transform val = ((Component)InventoryGui.instance).gameObject.transform.Find("root/SplitDialog");
		Transform val2 = Object.Instantiate<Transform>(val, val.parent);
		((Object)val2).name = dlgUid;
		Transform winWrap = val2.Find("win_bkg");
		((RectTransform)winWrap).SetSizeWithCurrentAnchors((Axis)0, 500f);
		dialogObj = ((Component)val2).gameObject;
		Object.Destroy((Object)(object)((Component)winWrap.Find("Icon_bkg")).gameObject);
		Object.Destroy((Object)(object)((Component)winWrap.Find("Slider")).gameObject);
		Object.Destroy((Object)(object)((Component)winWrap.Find("Text")).gameObject);
		Object.Destroy((Object)(object)((Component)winWrap.Find("amount")).gameObject);
		((Component)winWrap.Find("Button_cancel")).gameObject.AddComponent(typeof(UIGamePad));
		((Component)winWrap.Find("Button_ok")).gameObject.AddComponent(typeof(UIGamePad));
		Transform val3 = winWrap.Find("Button_cancel");
		Transform val4 = winWrap.Find("Button_ok");
		Transform val5 = Object.Instantiate<Transform>(val4, ((Component)winWrap).transform);
		((Object)val5).name = "Button_3";
		((TMP_Text)((Component)val3.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label1;
		((TMP_Text)((Component)val4.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label2;
		((TMP_Text)((Component)val5.Find("Text")).GetComponent<TextMeshProUGUI>()).text = label3;
		RectTransform val6 = (RectTransform)((Component)val3).transform;
		val6.pivot += new Vector2(0.5f, 0.7f);
		RectTransform val7 = (RectTransform)((Component)val4).transform;
		val7.pivot += new Vector2(0.57f, 0.7f);
		RectTransform val8 = (RectTransform)((Component)val5).transform;
		val8.pivot += new Vector2(-0.48f, 0.7f);
		((RectTransform)((Component)val3).transform).SetSizeWithCurrentAnchors((Axis)1, 40f);
		((RectTransform)((Component)val4).transform).SetSizeWithCurrentAnchors((Axis)1, 40f);
		((RectTransform)((Component)val5).transform).SetSizeWithCurrentAnchors((Axis)1, 40f);
		InitJoyKey((Transform)(RectTransform)val3, "JoyTabLeft", "(LB)");
		InitJoyKey((Transform)(RectTransform)val4, "JoyTabRight", "(RB)");
		InitJoyKey((Transform)(RectTransform)val5, "", "");
		Transform obj = Object.Instantiate<Transform>(((Component)InventoryGui.instance).gameObject.transform.Find("root/Texts/Texts_frame/TextArea"), winWrap);
		((Object)obj).name = "TextArea";
		((Component)obj).gameObject.SetActive(true);
		((Graphic)((Component)obj).GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.4f);
		RectTransform val9 = (RectTransform)obj;
		((Transform)val9).position = ((Transform)(RectTransform)((Component)val.Find("win_bkg/bkg")).transform).position;
		((Transform)val9).localScale = ((Transform)(RectTransform)((Component)val.Find("win_bkg/bkg")).transform).localScale;
		val9.sizeDelta = ((RectTransform)((Component)val.Find("win_bkg/bkg")).transform).sizeDelta;
		val9.SetSizeWithCurrentAnchors((Axis)1, 190f);
		val9.SetSizeWithCurrentAnchors((Axis)0, 515f);
		val9.pivot = new Vector2(0.51f, 0.33f);
		((RectTransform)obj.Find("ScrollArea/Content/Name")).SetSizeWithCurrentAnchors((Axis)0, 515f);
		((RectTransform)obj.Find("ScrollArea/Content/Description")).SetSizeWithCurrentAnchors((Axis)0, 515f);
		TextMeshProUGUI component = ((Component)obj.Find("ScrollArea/Content/Name")).GetComponent<TextMeshProUGUI>();
		TextMeshProUGUI component2 = ((Component)obj.Find("ScrollArea/Content/Description")).GetComponent<TextMeshProUGUI>();
		((TMP_Text)component).fontSize = 18f;
		((Graphic)component).color = new Color(0.79f, 0.75f, 0.28f, 1f);
		((TMP_Text)component2).fontSize = 18f;
		((Graphic)component2).color = new Color(0.8f, 0.8f, 0.8f, 1f);
		Transform val10 = CreateButton("Selector", "--select--", winWrap.Find("TextArea"), new Vector2(380f, 24f), new Vector2(-0.23f, 11.4f));
		GameObject val11 = Object.Instantiate<GameObject>(Find("RecipeList"), winWrap);
		((Object)val11).name = "SelectorDlg";
		((RectTransform)val11.transform).pivot = new Vector2(-0.55f, 1.7f);
		Transform val12 = val11.transform.Find("Recipes/ListRoot");
		for (int i = 0; i < val12.childCount; i++)
		{
			Object.Destroy((Object)(object)((Component)val12.GetChild(i)).gameObject);
		}
		((RectTransform)val11.transform).SetSizeWithCurrentAnchors((Axis)1, 150f);
		((UnityEvent)((Component)val10).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
		{
			GameObject gameObject = ((Component)winWrap.Find("SelectorDlg")).gameObject;
			gameObject.SetActive(!gameObject.activeSelf);
		});
		InitJoyKey((Transform)(RectTransform)val10, "", "");
		Transform obj2 = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform.Find("Text"), winWrap.Find("TextArea"));
		((RectTransform)obj2).pivot = new Vector2(-0.05f, -0.13f);
		((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)1, 24f);
		((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)0, 150f);
		((TMP_Text)((Component)obj2).GetComponent<TextMeshProUGUI>()).text = "Target group:";
		((RectTransform)((Component)winWrap).transform).pivot = new Vector2(-0.7f, 1f);
		((UnityEvent)((Component)val3).GetComponent<Button>().onClick).AddListener(onFirst);
		((UnityEvent)((Component)val4).GetComponent<Button>().onClick).AddListener(onSecond);
		((UnityEvent)((Component)val5).GetComponent<Button>().onClick).AddListener(onThird);
	}

	public static Transform AddContainerGuiButton(string btnObjName, string text, Vector2 size, Vector2 pos)
	{
		//IL_0016: 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)
		return CreateButton(btnObjName, text, ((Component)InventoryGui.instance.m_takeAllButton).transform.parent, size, pos);
	}

	public static Transform CreateButton(string btnObjName, string text, Transform parent, Vector2 size, Vector2 pos)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0035: 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_0042: 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_005d: 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)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		_ = (RectTransform)parent.Find(btnObjName);
		Transform obj = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform, parent);
		((Object)obj).name = btnObjName;
		RectTransform val = (RectTransform)((Component)obj).transform;
		val.SetSizeWithCurrentAnchors((Axis)0, size.x);
		val.SetSizeWithCurrentAnchors((Axis)1, size.y);
		RectTransform val2 = (RectTransform)((Component)val).transform.Find("Text");
		val2.SetSizeWithCurrentAnchors((Axis)0, size.x);
		val2.SetSizeWithCurrentAnchors((Axis)1, size.y);
		((TMP_Text)((Component)val2).GetComponent<TextMeshProUGUI>()).text = text;
		val.pivot = pos;
		return (Transform)val;
	}

	public static void InitJoyKey(Transform btnComponent, string joyKeyCode, string tooltip)
	{
		//IL_0049: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		UIGamePad component = ((Component)btnComponent).GetComponent<UIGamePad>();
		Transform val = Object.Instantiate<Transform>(((Component)btnComponent).transform.Find("Text"), ((Component)component).transform);
		((TMP_Text)((Component)val).GetComponent<TextMeshProUGUI>()).text = tooltip;
		((Graphic)((Component)val).GetComponent<TextMeshProUGUI>()).color = new Color(0.8f, 0.8f, 0.8f, 1f);
		Transform transform = ((Component)val).transform;
		transform.position += new Vector3(0f, 13f, 0f);
		if ((Object)(object)component.m_hint != (Object)null)
		{
			Object.Destroy((Object)(object)component.m_hint);
		}
		component.m_hint = ((Component)val).gameObject;
		component.m_zinputKey = joyKeyCode;
		((Behaviour)((Component)val).GetComponent<TextMeshProUGUI>()).enabled = ZInput.IsGamepadActive();
	}

	public static void FillResList(RectTransform parent, ICollection<string> names, ICollection<Object> m_resObjects, Action<string> cb)
	{
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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)
		foreach (Object m_resObject in m_resObjects)
		{
			Object.Destroy(m_resObject);
		}
		m_resObjects.Clear();
		float num = 0f;
		GameObject val = Find("RecipeList/Recipes/RecipeElement");
		foreach (string groupName in names)
		{
			GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)parent).transform);
			Object.Destroy((Object)(object)((Component)val2.transform.Find("icon")).gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.Find("Durability")).gameObject);
			Object.Destroy((Object)(object)((Component)val2.transform.Find("QualityLevel")).gameObject);
			val2.SetActive(true);
			((UnityEvent)val2.GetComponentInChildren<Button>().onClick).AddListener((UnityAction)delegate
			{
				cb(groupName);
			});
			Transform transform = val2.transform;
			((RectTransform)((transform is RectTransform) ? transform : null)).anchoredPosition = new Vector2(0f, num * -20f);
			((TMP_Text)val2.GetComponentInChildren<TextMeshProUGUI>()).text = groupName;
			m_resObjects.Add((Object)(object)val2);
			num += 1f;
		}
		Rect rect = parent.rect;
		parent.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(((Rect)(ref rect)).height, num * 20f));
	}

	private static GameObject Find(string name)
	{
		GameObject val = GameObject.Find("_GameMain/LoadingGUI/PixelFix/IngameGui/Inventory_screen/root/Crafting/" + name);
		if ((Object)(object)val == (Object)null)
		{
			Mod.log.LogWarning((object)("Failed to locate '" + name + "' GameObject - fallback to IngameGui(Clone) lookup.."));
			val = ((Component)GameObject.Find("IngameGui").transform.Find("Inventory_screen/root/Crafting/" + name)).gameObject;
		}
		return val;
	}
}
[HarmonyPatch(typeof(InventoryGui), "Show")]
public static class Gui_Patch
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static Func<Tuple<string, List<string>>, string> <>9__8_3;

		public static UnityAction <>9__8_0;

		public static Func<Tuple<string, List<string>>, string> <>9__8_4;

		public static UnityAction <>9__8_1;

		public static Func<Tuple<string, List<string>>, string> <>9__8_5;

		public static UnityAction <>9__8_2;

		public static Func<Tuple<string, List<string>>, string> <>9__10_0;

		public static Func<Tuple<string, List<string>>, IEnumerable<string>> <>9__10_1;

		public static Func<ItemData, bool> <>9__10_5;

		public static Func<ItemData, string> <>9__10_6;

		public static Func<Tuple<string, List<string>>, string> <>9__10_8;

		public static Func<Tuple<string, List<string>>, string> <>9__10_3;

		internal void <InitButtons>b__8_0()
		{
			if (containersUniqueItems != null && intersectedGroups != null)
			{
				ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
			}
			groupsDialogObj.gameObject.SetActive(false);
		}

		internal string <InitButtons>b__8_3(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}

		internal void <InitButtons>b__8_1()
		{
			if (containersUniqueItems != null)
			{
				ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
			}
			groupsDialogObj.gameObject.SetActive(false);
		}

		internal string <InitButtons>b__8_4(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}

		internal void <InitButtons>b__8_2()
		{
			if (containersUniqueItems != null && intersectedGroups != null)
			{
				ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
			}
			groupsDialogObj.gameObject.SetActive(false);
		}

		internal string <InitButtons>b__8_5(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}

		internal string <InitMergePromptDlg>b__10_0(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}

		internal IEnumerable<string> <InitMergePromptDlg>b__10_1(Tuple<string, List<string>> _)
		{
			return _.Item2;
		}

		internal bool <InitMergePromptDlg>b__10_5(ItemData i)
		{
			return intersectedGroups[0].Item2.Contains(i.SCName());
		}

		internal string <InitMergePromptDlg>b__10_6(ItemData _)
		{
			return Localization.instance.Localize(_.m_shared.m_name);
		}

		internal string <InitMergePromptDlg>b__10_8(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}

		internal string <InitMergePromptDlg>b__10_3(Tuple<string, List<string>> _)
		{
			return _.Item1;
		}
	}

	public static bool initialized = false;

	private static Transform createGroupButton;

	private static Transform storeAllButton;

	public static GameObject groupsDialogObj;

	private static readonly ICollection<Object> groupSelectorItems = new List<Object>();

	private static List<Tuple<string, List<string>>> intersectedGroups;

	private static List<string> containersUniqueItems;

	private static void Postfix(InventoryGui __instance)
	{
		if (Mod.modEnabled.Value && Mod.groupingEnabled.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !initialized && __instance.IsContainerOpen())
		{
			InitButtons(__instance);
		}
	}

	private static void InitButtons(InventoryGui __instance)
	{
		//IL_0086: 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_0091: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		if (!Mod.modEnabled.Value)
		{
			return;
		}
		try
		{
			if ((Mod.groupingEnabled.Value || Mod.unloadAllEnabled.Value) && Mod.createGroupBtnEnabled.Value)
			{
				AddCreateGroupBtn(__instance);
				if (Mod.groupingEnabled.Value && Mod.mergePromptEnabled.Value)
				{
					object obj = <>c.<>9__8_0;
					if (obj == null)
					{
						UnityAction val = delegate
						{
							if (containersUniqueItems != null && intersectedGroups != null)
							{
								ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
							}
							groupsDialogObj.gameObject.SetActive(false);
						};
						<>c.<>9__8_0 = val;
						obj = (object)val;
					}
					object obj2 = <>c.<>9__8_1;
					if (obj2 == null)
					{
						UnityAction val2 = delegate
						{
							if (containersUniqueItems != null)
							{
								ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
							}
							groupsDialogObj.gameObject.SetActive(false);
						};
						<>c.<>9__8_1 = val2;
						obj2 = (object)val2;
					}
					object obj3 = <>c.<>9__8_2;
					if (obj3 == null)
					{
						UnityAction val3 = delegate
						{
							if (containersUniqueItems != null && intersectedGroups != null)
							{
								ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
							}
							groupsDialogObj.gameObject.SetActive(false);
						};
						<>c.<>9__8_2 = val3;
						obj3 = (object)val3;
					}
					GuiFactory.CreateMrgDialog(out groupsDialogObj, "mrgToGroupDialog", "Extend", "Extend&Merge", "Merge All", (UnityAction)obj, (UnityAction)obj2, (UnityAction)obj3);
				}
			}
			if (Mod.unloadAllEnabled.Value && !Mod.unloadAllInsteadStackBtn.Value)
			{
				AddStoreAllBtn(__instance);
			}
			initialized = true;
		}
		catch (Exception ex)
		{
			Mod.log.LogError((object)("Failed to properly patch GUI with additional buttons: " + ex));
			Clean();
		}
		finally
		{
			Mod.log.LogInfo((object)"Initialized UI extensions.");
		}
	}

	private static void AddCreateGroupBtn(InventoryGui __instance)
	{
		//IL_0021: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		createGroupButton = GuiFactory.AddContainerGuiButton("createGroupBtn", "+æ+", new Vector2(45f, 30f), Mod.createGroupBtnPos.Value);
		GuiFactory.InitJoyKey(createGroupButton, "JoyMap", "(Гг)");
		((UnityEvent)((Component)createGroupButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
			{
				Inventory inventory = __instance.m_containerGrid.GetInventory();
				KeyboardShortcut value;
				if (Mod.unloadAllEnabled.Value)
				{
					value = Mod.unloadAllItemsGroupKeyModifier.Value;
					if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyRTrigger"))
					{
						UnloadItems.AddToUnloadAllItemsFilter(inventory);
						return;
					}
				}
				if (Mod.unloadAllEnabled.Value)
				{
					value = Mod.unloadAllSkipItemsGroupKeyModifier.Value;
					if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyLTrigger"))
					{
						UnloadItems.AddToUnloadAllItemsSkipList(inventory);
						return;
					}
				}
				if (Mod.groupingEnabled.Value)
				{
					containersUniqueItems = ItemGroupUtils.ExtractUniqueItemNames(inventory);
					if (containersUniqueItems.Count >= 2)
					{
						if (Mod.mergePromptEnabled.Value)
						{
							InitMergePromptDlg(inventory);
						}
						else
						{
							ItemGroupUtils.RegisterNewGroup(inventory);
						}
					}
				}
			}
		});
	}

	private static void InitMergePromptDlg(Inventory inventory)
	{
		//IL_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Expected O, but got Unknown
		//IL_0396: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Expected O, but got Unknown
		intersectedGroups = ItemGroupUtils.FindIntersections(containersUniqueItems);
		if (!intersectedGroups.Any())
		{
			ItemGroupUtils.RegisterNewGroup(inventory);
			return;
		}
		List<string> second = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList();
		HashSet<string> intersectedItemNames = intersectedGroups.FlatMap((Tuple<string, List<string>> _) => _.Item2).ToHashSet();
		List<string> nonGroupedItems = containersUniqueItems.Filter((string _) => !intersectedItemNames.Contains(_)).ToList();
		TextMeshProUGUI component = ((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/ScrollArea/Content/Name")).GetComponent<TextMeshProUGUI>();
		TextMeshProUGUI component2 = ((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/ScrollArea/Content/Description")).GetComponent<TextMeshProUGUI>();
		if (intersectedGroups.Count == 1)
		{
			if (!nonGroupedItems.Any())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Group " + intersectedGroups[0].Item1 + " already contains these items", 0, (Sprite)null);
				return;
			}
			List<string> list = inventory.m_inventory.Filter((ItemData i) => intersectedGroups[0].Item2.Contains(i.SCName())).Map((ItemData _) => Localization.instance.Localize(_.m_shared.m_name)).Distinct()
				.ToList();
			((TMP_Text)component).text = string.Join(",", list.Take(3)) + " " + ((list.Count > 3) ? "and others " : "") + ((list.Count > 1) ? "are already members" : "is already a member") + $" of an existing group of {ItemGroups.Groups[intersectedGroups[0].Item1].Count} items. ";
		}
		else
		{
			((TMP_Text)component).text = $"Items from {intersectedGroups.Count} different groups are already presented in this container.";
		}
		((TMP_Text)component2).text = " Please review info bellow, select target-group & action.\n You can: \n • <color=#FFA13CB7>'Extend'</color>: add previously non-grouped items \n(colored in <color=green>green</color>) to a selected  target-group.\n";
		((TMP_Text)component2).text = ((TMP_Text)component2).text + " • <color=#FFA13CB7>'Extend & merge'</color>: add all items from this container to a selected target-group. All conflicting items (colored in <color=red>red</color>) would be removed from their current groups.\n";
		((TMP_Text)component2).text = ((TMP_Text)component2).text + " • <color=#FFA13CB7>'Merge all'</color>: (Not recommended) move all items (from this container) & all conflicting group items to a target group.All members of all listed bellow groups will be moved to a target group. \n<color=grey>(target-group could be a new or an existing group)</color>\n";
		List<string> list2 = UnloadItems.unloadAllGroupsList.Intersect(second).ToList();
		if (Mod.unloadAllEnabled.Value && list2.Any())
		{
			((TMP_Text)component2).text = ((TMP_Text)component2).text + " \n<color=orange> ! Please note that groups [" + string.Join(",", list2) + "] are used for 'Unloading' filtering. Changing them will affect it's behaviour.</color>\n";
		}
		((TMP_Text)component2).text = ((TMP_Text)component2).text + "\n Items in the container: " + GeneralExtensions.Join<string>(containersUniqueItems.Map((string itemName) => "<color=" + (nonGroupedItems.Contains(itemName) ? "green" : "red") + ">" + itemName + "</color>"), (Func<string, string>)null, ",") + ".\n";
		((TMP_Text)component2).text = ((TMP_Text)component2).text + "\n Detected groups: \n";
		((TMP_Text)component2).text = ((TMP_Text)component2).text + GeneralExtensions.Join<string>(intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Map(delegate(string gKey)
		{
			IEnumerable<string> values = ItemGroups.Groups[gKey].Map((string _) => (!intersectedItemNames.Contains(_)) ? _ : ("<color=red>" + _ + "</color>"));
			return "<color=yellow>" + gKey + "</color>: [" + string.Join(", ", values) + "] \n";
		}), (Func<string, string>)null, "");
		RectTransform selectorBtn = (RectTransform)groupsDialogObj.transform.Find("win_bkg/TextArea/Selector");
		RectTransform val = (RectTransform)groupsDialogObj.transform.Find("win_bkg/SelectorDlg/Recipes/ListRoot");
		List<string> names = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Prepend("--new Group--").ToList();
		GuiFactory.FillResList(val, names, groupSelectorItems, delegate(string selection)
		{
			((TMP_Text)((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>()).text = selection;
			((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg")).gameObject.SetActive(false);
		});
		((TMP_Text)((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>()).text = ((intersectedGroups.Count == 1) ? intersectedGroups[0].Item1 : "--new Group--");
		((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg/RecipeScroll")).GetComponent<Scrollbar>().value = 1f;
		((Component)groupsDialogObj.transform.Find("win_bkg/SelectorDlg")).gameObject.SetActive(false);
		groupsDialogObj.SetActive(true);
	}

	private static string SelectedTargetGroupId()
	{
		return ((TMP_Text)((Component)groupsDialogObj.transform.Find("win_bkg/TextArea/Selector")).GetComponentInChildren<TextMeshProUGUI>()).text;
	}

	private static void AddStoreAllBtn(InventoryGui __instance)
	{
		//IL_0021: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		storeAllButton = GuiFactory.AddContainerGuiButton("storeAllButton", "\\||/", new Vector2(45f, 36f), Mod.unloadAllBtnPos.Value);
		GuiFactory.InitJoyKey(storeAllButton, "JoyMenu", "(≡)");
		((UnityEvent)((Component)storeAllButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
		{
			if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
			{
				UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory());
			}
		});
	}

	public static void Init()
	{
		if ((Object)(object)InventoryGui.instance != (Object)null)
		{
			InitButtons(InventoryGui.instance);
		}
	}

	public static void Clean()
	{
		if ((Object)(object)createGroupButton != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)createGroupButton).gameObject);
		}
		if ((Object)(object)storeAllButton != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)storeAllButton).gameObject);
		}
		if ((Object)(object)groupsDialogObj != (Object)null)
		{
			Object.Destroy((Object)(object)groupsDialogObj);
		}
		initialized = false;
		Mod.log.LogInfo((object)"Cleaned up UI extensions.");
	}
}
[HarmonyPatch(typeof(Game), "Start")]
public static class Game_Start_Patch
{
	private static void Postfix(Game __instance)
	{
		Gui_Patch.Clean();
	}
}
[HarmonyPatch(typeof(InventoryGui), "Hide")]
public static class Gui_Hide_Patch
{
	private static void Postfix(InventoryGui __instance)
	{
		if (Gui_Patch.initialized)
		{
			GameObject groupsDialogObj = Gui_Patch.groupsDialogObj;
			if (groupsDialogObj != null)
			{
				groupsDialogObj.SetActive(false);
			}
		}
	}
}
public static class ItemGroups
{
	private static ICollection<string> prefixItemGroups = new HashSet<string>();

	private static ICollection<string> postfixItemGroups = new HashSet<string>();

	public static readonly IDictionary<string, ISet<string>> Groups = new Dictionary<string, ISet<string>>();

	public static void ParseConfig()
	{
		foreach (KeyValuePair<ConfigDefinition, string> item in Mod.ConfigOrphanedEntries().ToList())
		{
			if (item.Key.Section.Equals("ItemGroup"))
			{
				Mod.config.Bind<string>(item.Key.Section, item.Key.Key, item.Value.ToLower().Replace("_", ""), Mod.groupDescr("user-added items-group based on item-names list"));
			}
		}
		ConfigEntry<string> val = default(ConfigEntry<string>);
		if (Mod.config.TryGetEntry<string>("PrefixedItemGroups", "prefixes", ref val) && val.Value.Length > 0)
		{
			prefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val);
			Mod.log.LogInfo((object)string.Format("parsed PrefixedItemGroups : [{0}] ({1})", string.Join(",", prefixItemGroups), prefixItemGroups.Count));
		}
		ConfigEntry<string> val2 = default(ConfigEntry<string>);
		if (Mod.config.TryGetEntry<string>("PostfixedItemGroups", "posfixes", ref val2) && val2.Value.Length > 0)
		{
			postfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val2);
			Mod.log.LogInfo((object)string.Format("parsed PostfixedItemGroups: [{0}] ({1})", string.Join(",", postfixItemGroups), postfixItemGroups.Count));
		}
		ConfigEntry<string> val3 = default(ConfigEntry<string>);
		foreach (ConfigDefinition item2 in from itemKey in Mod.config.Keys
			where itemKey.Section.Equals("ItemGroup")
			select itemKey into _
			orderby _.Key
			select _)
		{
			if (Mod.config.TryGetEntry<string>(item2.Section, item2.Key, ref val3) && val3.Value.Length > 0)
			{
				ISet<string> set = ItemGroupUtils.ParseGroupConfigEntry(val3);
				Groups.Add(item2.Key, set);
				Mod.log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", item2.Key, string.Join(",", set), set.Count));
			}
		}
	}

	public static string FindMatchingUserGroup(Container container, ItemData item)
	{
		if (item.m_shared.m_name.Length < 7)
		{
			Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
			return null;
		}
		ICollection<string> collection = FindMatchingGroups(container, item.SCName(), item, Groups.Keys.Except(Mod.systemGroupKeys).ToList());
		if (collection.Count > 1)
		{
			Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", collection) + "] found for " + ((Object)item.m_dropPrefab).name + " item in single container."));
		}
		if (!collection.Any())
		{
			return null;
		}
		return collection.Max((string _) => _);
	}

	public static bool ContainerHasSame_SystemGroupItems(Container container, ItemData item)
	{
		if (item.m_shared.m_name.Length < 7)
		{
			Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
			return false;
		}
		return TestConfiguredGroups(container, item.SCName(), item, Mod.systemGroupKeys);
	}

	public static bool ContainerHasSame_NamePatternItems(Container container, ItemData item)
	{
		if (item.m_shared.m_name.Length < 7)
		{
			Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
			return false;
		}
		string shortItemName = item.SCName();
		if (!TestItemNamePrefix(container, shortItemName, item))
		{
			return TestItemNamePostfix(container, shortItemName, item);
		}
		return true;
	}

	public static bool ContainerHasSameItemType(Container container, ItemData item)
	{
		//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)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (item.m_shared.m_name.Length < 7)
		{
			return false;
		}
		ItemType itemType = item.m_shared.m_itemType;
		string shortItemName = item.SCName();
		int num;
		if ((!IsTrophie(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTrophie(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsTool(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTool(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsAmmo(itemType) || !HaveMatchingItem(container, (ItemData _) => IsAmmo(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsArmor(itemType) || !HaveMatchingItem(container, (ItemData _) => IsArmor(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))))
		{
			if (IsWeapon(itemType))
			{
				num = (HaveMatchingItem(container, (ItemData _) => IsWeapon(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName)) ? 1 : 0);
				if (num != 0)
				{
					goto IL_00c6;
				}
			}
			else
			{
				num = 0;
			}
			goto IL_00ff;
		}
		num = 1;
		goto IL_00c6;
		IL_00ff:
		return (byte)num != 0;
		IL_00c6:
		Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type {item.m_shared.m_itemType}");
		goto IL_00ff;
	}

	public static bool ContainerHasSimilarGroupItems(Container container, ItemData item)
	{
		//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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		if (item.m_shared.m_name.Length < 7)
		{
			return false;
		}
		string shortItemName = item.m_shared.m_name.SCName();
		ItemType itemType = item.m_shared.m_itemType;
		int num;
		if ((int)itemType != 0)
		{
			num = (HaveMatchingItem(container, (ItemData _) => _.m_shared.m_itemType == itemType && !_.SCName().Equals(shortItemName)) ? 1 : 0);
			if (num != 0)
			{
				Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type (fuzzy) {item.m_shared.m_itemType}");
			}
		}
		else
		{
			num = 0;
		}
		return (byte)num != 0;
	}

	private static bool TestItemNamePrefix(Container container, string shortItemName, ItemData item)
	{
		foreach (string prefix in prefixItemGroups)
		{
			if (shortItemName.StartsWith(prefix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.StartsWith("$item_" + prefix) && !_.SCName().Equals(shortItemName)))
			{
				Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Prefix " + prefix);
				return true;
			}
		}
		return false;
	}

	private static bool TestItemNamePostfix(Container container, string shortItemName, ItemData item)
	{
		foreach (string postfix in postfixItemGroups)
		{
			if (shortItemName.EndsWith(postfix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.EndsWith(postfix) && !_.SCName().Equals(shortItemName)))
			{
				Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Postfix " + postfix);
				return true;
			}
		}
		return false;
	}

	private static bool TestConfiguredGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null)
	{
		foreach (string item2 in grKeys ?? Groups.Keys)
		{
			if (Groups.ContainsKey(item2))
			{
				ISet<string> set = Groups[item2];
				if (TestGroup(shortItemName, container, set))
				{
					Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + item2 + " : [" + string.Join(",", set) + "]");
					return true;
				}
			}
		}
		return false;
	}

	private static ICollection<string> FindMatchingGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null)
	{
		ICollection<string> obj = grKeys ?? Groups.Keys;
		List<string> list = new List<string>();
		foreach (string item2 in obj)
		{
			if (Groups.ContainsKey(item2))
			{
				ISet<string> group = Groups[item2];
				if (TestGroup(shortItemName, container, group))
				{
					list.Add(item2);
				}
			}
		}
		return list;
	}

	private static bool TestGroup(string shortItemName, Container container, ICollection<string> group)
	{
		if (group.Contains(shortItemName))
		{
			foreach (string iname in group)
			{
				if (!iname.Equals(shortItemName) && HaveMatchingItem(container, (ItemData _) => _.SCName().Equals(iname)))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool HaveMatchingItem(Container container, Func<ItemData, bool> predicate)
	{
		foreach (ItemData item in container.GetInventory().m_inventory)
		{
			if (predicate(item))
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsArmor(ItemType _)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Invalid comparison between Unknown and I4
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Invalid comparison between Unknown and I4
		if ((int)_ != 6 && (int)_ != 7 && (int)_ != 11 && (int)_ != 17)
		{
			return (int)_ == 18;
		}
		return true;
	}

	private static bool IsWeapon(ItemType _)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Invalid comparison between Unknown and I4
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Invalid comparison between Unknown and I4
		if ((int)_ != 3 && (int)_ != 4 && (int)_ != 14)
		{
			return (int)_ == 5;
		}
		return true;
	}

	private static bool IsTrophie(ItemType _)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		return (int)_ == 13;
	}

	private static bool IsTool(ItemType _)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		return (int)_ == 19;
	}

	private static bool IsAmmo(ItemType _)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		return (int)_ == 9;
	}

	public static void Clear()
	{
		prefixItemGroups.Clear();
		postfixItemGroups.Clear();
		Groups.Clear();
	}
}
public static class ItemGroupUtils
{
	private static readonly Predicate<string> IsItemSupported = (string itemName) => itemName.StartsWith("$item_") || itemName.StartsWith("$mod_");

	public static void RegisterNewGroup(Inventory inventory)
	{
		List<string> list = ExtractUniqueItemNames(inventory);
		if (list.Count > 1)
		{
			RegisterNewGroup((ICollection<string>)list);
		}
	}

	public static void RegisterNewGroup(ICollection<string> names)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		if (!names.Any())
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "No new items to create a group from.", 0, (Sprite)null);
			return;
		}
		Mod.ignoreUpdate = true;
		ConfigDefinition val = new ConfigDefinition("ItemGroup", "userGroup" + DateTimeOffset.UtcNow.ToUnixTimeSeconds());
		Mod.config.Bind<string>(val, string.Join(",", names), Mod.groupDescr("user-added items-group based on item-names list"));
		ConfigEntry<string> val2 = default(ConfigEntry<string>);
		if (Mod.config.TryGetEntry<string>(val, ref val2) && val2.Value.Length > 0)
		{
			ISet<string> set = ParseGroupConfigEntry(val2);
			ItemGroups.Groups.Add(val.Key, set);
			ManualLogSource log = Mod.log;
			if (log != null)
			{
				log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", val.Key, string.Join(",", set), set.Count));
			}
			NotifyPlayer(set.Count, "Registered new group of {0} items.");
		}
	}

	public static void MergeAllToSingleGroup(string targetGroupId, List<string> groupIds, List<string> newItems)
	{
		HashSet<string> hashSet = groupIds.Filter((string _) => !_.Equals(targetGroupId)).FlatMap((string _) => ItemGroups.Groups[_]).ToList()
			.Concat(newItems)
			.ToHashSet();
		if (!ItemGroups.Groups.ContainsKey(targetGroupId))
		{
			RegisterNewGroup((ICollection<string>)hashSet);
		}
		else
		{
			hashSet = hashSet.Except(ItemGroups.Groups[targetGroupId]).ToHashSet();
			if (!hashSet.Any())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null);
			}
			else
			{
				AddToItemsGroup(targetGroupId, hashSet);
				NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
			}
		}
		foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId)))
		{
			Mod.log.LogInfo((object)("flattened group : " + item));
			ClearItemsGroup(item);
		}
	}

	public static void ExtendGroup(string targetGroupId, List<string> groupIds, List<string> newItems)
	{
		List<string> second = groupIds.FlatMap((string _) => ItemGroups.Groups[_]).Intersect(newItems).ToList();
		HashSet<string> hashSet = newItems.Except(second).ToHashSet();
		if (!ItemGroups.Groups.ContainsKey(targetGroupId))
		{
			RegisterNewGroup((ICollection<string>)hashSet);
			return;
		}
		if (!hashSet.Any())
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null);
			return;
		}
		AddToItemsGroup(targetGroupId, hashSet);
		NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
	}

	public static void ExtendAndMerge(string targetGroupId, List<string> groupIds, List<string> newItems)
	{
		foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId)))
		{
			List<string> items = newItems.Intersect(ItemGroups.Groups[item]).ToList();
			RemoveFromItemsGroup(item, items);
		}
		if (!ItemGroups.Groups.ContainsKey(targetGroupId))
		{
			RegisterNewGroup((ICollection<string>)newItems);
			return;
		}
		HashSet<string> hashSet = newItems.Except(ItemGroups.Groups[targetGroupId]).ToHashSet();
		if (!hashSet.Any())
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null);
			return;
		}
		AddToItemsGroup(targetGroupId, hashSet);
		NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
	}

	public static ConfigEntry<string> AddToItemListConfig(ICollection<string> names, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage)
	{
		foreach (string name in names)
		{
			targetSet.Add(name);
		}
		Mod.ignoreUpdate = true;
		configEntry.Value = string.Join(",", targetSet);
		NotifyPlayer(names.Count, uiMessage);
		return configEntry;
	}

	private static void NotifyPlayer(int count, string uiMessage)
	{
		//IL_0039: 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)
		//IL_0049: 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)
		((Character)Player.m_localPlayer).Message((MessageType)2, string.Format(uiMessage, count), 0, (Sprite)null);
		if (Mod.effectFeedbackEnabled.Value)
		{
			Vector3 position = ((Component)InventoryGui.instance.m_currentContainer).gameObject.transform.position;
			Player.m_localPlayer.m_skillLevelupEffects.Create(position, Quaternion.identity, (Transform)null, 1f, -1);
		}
	}

	public static List<Tuple<string, List<string>>> FindIntersections(List<string> names)
	{
		List<Tuple<string, List<string>>> list = new List<Tuple<string, List<string>>>();
		foreach (string item in ItemGroups.Groups.Keys.ToList())
		{
			List<string> list2 = ItemGroups.Groups[item].Intersect(names).ToList();
			if (list2.Any())
			{
				list.Add(new Tuple<string, List<string>>(item, list2));
			}
		}
		return list.OrderByDescending((Tuple<string, List<string>> tt) => tt.Item2.Count).ToList();
	}

	public static List<string> ExtractUniqueItemNames(Inventory inventory)
	{
		foreach (string item in inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => !IsItemSupported(_)).ToList())
		{
			Mod.log.LogWarning((object)("Unsupported item name " + item));
		}
		return inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => IsItemSupported(_)).Distinct()
			.Map((string _) => _.SCName())
			.ToList();
	}

	public static ISet<string> ParseGroupConfigEntry(ConfigEntry<string> configEntry)
	{
		return new HashSet<string>(configEntry.Value.Split(new char[1] { ',' }).Map((string _) => _.SCName().Replace(" ", "")));
	}

	private static void AddToItemsGroup(string groupId, ICollection<string> items)
	{
		foreach (string item in items)
		{
			ItemGroups.Groups[groupId].Add(item);
		}
		SaveItemsGroup(groupId, ItemGroups.Groups[groupId]);
	}

	private static void RemoveFromItemsGroup(string groupId, ICollection<string> items)
	{
		foreach (string item in items)
		{
			ItemGroups.Groups[groupId].Remove(item);
		}
		SaveItemsGroup(groupId, ItemGroups.Groups[groupId]);
	}

	private static void ClearItemsGroup(string flattenedGroupId)
	{
		ItemGroups.Groups[flattenedGroupId].Clear();
		SaveItemsGroup(flattenedGroupId, ItemGroups.Groups[flattenedGroupId]);
	}

	private static void SaveItemsGroup(string groupId, ICollection<string> groupItems)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		ConfigEntry<string> val = default(ConfigEntry<string>);
		if (Mod.config.TryGetEntry<string>(new ConfigDefinition("ItemGroup", groupId), ref val))
		{
			Mod.ignoreUpdate = true;
			val.Value = string.Join(",", groupItems);
		}
	}
}
[BepInPlugin("flueno.SmartContainers", "Smart Containers Mod", "1.7.0")]
public class Mod : BaseUnityPlugin
{
	internal readonly Harmony harmony;

	internal readonly Assembly assembly;

	public static ManualLogSource log;

	public static ConfigFile config;

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<bool> groupingEnabled;

	public static ConfigEntry<bool> itemTypeGroupsEnabled;

	public static ConfigEntry<bool> fuzzyGroupingEnabled;

	public static ConfigEntry<bool> onlyStackableItems;

	public static ConfigEntry<ConcurrentChestModificationWorkaround> concurrencyWorkaround;

	public static ConfigEntry<bool> hudMessageEnabled;

	public static ConfigEntry<bool> audioFeedbackEnabled;

	public static ConfigEntry<bool> effectFeedbackEnabled;

	public static ConfigEntry<string> hudMessageText;

	public static ConfigEntry<int> range;

	public static ConfigEntry<KeyboardShortcut> keyModifier;

	public static ConfigEntry<string> gamepadKey1;

	public static ConfigEntry<KeyboardShortcut> gamepadKey2;

	public static ConfigEntry<KeyboardShortcut> groupingKeyModifier;

	public static ConfigEntry<bool> createGroupBtnEnabled;

	public static ConfigEntry<bool> mergePromptEnabled;

	public static ConfigEntry<Vector2> createGroupBtnPos;

	public static ConfigEntry<bool> unloadAllEnabled;

	public static ConfigEntry<bool> unloadAllInsteadStackBtn;

	public static ConfigEntry<Vector2> unloadAllBtnPos;

	public static ConfigEntry<KeyboardShortcut> unloadAllItemsGroupKeyModifier;

	public static ConfigEntry<KeyboardShortcut> unloadAllSkipItemsGroupKeyModifier;

	public static ConfigEntry<bool> unloadForceGrouping;

	public static ConfigEntry<string> unloadAllItemsList;

	public static ConfigEntry<string> unloadAllSkipList;

	public static ConfigEntry<string> unloadAllGroupsList;

	public static ConfigEntry<string> unloadAllPrefixItemGroups;

	public static ConfigEntry<string> unloadAllPostfixItemGroups;

	public static ConfigEntry<bool> unloadAllMaterialsFiltering;

	public static ConfigEntry<bool> unloadAllTrophiesFiltering;

	public static ConfigEntry<bool> unloadAllConsumableFiltering;

	public static bool ignoreUpdate = false;

	public static readonly ICollection<string> systemGroupKeys = new HashSet<string> { "valuables", "ore", "rock", "ingots", "wood", "mushrooms", "berries", "vegetables", "cookedMeat", "food" };

	public Mod()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		harmony = new Harmony("flueno.SmartContainers");
		assembly = Assembly.GetExecutingAssembly();
		config = ((BaseUnityPlugin)this).Config;
		log = ((BaseUnityPlugin)this).Logger;
	}

	public void Start()
	{
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_054b: Unknown result type (might be due to invalid IL or missing references)
		((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 332, "Nexus mod ID");
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "enabled", true, "Enables this mod");
		MigrateConfig(ConfigOrphanedEntries());
		onlyStackableItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "onlyStackableItems", true, "Rearranges only stackable items");
		hudMessageEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "hudMessageEnabled", true, "Enables hud message indicating that item was routed & placed to some other chest");
		hudMessageText = ((BaseUnityPlugin)this).Config.Bind<string>("General", "hudMessageText", "Routed to another Chest", "HUD message consists of Icon, item-name plus this text.");
		range = ((BaseUnityPlugin)this).Config.Bind<int>("General", "range", 14, new ConfigDescription("Range within which containers will participate in resources arrangement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 99), Array.Empty<object>()));
		keyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "hkeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "Change only if you wish to have even longer than ctrl+click combination (holding ctrl is mandatory since it's a 'move-stack' ingame key)");
		gamepadKey1 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "gamepadKey1", "JoyLTrigger", "first part of gamepads transfer-item key-combo");
		gamepadKey2 = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "gamepadKey2", new KeyboardShortcut((KeyCode)332, Array.Empty<KeyCode>()), "second part of gamepads transfer-item key-combo");
		audioFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "audioFeedbackEnabled", true, "Enables playing of sound on successful items transfer");
		effectFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "effectFeedbackEnabled", true, "Enables highlighting of end-target chests where items have been transferred.");
		concurrencyWorkaround = ((BaseUnityPlugin)this).Config.Bind<ConcurrentChestModificationWorkaround>("General", "concurrentChestModificationWorkaround", ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers, "There are rare possibility of items loss if two players simultaneously (within a ~second) modify same containers inventory. Options are: ignore possible issue; ignore 'opened' chests; block mod if any other nearby player opened a chest");
		groupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "enabled", true, "Enables distributing items to containers with 'same-kinded' items (used if no nearby containers contain 'same item')");
		itemTypeGroupsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "itemTypeGroupsEnabled", true, "Enable grouping by item-types (Trophie, Tool, Ammo, Armor, Weapon).");
		fuzzyGroupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "fuzzyGroupingEnabled", false, "Enable grouping by more broad criteria.");
		groupingKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Grouping", "groupingKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), " Change to 'LeftControl + LeftShift' if you want to trigger grouping with a separate hotkey (ctrl+shift+click)(holding ctrl is mandatory since it's a 'move-stack' ingame key)");
		createGroupBtnEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "createGroupBtnEnabled", true, "Adds to the chest UI button [☼] which creates items-group based on the current items set in the chest.");
		mergePromptEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "mergePromptEnabled", true, "In case when createGroupBtn clicked and chest already contains some members of one ore more groups - dialog showed with option to merge items & groups into a single group.");
		createGroupBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Grouping", "createGroupBtnPos", new Vector2(1.5f, 10.7f), "Adjusts btn position on inventory ui. →x:1.5..-10 ↓y:0.4..10.7  bottom-left: (1.5f, 10.7f) top-right:(-10f, 0.4f) bottom-right:(-10f, 10.7f)");
		((BaseUnityPlugin)this).Config.Bind<string>("PrefixedItemGroups", "prefixes", "trophy,mead,arrow,armor,cape,helmet,atgeir,bow,battleaxe,knife,mace,shield,sledge,spear,sword,tankard,club,mushroom,arrow", groupDescr("If both item names start with same 'prefix' - they are considered to have same group. I.e. arrowFire & arrowFlint"));
		((BaseUnityPlugin)this).Config.Bind<string>("PostfixedItemGroups", "posfixes", "cone,seeds,pelt,hide,berries", groupDescr("If both item names end with same 'postfix' - they are considered to have same group. I.e. carrotSeeds & turnipSeeds"));
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "valuables", "ruby,coins,amber,amberpearl", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ore", "copperore,flametalore,ironore,silverore,tinore,ironscrap,blackmetalscrap", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "rock", "stone,flint,obsidian", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ingots", "copper,bronze,flametal,iron,silver,tin,blackmetal", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "wood", "wood,finewood,corewood,elderbark,roundlog", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "mushrooms", "Mushroom,MushroomBlue,MushroomYellow,mushroomcommon", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "berries", "Blueberries,raspberries,cloudberries,honey", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "vegetables", "Carrot,Turnip", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "cookedMeat", "CookedLoxMeat,NeckTailGrilled,MeatCooked,FishCooked,SerpentMeatCooked", groupDescr());
		((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "food", "CarrotSoup,Sausages,QueensJam,SerpentStew,TurnipStew,BloodPudding", groupDescr());
		unloadAllEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "enabled", false, "Enables Unload-all option & UI button [\\||/]. Allows to batch-unload all eligible items from players inventory to their corresponding stacks & groups in nearby chests.");
		unloadAllInsteadStackBtn = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "nativeButton", false, "Use existing 'place-stacks' UI button for unloading. If disabled - new UI button [\\||/] will be created.");
		unloadAllBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Unload", "btnPos", new Vector2(1.5f, 8.15f), (ConfigDescription)null);
		unloadAllItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsList' instead of creating new items group");
		unloadForceGrouping = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "alwaysGrouping", true, "If enabled - check for groupingKeyModifier pressed is ignored for 'unload' button");
		unloadAllSkipItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToSkipItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsSkipList' instead of creating new items group");
		unloadAllItemsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsList", "", groupDescr("List of item-names allowed to be 'unloaded'"));
		unloadAllSkipList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsSkipList", "", groupDescr("List of item-names to exclude from being 'unloaded'"));
		unloadAllGroupsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "groupsList", "valuables,ore,wood,mushrooms", "List of items group-ids from [ItemGroup] config section allowed to be 'unloaded'");
		unloadAllPrefixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "prefixItemGroups", "trophy", (ConfigDescription)null);
		unloadAllPostfixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "postfixItemGroups", "seeds", (ConfigDescription)null);
		unloadAllMaterialsFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "materialsFiltering", true, "allow all Materials to be 'unloaded'");
		unloadAllTrophiesFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "trophiesFiltering", true, "allow all Trophies to be 'unloaded'");
		unloadAllConsumableFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "consumableFiltering", false, "allow all Consumables to be 'unloaded'");
		if (modEnabled.Value)
		{
			ItemGroups.ParseConfig();
			UnloadItems.ParseConfig();
			ContainersTracker.Init();
			Gui_Patch.Init();
			((BaseUnityPlugin)this).Config.SettingChanged += HandleConfigUpdate;
			harmony.PatchAll(assembly);
		}
	}

	public static ConfigDescription groupDescr(string descr = "Items-group based on item-names list")
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected O, but got Unknown
		return new ConfigDescription(descr, (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				CustomDrawer = TextAreaDrawer
			}
		});
	}

	private static void TextAreaDrawer(ConfigEntryBase entry)
	{
		GUILayout.ExpandHeight(true);
		GUILayout.ExpandWidth(true);
		entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.ExpandWidth(true),
			GUILayout.ExpandHeight(true)
		});
	}

	private void HandleConfigUpdate(object sender, SettingChangedEventArgs e)
	{
		if (ignoreUpdate)
		{
			ignoreUpdate = false;
			log.LogInfo((object)$"SettingChangedEventArgs (ignored) {e.ChangedSetting.Definition}");
			return;
		}
		Gui_Patch.Clean();
		Gui_Patch.Init();
		ItemGroups.Clear();
		ItemGroups.ParseConfig();
		UnloadItems.Clear();
		UnloadItems.ParseConfig();
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
		((BaseUnityPlugin)this).Config.Reload();
		Gui_Patch.Clean();
		ItemGroups.Clear();
		UnloadItems.Clear();
		ContainersTracker.containerList.Clear();
	}

	public static bool isSystemGroup(string groupId)
	{
		return systemGroupKeys.Contains(groupId);
	}

	public static void PlayEffect(bool allowed, string prefabName, Vector3 pos)
	{
		//IL_0019: 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 (allowed)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)prefab != (Object)null)
			{
				Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity);
			}
			else
			{
				log.LogWarning((object)("Failed to locate FeedbackEffect " + prefabName + " prefab"));
			}
		}
	}

	public static Dictionary<ConfigDefinition, string> ConfigOrphanedEntries()
	{
		return Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>();
	}

	private static void MigrateConfig(Dictionary<ConfigDefinition, string> orphans)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		//IL_0051: Expected O, but got Unknown
		//IL_005c: 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_0075: Expected O, but got Unknown
		//IL_0075: Expected O, but got Unknown
		//IL_0080: 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_0099: Expected O, but got Unknown
		//IL_0099: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Expected O, but got Unknown
		//IL_00bd: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Expected O, but got Unknown
		//IL_00e1: Expected O, but got Unknown
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (orphans.ContainsKey(new ConfigDefinition("ItemGroup", "coockedMeat")))
		{
			orphans.Remove(new ConfigDefinition("ItemGroup", "coockedMeat"));
		}
		ChangeKey<bool>(orphans, new ConfigDefinition("General", "groupingEnabled"), new ConfigDefinition("Grouping", "enabled"));
		ChangeKey<bool>(orphans, new ConfigDefinition("General", "itemTypeGroupsEnabled"), new ConfigDefinition("Grouping", "itemTypeGroupsEnabled"));
		ChangeKey<bool>(orphans, new ConfigDefinition("General", "fuzzyGroupingEnabled"), new ConfigDefinition("Grouping", "fuzzyGroupingEnabled"));
		ChangeKey<bool>(orphans, new ConfigDefinition("General", "createGroupBtnEnabled"), new ConfigDefinition("Grouping", "createGroupBtnEnabled"));
		ChangeKey<Vector2>(orphans, new ConfigDefinition("General", "createGroupBtnPos"), new ConfigDefinition("Grouping", "createGroupBtnPos"));
	}

	private static void ChangeKey<T>(Dictionary<ConfigDefinition, string> orphans, ConfigDefinition dkey, ConfigDefinition dkeyNew)
	{
		if (orphans.ContainsKey(dkey))
		{
			orphans.Add(dkeyNew, orphans[dkey]);
			orphans.Remove(dkey);
		}
	}
}
public enum ConcurrentChestModificationWorkaround
{
	None,
	ExcludeContainersOpenedByOthers,
	BlockIfOtherContainersAreOpened
}
internal static class ConcurrentChestModificationWorkaroundMethods
{
	public static bool SkipOpenedOthers(this ConcurrentChestModificationWorkaround option)
	{
		return option == ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers;
	}

	public static bool Ignore(this ConcurrentChestModificationWorkaround option)
	{
		return option == ConcurrentChestModificationWorkaround.None;
	}

	public static bool BlockIfAnyOtherOpened(this ConcurrentChestModificationWorkaround option)
	{
		return option == ConcurrentChestModificationWorkaround.BlockIfOtherContainersAreOpened;
	}
}
internal static class KeyboardShortcutMethods
{
	public static bool IsPressedOrNone(this KeyboardShortcut shortcut)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Invalid comparison between Unknown and I4
		if (!((KeyboardShortcut)(ref shortcut)).IsPressed())
		{
			return (int)((KeyboardShortcut)(ref shortcut)).MainKey == 0;
		}
		return true;
	}

	public static bool MainPressed(this KeyboardShortcut shortcut)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey);
	}
}
internal static class ItemDataMethods
{
	public static string SCName(this string itemName)
	{
		return itemName.ToLower().Replace("$item_", "").Replace("_", "");
	}

	public static string SCName(this ItemData itemDrop)
	{
		return itemDrop.m_shared.m_name.SCName();
	}
}
internal static class EnumerableMethods
{
	public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector)
	{
		return self.Select(selector);
	}

	public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func)
	{
		return self.Aggregate(func);
	}

	public static T Reduce<T>(this IEnumerable<T> self, T seed, Func<T, T, T> func)
	{
		return self.Aggregate(seed, func);
	}

	public static IEnumerable<R> FlatMap<T, R>(this IEnumerable<T> self, Func<T, IEnumerable<R>> func)
	{
		return self.SelectMany(func);
	}

	public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate)
	{
		return self.Where(predicate);
	}
}
public static class UnloadItems
{
	private static ISet<string> unloadAllItemsList = new HashSet<string>();

	private static ISet<string> unloadAllItemsSkipList = new HashSet<string>();

	public static ICollection<string> unloadAllGroupsList = new HashSet<string>();

	private static ICollection<string> unloadAllPrefixItemGroups = new HashSet<string>();

	private static ICollection<string> unloadAllPostfixItemGroups = new HashSet<string>();

	public static void ParseConfig()
	{
		if (Mod.unloadAllPrefixItemGroups.Value.Length > 0)
		{
			unloadAllPrefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPrefixItemGroups);
		}
		if (Mod.unloadAllPostfixItemGroups.Value.Length > 0)
		{
			unloadAllPostfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPostfixItemGroups);
		}
		if (Mod.unloadAllItemsList.Value.Length > 0)
		{
			unloadAllItemsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllItemsList);
		}
		if (Mod.unloadAllSkipList.Value.Length > 0)
		{
			unloadAllItemsSkipList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllSkipList);
		}
		if (Mod.unloadAllGroupsList.Value.Length > 0)
		{
			unloadAllGroupsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllGroupsList);
		}
	}

	public static void UnloadAllItems(Inventory playerInv)
	{
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		List<ItemData> list = playerInv.m_inventory.Filter((ItemData i) => !i.m_equipped).Map((ItemData i) => (i, i.m_shared.m_name.SCName())).Filter<(ItemData, string)>(((ItemData i, string) tuple) => !Mod.onlyStackableItems.Value || tuple.i.m_shared.m_maxStackSize > 1)
			.Filter<(ItemData, string)>(((ItemData i, string) tuple) => !unloadAllItemsSkipList.Contains(tuple.Item2))
			.Filter<(ItemData, string)>(((ItemData i, string) tuple) => (Mod.unloadAllMaterialsFiltering.Value && (int)tuple.i.m_shared.m_itemType == 1) || (Mod.unloadAllTrophiesFiltering.Value && (int)tuple.i.m_shared.m_itemType == 13) || (Mod.unloadAllConsumableFiltering.Value && (int)tuple.i.m_shared.m_itemType == 2) || (unloadAllItemsList.Any() && unloadAllItemsList.Contains(tuple.Item2)) || (unloadAllPrefixItemGroups.Any() && TestList((string _) => tuple.Item2.StartsWith(_), unloadAllPrefixItemGroups)) || (unloadAllPostfixItemGroups.Any() && TestList((string _) => tuple.Item2.EndsWith(_), unloadAllPostfixItemGroups)) || (unloadAllGroupsList.Any() && unloadAllGroupsList.Any((string groupId) => TestList((string _) => tuple.Item2.Equals(_), ItemGroups.Groups[groupId]))))
			.Map<(ItemData, string), ItemData>(((ItemData i, string) tuple) => tuple.i)
			.ToList();
		bool flag = false;
		foreach (ItemData item in list)
		{
			if (Inventory_Patch.TryAddToNearBy(item, allowCurrent: true, Mod.unloadForceGrouping.Value))
			{
				playerInv.RemoveItem(item);
				if (!flag)
				{
					Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
					flag = true;
				}
			}
		}
	}

	public static void AddToUnloadAllItemsFilter(Inventory inventory)
	{
		Mod.unloadAllItemsList = AddToItemListConfig(inventory, unloadAllItemsList, Mod.unloadAllItemsList, "Added {0} items to unload-items filter");
	}

	public static void AddToUnloadAllItemsSkipList(Inventory inventory)
	{
		Mod.unloadAllSkipList = AddToItemListConfig(inventory, unloadAllItemsSkipList, Mod.unloadAllSkipList, "Added {0} items to unload-skip-items list");
	}

	private static ConfigEntry<string> AddToItemListConfig(Inventory inventory, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage)
	{
		List<string> list = ItemGroupUtils.ExtractUniqueItemNames(inventory);
		if (list.Count < 1)
		{
			return configEntry;
		}
		return ItemGroupUtils.AddToItemListConfig(list, targetSet, configEntry, uiMessage);
	}

	private static bool TestList(Func<string, bool> predicate, ICollection<string> group)
	{
		foreach (string item in group)
		{
			if (predicate(item))
			{
				return true;
			}
		}
		return false;
	}

	public static void Clear()
	{
		unloadAllItemsList.Clear();
		unloadAllItemsSkipList.Clear();
		unloadAllGroupsList.Clear();
		unloadAllPrefixItemGroups.Clear();
		unloadAllPostfixItemGroups.Clear();
	}
}

BepInEx/plugins/Trinsic-Better_Wisplight/Toombe_BetterWispLight.dll

Decompiled 6 months ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BetterWispLight")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HP")]
[assembly: AssemblyProduct("BetterWispLight")]
[assembly: AssemblyCopyright("Copyright © HP 2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f18cf8b6-b433-4736-a499-13a764b20ea1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BetterWisplight;

[BepInPlugin("toombe.BetterWisplight", "Better Wisplight", "1.0.0")]
[BepInProcess("valheim.exe")]
public class BetterWisplight : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Demister), "Awake")]
	private static class Demister_Awake_Patch
	{
		private static void Postfix(ref ParticleSystemForceField ___m_forceField)
		{
			Debug.Log((object)$"Old forcefield: {___m_forceField.endRange}");
			ParticleSystemForceField obj = ___m_forceField;
			obj.endRange *= demisterRangeMultiplier.Value;
			Debug.Log((object)$"New forcefield: {___m_forceField.endRange}");
		}
	}

	private readonly Harmony harmony = new Harmony("toombe.BetterWisplight");

	private static ConfigEntry<float> demisterRangeMultiplier;

	private void Awake()
	{
		demisterRangeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "demisterRangeMultiplier", 2f, "Demister Range Multiplier");
		Debug.Log((object)"Initialized Better Wisplight");
		harmony.PatchAll();
	}

	private void DisableForcefield()
	{
		harmony.UnpatchSelf();
	}
}

BepInEx/plugins/Valheim.DisplayBepInExInfo.dll

Decompiled 6 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace Valheim.DisplayBepInExInfo;

[BepInPlugin("org.bepinex.valheim.displayinfo", "Display BepInEx Info In-Game", "2.0.2")]
public class DisplayInfoPlugin : BaseUnityPlugin
{
	internal static ConfigEntry<LogLevel> LogLevels;

	internal static ConfigEntry<bool> DisplayLogsInConsole;

	internal static string BepInExVersion => typeof(BaseUnityPlugin).Assembly.GetName().Version.ToString();

	private void Awake()
	{
		LogLevels = ((BaseUnityPlugin)this).Config.Bind<LogLevel>("Console", "LogLevels", (LogLevel)30, "Log levels to log to Valheim console.");
		DisplayLogsInConsole = ((BaseUnityPlugin)this).Config.Bind<bool>("Console", "DisplayBepInExLogs", true, "If true, will display BepInEx logs in Valheim console.");
		if (DisplayLogsInConsole.Value)
		{
			Logger.Listeners.Add((ILogListener)(object)new ValheimConsoleListener());
		}
		Harmony.CreateAndPatchAll(typeof(DisplayInfoPlugin), (string)null);
		Traverse.Create<Game>().Field<bool>("isModded").Value = true;
	}

	[HarmonyPatch(typeof(FejdStartup), "Start")]
	[HarmonyPostfix]
	private static void OnFejdStartup(FejdStartup __instance)
	{
		//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_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_005c: 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_0081: 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)
		if ((Object)(object)__instance == (Object)null)
		{
			Debug.LogWarning((object)"Instance is null");
			return;
		}
		GameObject gameObject = ((Component)__instance.m_versionLabel.transform.parent).gameObject;
		GameObject val = new GameObject("BepInEx Version");
		val.transform.parent = gameObject.transform;
		val.AddComponent<CanvasRenderer>();
		val.transform.localPosition = Vector3.zero;
		RectTransform obj = val.AddComponent<RectTransform>();
		obj.anchorMin = new Vector2(0.03f, 0.95f);
		obj.anchorMax = new Vector2(0.3f, 0.95f);
		Text val2 = val.AddComponent<Text>();
		val2.font = Font.CreateDynamicFontFromOSFont("Arial", 20);
		val2.text = $"Running BepInEx {BepInExVersion}\n{Chainloader.PluginInfos.Count} plugins loaded";
		if ((Object)(object)Console.instance != (Object)null && Console.instance.IsConsoleEnabled())
		{
			val2.text += "\nPress F5 to open console";
		}
		((Graphic)val2).color = Color.white;
		val2.fontSize = 20;
	}

	[HarmonyPatch(typeof(ZNet), "SetServer")]
	[HarmonyPostfix]
	private static void OnServerStart(string serverName)
	{
		Type type = typeof(BaseUnityPlugin).Assembly.GetType("BepInEx.ConsoleManager", throwOnError: false);
		if (!(type == null))
		{
			AccessTools.MethodDelegate<Action<string>>(AccessTools.Method(type, "SetConsoleTitle", (Type[])null, (Type[])null), (object)null, true)("BepInEx " + BepInExVersion + " - Valheim Server - " + serverName);
		}
	}

	[HarmonyPatch(typeof(Terminal), "Awake")]
	[HarmonyPostfix]
	private static void FixConsoleMesh()
	{
		if (Object.op_Implicit((Object)(object)Console.instance) && Object.op_Implicit((Object)(object)((Component)((Terminal)Console.instance).m_chatWindow).gameObject))
		{
			Outline[] componentsInChildren = ((Component)((Terminal)Console.instance).m_chatWindow).gameObject.GetComponentsInChildren<Outline>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
			}
		}
	}

	[HarmonyPatch(typeof(Terminal), "UpdateChat")]
	[HarmonyPostfix]
	private static void FixConsoleMesh2()
	{
		if (((TMP_Text)((Terminal)Console.instance).m_output).text.Length > 6000)
		{
			((Terminal)Console.instance).m_chatBuffer.Clear();
		}
	}
}
internal class ValheimConsoleListener : ILogListener, IDisposable
{
	public void Dispose()
	{
	}

	public void LogEvent(object sender, LogEventArgs eventArgs)
	{
		//IL_0001: 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_0010: Unknown result type (might be due to invalid IL or missing references)
		if ((eventArgs.Level & DisplayInfoPlugin.LogLevels.Value) != 0 && Object.op_Implicit((Object)(object)Console.instance))
		{
			Console.instance.Print(((object)eventArgs).ToString());
		}
	}
}

BepInEx/plugins/ValheimModding-Jotunn/Jotunn.dll

Decompiled 6 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.GUI;
using Jotunn.Managers;
using Jotunn.Managers.MockSystem;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using SimpleJson;
using SimpleJson.Reflection;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("JotunnTests")]
[assembly: InternalsVisibleTo("JotunnDoc")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Valheim-Modding team")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Jötunn (/ˈjɔːtʊn/, \"giant\") is a modding library for Valheim, with the goal of making the lives of mod developers easier.")]
[assembly: AssemblyFileVersion("2.19.3.0")]
[assembly: AssemblyInformationalVersion("2.19.3+53d0c8916dbe6b1bdba2460aa3bdbb5f031baad2")]
[assembly: AssemblyProduct("JotunnLib")]
[assembly: AssemblyTitle("Jotunn")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Valheim-Modding/Jotunn")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.19.3.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
internal class CompatibilityWindow : MonoBehaviour
{
	public ScrollRect scrollRect;

	public Text failedConnection;

	public Text localVersion;

	public Text remoteVersion;

	public Text errorMessages;

	public Button continueButton;

	public Button logFileButton;

	public Button troubleshootingButton;

	public void UpdateTextPositions()
	{
		//IL_003b: 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_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_0068: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Expected O, but got Unknown
		float preferredHeight = failedConnection.preferredHeight;
		float preferredHeight2 = localVersion.preferredHeight;
		float preferredHeight3 = remoteVersion.preferredHeight;
		float preferredHeight4 = errorMessages.preferredHeight;
		Vector2 anchoredPosition = ((Graphic)localVersion).rectTransform.anchoredPosition;
		Vector2 anchoredPosition2 = ((Graphic)remoteVersion).rectTransform.anchoredPosition;
		float num = preferredHeight + 32f;
		((Graphic)localVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition.x, 0f - num);
		((Graphic)remoteVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition2.x, 0f - num);
		Vector2 anchoredPosition3 = ((Graphic)errorMessages).rectTransform.anchoredPosition;
		float num2 = num + Mathf.Max(preferredHeight2, preferredHeight3) + 32f;
		((Graphic)errorMessages).rectTransform.anchoredPosition = new Vector2(anchoredPosition3.x, 0f - num2);
		RectTransform val = (RectTransform)((Component)scrollRect.content).transform;
		val.SetSizeWithCurrentAnchors((Axis)1, num2 + preferredHeight4);
	}
}
public sealed class ConfigurationManagerAttributes
{
	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;

	private bool isAdminOnly;

	private bool isUnlocked;

	private static readonly PropertyInfo[] _myProperties = typeof(ConfigurationManagerAttributes).GetProperties(BindingFlags.Instance | BindingFlags.Public);

	private static readonly FieldInfo[] _myFields = typeof(ConfigurationManagerAttributes).GetFields(BindingFlags.Instance | BindingFlags.Public);

	public bool IsAdminOnly
	{
		get
		{
			return isAdminOnly;
		}
		set
		{
			isAdminOnly = value;
			IsUnlocked = !value;
		}
	}

	public Color EntryColor { get; set; }

	public Color DescriptionColor { get; set; }

	public bool IsUnlocked
	{
		get
		{
			return isUnlocked;
		}
		internal set
		{
			ReadOnly = !value;
			HideDefaultButton = !value;
			isUnlocked = value;
		}
	}

	public ConfigurationManagerAttributes()
	{
		//IL_001b: 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)
		EntryColor = new Color(1f, 0.631f, 0.235f, 1f);
		DescriptionColor = Color.white;
	}

	public void SetFromAttributes(object[] attribs)
	{
		if (attribs == null || attribs.Length == 0)
		{
			return;
		}
		foreach (object obj in attribs)
		{
			if (obj == null)
			{
				continue;
			}
			if (!(obj is DisplayNameAttribute displayNameAttribute))
			{
				if (!(obj is CategoryAttribute categoryAttribute))
				{
					if (!(obj is DescriptionAttribute descriptionAttribute))
					{
						if (!(obj is DefaultValueAttribute defaultValueAttribute))
						{
							if (!(obj is ReadOnlyAttribute readOnlyAttribute))
							{
								if (!(obj is BrowsableAttribute browsableAttribute))
								{
									if (obj is string text)
									{
										switch (text)
										{
										case "ReadOnly":
											ReadOnly = true;
											break;
										case "Browsable":
											Browsable = true;
											break;
										case "Unbrowsable":
										case "Hidden":
											Browsable = false;
											break;
										case "Advanced":
											IsAdvanced = true;
											break;
										}
										continue;
									}
									Type type = obj.GetType();
									if (!(type.Name == "ConfigurationManagerAttributes"))
									{
										break;
									}
									FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
									foreach (var item in from my in _myProperties
										join other in fields on my.Name equals other.Name
										select new { my, other })
									{
										try
										{
											object obj2 = item.other.GetValue(obj);
											if (obj2 != null)
											{
												if (item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType))
												{
													obj2 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj2).Target, ((Delegate)obj2).Method);
												}
												item.my.SetValue(this, obj2, null);
											}
										}
										catch (Exception ex)
										{
											Logger.LogWarning("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message);
										}
									}
									foreach (var item2 in from my in _myFields
										join other in fields on my.Name equals other.Name
										select new { my, other })
									{
										try
										{
											object obj3 = item2.other.GetValue(obj);
											if (obj3 != null)
											{
												if (item2.my.FieldType != item2.other.FieldType && typeof(Delegate).IsAssignableFrom(item2.my.FieldType))
												{
													obj3 = Delegate.CreateDelegate(item2.my.FieldType, ((Delegate)obj3).Target, ((Delegate)obj3).Method);
												}
												item2.my.SetValue(this, obj3);
											}
										}
										catch (Exception ex2)
										{
											Logger.LogWarning("Failed to copy value " + item2.my.Name + " from provided tag object " + type.FullName + " - " + ex2.Message);
										}
									}
								}
								else
								{
									Browsable = browsableAttribute.Browsable;
								}
							}
							else
							{
								ReadOnly = readOnlyAttribute.IsReadOnly;
							}
						}
						else
						{
							DefaultValue = defaultValueAttribute.Value;
						}
					}
					else
					{
						Description = descriptionAttribute.Description;
					}
				}
				else
				{
					Category = categoryAttribute.Category;
				}
			}
			else
			{
				DispName = displayNameAttribute.DisplayName;
			}
		}
	}
}
public static class ObjImporter
{
	private struct meshStruct
	{
		public Vector3[] vertices;

		public Vector3[] normals;

		public Vector2[] uv;

		public Vector2[] uv1;

		public Vector2[] uv2;

		public int[] triangles;

		public int[] faceVerts;

		public int[] faceUVs;

		public Vector3[] faceData;

		public string name;

		public string fileName;
	}

	public static Mesh ImportFile(string filePath)
	{
		//IL_004f: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: 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_00e7: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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)
		meshStruct mesh = CreateMeshStruct(filePath);
		PopulateMeshStruct(ref mesh);
		Vector3[] array = (Vector3[])(object)new Vector3[mesh.faceData.Length];
		Vector2[] array2 = (Vector2[])(object)new Vector2[mesh.faceData.Length];
		Vector3[] array3 = (Vector3[])(object)new Vector3[mesh.faceData.Length];
		int num = 0;
		Vector3[] faceData = mesh.faceData;
		foreach (Vector3 val in faceData)
		{
			array[num] = mesh.vertices[(int)val.x - 1];
			if (val.y >= 1f)
			{
				array2[num] = mesh.uv[(int)val.y - 1];
			}
			if (val.z >= 1f)
			{
				array3[num] = mesh.normals[(int)val.z - 1];
			}
			num++;
		}
		Mesh val2 = new Mesh();
		val2.vertices = array;
		val2.uv = array2;
		val2.normals = array3;
		val2.triangles = mesh.triangles;
		val2.RecalculateBounds();
		val2.Optimize();
		return val2;
	}

	private static meshStruct CreateMeshStruct(string filename)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		meshStruct result = default(meshStruct);
		result.fileName = filename;
		StreamReader streamReader = File.OpenText(filename);
		string s = streamReader.ReadToEnd();
		streamReader.Close();
		using (StringReader stringReader = new StringReader(s))
		{
			string text = stringReader.ReadLine();
			char[] separator = new char[1] { ' ' };
			while (text != null)
			{
				if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn "))
				{
					text = stringReader.ReadLine();
					if (text != null)
					{
						text = text.Replace("  ", " ");
					}
					continue;
				}
				text = text.Trim();
				string[] array = text.Split(separator, 50);
				switch (array[0])
				{
				case "v":
					num2++;
					break;
				case "vt":
					num3++;
					break;
				case "vn":
					num4++;
					break;
				case "f":
					num5 = num5 + array.Length - 1;
					num += 3 * (array.Length - 2);
					break;
				}
				text = stringReader.ReadLine();
				if (text != null)
				{
					text = text.Replace("  ", " ");
				}
			}
		}
		result.triangles = new int[num];
		result.vertices = (Vector3[])(object)new Vector3[num2];
		result.uv = (Vector2[])(object)new Vector2[num3];
		result.normals = (Vector3[])(object)new Vector3[num4];
		result.faceData = (Vector3[])(object)new Vector3[num5];
		return result;
	}

	private static void PopulateMeshStruct(ref meshStruct mesh)
	{
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_032e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_0425: Unknown result type (might be due to invalid IL or missing references)
		StreamReader streamReader = File.OpenText(mesh.fileName);
		string s = streamReader.ReadToEnd();
		streamReader.Close();
		using StringReader stringReader = new StringReader(s);
		string text = stringReader.ReadLine();
		char[] separator = new char[1] { ' ' };
		char[] separator2 = new char[1] { '/' };
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		while (text != null)
		{
			if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn ") && !text.StartsWith("g ") && !text.StartsWith("usemtl ") && !text.StartsWith("mtllib ") && !text.StartsWith("vt1 ") && !text.StartsWith("vt2 ") && !text.StartsWith("vc ") && !text.StartsWith("usemap "))
			{
				text = stringReader.ReadLine();
				if (text != null)
				{
					text = text.Replace("  ", " ");
				}
				continue;
			}
			text = text.Trim();
			string[] array = text.Split(separator, 50);
			switch (array[0])
			{
			case "v":
				mesh.vertices[num3] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3]));
				num3++;
				break;
			case "vt":
				mesh.uv[num5] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num5++;
				break;
			case "vt1":
				mesh.uv[num6] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num6++;
				break;
			case "vt2":
				mesh.uv[num7] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num7++;
				break;
			case "vn":
				mesh.normals[num4] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3]));
				num4++;
				break;
			case "f":
			{
				int num8 = 1;
				List<int> list = new List<int>();
				while (num8 < array.Length && (array[num8] ?? "").Length > 0)
				{
					Vector3 val = default(Vector3);
					string[] array2 = array[num8].Split(separator2, 3);
					val.x = Convert.ToInt32(array2[0]);
					if (array2.Length > 1)
					{
						if (array2[1] != "")
						{
							val.y = Convert.ToInt32(array2[1]);
						}
						val.z = Convert.ToInt32(array2[2]);
					}
					num8++;
					mesh.faceData[num2] = val;
					list.Add(num2);
					num2++;
				}
				for (num8 = 1; num8 + 2 < array.Length; num8++)
				{
					mesh.triangles[num] = list[0];
					num++;
					mesh.triangles[num] = list[num8];
					num++;
					mesh.triangles[num] = list[num8 + 1];
					num++;
				}
				break;
			}
			}
			text = stringReader.ReadLine();
			if (text != null)
			{
				text = text.Replace("  ", " ");
			}
		}
	}
}
namespace SimpleJson
{
	[GeneratedCode("simple-json", "1.0.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public class JsonArray : List<object>
	{
		public JsonArray()
		{
		}

		public JsonArray(int capacity)
			: base(capacity)
		{
		}

		public override string ToString()
		{
			return SimpleJson.SerializeObject(this) ?? string.Empty;
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public class JsonObject : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
	{
		private readonly Dictionary<string, object> _members;

		public object this[int index] => GetAtIndex(_members, index);

		public ICollection<string> Keys => _members.Keys;

		public ICollection<object> Values => _members.Values;

		public object this[string key]
		{
			get
			{
				return _members[key];
			}
			set
			{
				_members[key] = value;
			}
		}

		public int Count => _members.Count;

		public bool IsReadOnly => false;

		public JsonObject()
		{
			_members = new Dictionary<string, object>();
		}

		public JsonObject(IEqualityComparer<string> comparer)
		{
			_members = new Dictionary<string, object>(comparer);
		}

		internal static object GetAtIndex(IDictionary<string, object> obj, int index)
		{
			if (obj == null)
			{
				throw new ArgumentNullException("obj");
			}
			if (index >= obj.Count)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			int num = 0;
			foreach (KeyValuePair<string, object> item in obj)
			{
				if (num++ == index)
				{
					return item.Value;
				}
			}
			return null;
		}

		public void Add(string key, object value)
		{
			_members.Add(key, value);
		}

		public bool ContainsKey(string key)
		{
			return _members.ContainsKey(key);
		}

		public bool Remove(string key)
		{
			return _members.Remove(key);
		}

		public bool TryGetValue(string key, out object value)
		{
			return _members.TryGetValue(key, out value);
		}

		public void Add(KeyValuePair<string, object> item)
		{
			_members.Add(item.Key, item.Value);
		}

		public void Clear()
		{
			_members.Clear();
		}

		public bool Contains(KeyValuePair<string, object> item)
		{
			if (_members.ContainsKey(item.Key))
			{
				return _members[item.Key] == item.Value;
			}
			return false;
		}

		public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			int num = Count;
			using IEnumerator<KeyValuePair<string, object>> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, object> current = enumerator.Current;
				array[arrayIndex++] = current;
				if (--num <= 0)
				{
					break;
				}
			}
		}

		public bool Remove(KeyValuePair<string, object> item)
		{
			return _members.Remove(item.Key);
		}

		public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
		{
			return _members.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _members.GetEnumerator();
		}

		public override string ToString()
		{
			return SimpleJson.SerializeObject(this);
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public static class SimpleJson
	{
		private const int TOKEN_NONE = 0;

		private const int TOKEN_CURLY_OPEN = 1;

		private const int TOKEN_CURLY_CLOSE = 2;

		private const int TOKEN_SQUARED_OPEN = 3;

		private const int TOKEN_SQUARED_CLOSE = 4;

		private const int TOKEN_COLON = 5;

		private const int TOKEN_COMMA = 6;

		private const int TOKEN_STRING = 7;

		private const int TOKEN_NUMBER = 8;

		private const int TOKEN_TRUE = 9;

		private const int TOKEN_FALSE = 10;

		private const int TOKEN_NULL = 11;

		private const int BUILDER_CAPACITY = 2000;

		private static readonly char[] EscapeTable;

		private static readonly char[] EscapeCharacters;

		private static readonly string EscapeCharactersString;

		private static IJsonSerializerStrategy _currentJsonSerializerStrategy;

		private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy;

		public static IJsonSerializerStrategy CurrentJsonSerializerStrategy
		{
			get
			{
				return _currentJsonSerializerStrategy ?? (_currentJsonSerializerStrategy = PocoJsonSerializerStrategy);
			}
			set
			{
				_currentJsonSerializerStrategy = value;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy => _pocoJsonSerializerStrategy ?? (_pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy());

		static SimpleJson()
		{
			EscapeCharacters = new char[7] { '"', '\\', '\b', '\f', '\n', '\r', '\t' };
			EscapeCharactersString = new string(EscapeCharacters);
			EscapeTable = new char[93];
			EscapeTable[34] = '"';
			EscapeTable[92] = '\\';
			EscapeTable[8] = 'b';
			EscapeTable[12] = 'f';
			EscapeTable[10] = 'n';
			EscapeTable[13] = 'r';
			EscapeTable[9] = 't';
		}

		public static object DeserializeObject(string json)
		{
			if (TryDeserializeObject(json, out var obj))
			{
				return obj;
			}
			throw new SerializationException("Invalid JSON string");
		}

		public static bool TryDeserializeObject(string json, out object obj)
		{
			bool success = true;
			if (json != null)
			{
				char[] json2 = json.ToCharArray();
				int index = 0;
				obj = ParseValue(json2, ref index, ref success);
			}
			else
			{
				obj = null;
			}
			return success;
		}

		public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			object obj = DeserializeObject(json);
			if (!(type == null) && (obj == null || !ReflectionUtils.IsAssignableFrom(obj.GetType(), type)))
			{
				return (jsonSerializerStrategy ?? CurrentJsonSerializerStrategy).DeserializeObject(obj, type);
			}
			return obj;
		}

		public static object DeserializeObject(string json, Type type)
		{
			return DeserializeObject(json, type, null);
		}

		public static T DeserializeObject<T>(string json, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			return (T)DeserializeObject(json, typeof(T), jsonSerializerStrategy);
		}

		public static T DeserializeObject<T>(string json)
		{
			return (T)DeserializeObject(json, typeof(T), null);
		}

		public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			StringBuilder stringBuilder = new StringBuilder(2000);
			if (!SerializeValue(jsonSerializerStrategy, json, stringBuilder))
			{
				return null;
			}
			return stringBuilder.ToString();
		}

		public static string SerializeObject(object json)
		{
			return SerializeObject(json, CurrentJsonSerializerStrategy);
		}

		public static string EscapeToJavascriptString(string jsonString)
		{
			if (string.IsNullOrEmpty(jsonString))
			{
				return jsonString;
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			while (num < jsonString.Length)
			{
				char c = jsonString[num++];
				if (c == '\\')
				{
					int num2 = jsonString.Length - num;
					if (num2 >= 2)
					{
						switch (jsonString[num])
						{
						case '\\':
							stringBuilder.Append('\\');
							num++;
							break;
						case '"':
							stringBuilder.Append("\"");
							num++;
							break;
						case 't':
							stringBuilder.Append('\t');
							num++;
							break;
						case 'b':
							stringBuilder.Append('\b');
							num++;
							break;
						case 'n':
							stringBuilder.Append('\n');
							num++;
							break;
						case 'r':
							stringBuilder.Append('\r');
							num++;
							break;
						}
					}
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		private static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
		{
			IDictionary<string, object> dictionary = new JsonObject();
			NextToken(json, ref index);
			bool flag = false;
			while (!flag)
			{
				switch (LookAhead(json, index))
				{
				case 0:
					success = false;
					return null;
				case 6:
					NextToken(json, ref index);
					continue;
				case 2:
					NextToken(json, ref index);
					return dictionary;
				}
				string key = ParseString(json, ref index, ref success);
				if (!success)
				{
					success = false;
					return null;
				}
				int num = NextToken(json, ref index);
				if (num != 5)
				{
					success = false;
					return null;
				}
				object value = ParseValue(json, ref index, ref success);
				if (!success)
				{
					success = false;
					return null;
				}
				dictionary[key] = value;
			}
			return dictionary;
		}

		private static JsonArray ParseArray(char[] json, ref int index, ref bool success)
		{
			JsonArray jsonArray = new JsonArray();
			NextToken(json, ref index);
			bool flag = false;
			while (!flag)
			{
				switch (LookAhead(json, index))
				{
				case 0:
					success = false;
					return null;
				case 6:
					NextToken(json, ref index);
					continue;
				case 4:
					break;
				default:
				{
					object item = ParseValue(json, ref index, ref success);
					if (!success)
					{
						return null;
					}
					jsonArray.Add(item);
					continue;
				}
				}
				NextToken(json, ref index);
				break;
			}
			return jsonArray;
		}

		private static object ParseValue(char[] json, ref int index, ref bool success)
		{
			switch (LookAhead(json, index))
			{
			case 7:
				return ParseString(json, ref index, ref success);
			case 8:
				return ParseNumber(json, ref index, ref success);
			case 1:
				return ParseObject(json, ref index, ref success);
			case 3:
				return ParseArray(json, ref index, ref success);
			case 9:
				NextToken(json, ref index);
				return true;
			case 10:
				NextToken(json, ref index);
				return false;
			case 11:
				NextToken(json, ref index);
				return null;
			default:
				success = false;
				return null;
			}
		}

		private static string ParseString(char[] json, ref int index, ref bool success)
		{
			StringBuilder stringBuilder = new StringBuilder(2000);
			EatWhitespace(json, ref index);
			char c = json[index++];
			bool flag = false;
			while (!flag && index != json.Length)
			{
				c = json[index++];
				switch (c)
				{
				case '"':
					flag = true;
					break;
				case '\\':
				{
					if (index == json.Length)
					{
						break;
					}
					switch (json[index++])
					{
					case '"':
						stringBuilder.Append('"');
						continue;
					case '\\':
						stringBuilder.Append('\\');
						continue;
					case '/':
						stringBuilder.Append('/');
						continue;
					case 'b':
						stringBuilder.Append('\b');
						continue;
					case 'f':
						stringBuilder.Append('\f');
						continue;
					case 'n':
						stringBuilder.Append('\n');
						continue;
					case 'r':
						stringBuilder.Append('\r');
						continue;
					case 't':
						stringBuilder.Append('\t');
						continue;
					case 'u':
						break;
					default:
						continue;
					}
					int num = json.Length - index;
					if (num < 4)
					{
						break;
					}
					if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)))
					{
						return "";
					}
					if (55296 <= result && result <= 56319)
					{
						index += 4;
						num = json.Length - index;
						if (num < 6 || !(new string(json, index, 2) == "\\u") || !uint.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result2) || 56320 > result2 || result2 > 57343)
						{
							success = false;
							return "";
						}
						stringBuilder.Append((char)result);
						stringBuilder.Append((char)result2);
						index += 6;
					}
					else
					{
						stringBuilder.Append(ConvertFromUtf32((int)result));
						index += 4;
					}
					continue;
				}
				default:
					stringBuilder.Append(c);
					continue;
				}
				break;
			}
			if (!flag)
			{
				success = false;
				return null;
			}
			return stringBuilder.ToString();
		}

		private static string ConvertFromUtf32(int utf32)
		{
			if (utf32 < 0 || utf32 > 1114111)
			{
				throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
			}
			if (55296 <= utf32 && utf32 <= 57343)
			{
				throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
			}
			if (utf32 < 65536)
			{
				return new string((char)utf32, 1);
			}
			utf32 -= 65536;
			return new string(new char[2]
			{
				(char)((utf32 >> 10) + 55296),
				(char)(utf32 % 1024 + 56320)
			});
		}

		private static object ParseNumber(char[] json, ref int index, ref bool success)
		{
			EatWhitespace(json, ref index);
			int lastIndexOfNumber = GetLastIndexOfNumber(json, index);
			int length = lastIndexOfNumber - index + 1;
			string text = new string(json, index, length);
			object result2;
			if (text.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || text.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
			{
				success = double.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result);
				result2 = result;
			}
			else
			{
				success = long.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result3);
				result2 = result3;
			}
			index = lastIndexOfNumber + 1;
			return result2;
		}

		private static int GetLastIndexOfNumber(char[] json, int index)
		{
			int i;
			for (i = index; i < json.Length && "0123456789+-.eE".IndexOf(json[i]) != -1; i++)
			{
			}
			return i - 1;
		}

		private static void EatWhitespace(char[] json, ref int index)
		{
			while (index < json.Length && " \t\n\r\b\f".IndexOf(json[index]) != -1)
			{
				index++;
			}
		}

		private static int LookAhead(char[] json, int index)
		{
			int index2 = index;
			return NextToken(json, ref index2);
		}

		private static int NextToken(char[] json, ref int index)
		{
			EatWhitespace(json, ref index);
			if (index == json.Length)
			{
				return 0;
			}
			char c = json[index];
			index++;
			switch (c)
			{
			case '{':
				return 1;
			case '}':
				return 2;
			case '[':
				return 3;
			case ']':
				return 4;
			case ',':
				return 6;
			case '"':
				return 7;
			case '-':
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				return 8;
			case ':':
				return 5;
			default:
			{
				index--;
				int num = json.Length - index;
				if (num >= 5 && json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e')
				{
					index += 5;
					return 10;
				}
				if (num >= 4 && json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e')
				{
					index += 4;
					return 9;
				}
				if (num >= 4 && json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l')
				{
					index += 4;
					return 11;
				}
				return 0;
			}
			}
		}

		private static bool SerializeValue(IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder)
		{
			bool flag = true;
			if (value is string aString)
			{
				flag = SerializeString(aString, builder);
			}
			else if (value is IDictionary<string, object> dictionary)
			{
				flag = SerializeObject(jsonSerializerStrategy, dictionary.Keys, dictionary.Values, builder);
			}
			else if (value is IDictionary<string, string> dictionary2)
			{
				flag = SerializeObject(jsonSerializerStrategy, dictionary2.Keys, dictionary2.Values, builder);
			}
			else if (value is IEnumerable anArray)
			{
				flag = SerializeArray(jsonSerializerStrategy, anArray, builder);
			}
			else if (IsNumeric(value))
			{
				flag = SerializeNumber(value, builder);
			}
			else if (value is bool)
			{
				builder.Append(((bool)value) ? "true" : "false");
			}
			else if (value == null)
			{
				builder.Append("null");
			}
			else
			{
				flag = jsonSerializerStrategy.TrySerializeNonPrimitiveObject(value, out var output);
				if (flag)
				{
					SerializeValue(jsonSerializerStrategy, output, builder);
				}
			}
			return flag;
		}

		private static bool SerializeObject(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder)
		{
			builder.Append("{");
			IEnumerator enumerator = keys.GetEnumerator();
			IEnumerator enumerator2 = values.GetEnumerator();
			bool flag = true;
			while (enumerator.MoveNext() && enumerator2.MoveNext())
			{
				object current = enumerator.Current;
				object current2 = enumerator2.Current;
				if (!flag)
				{
					builder.Append(",");
				}
				if (current is string aString)
				{
					SerializeString(aString, builder);
				}
				else if (!SerializeValue(jsonSerializerStrategy, current2, builder))
				{
					return false;
				}
				builder.Append(":");
				if (!SerializeValue(jsonSerializerStrategy, current2, builder))
				{
					return false;
				}
				flag = false;
			}
			builder.Append("}");
			return true;
		}

		private static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder)
		{
			builder.Append("[");
			bool flag = true;
			foreach (object item in anArray)
			{
				if (!flag)
				{
					builder.Append(",");
				}
				if (!SerializeValue(jsonSerializerStrategy, item, builder))
				{
					return false;
				}
				flag = false;
			}
			builder.Append("]");
			return true;
		}

		private static bool SerializeString(string aString, StringBuilder builder)
		{
			if (aString.IndexOfAny(EscapeCharacters) == -1)
			{
				builder.Append('"');
				builder.Append(aString);
				builder.Append('"');
				return true;
			}
			builder.Append('"');
			int num = 0;
			char[] array = aString.ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				char c = array[i];
				if (c >= EscapeTable.Length || EscapeTable[(uint)c] == '\0')
				{
					num++;
					continue;
				}
				if (num > 0)
				{
					builder.Append(array, i - num, num);
					num = 0;
				}
				builder.Append('\\');
				builder.Append(EscapeTable[(uint)c]);
			}
			if (num > 0)
			{
				builder.Append(array, array.Length - num, num);
			}
			builder.Append('"');
			return true;
		}

		private static bool SerializeNumber(object number, StringBuilder builder)
		{
			if (number is long)
			{
				builder.Append(((long)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is ulong)
			{
				builder.Append(((ulong)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is int)
			{
				builder.Append(((int)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is uint)
			{
				builder.Append(((uint)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is decimal)
			{
				builder.Append(((decimal)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is float)
			{
				builder.Append(((float)number).ToString(CultureInfo.InvariantCulture));
			}
			else
			{
				builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture));
			}
			return true;
		}

		private static bool IsNumeric(object value)
		{
			if (value is sbyte)
			{
				return true;
			}
			if (value is byte)
			{
				return true;
			}
			if (value is short)
			{
				return true;
			}
			if (value is ushort)
			{
				return true;
			}
			if (value is int)
			{
				return true;
			}
			if (value is uint)
			{
				return true;
			}
			if (value is long)
			{
				return true;
			}
			if (value is ulong)
			{
				return true;
			}
			if (value is float)
			{
				return true;
			}
			if (value is double)
			{
				return true;
			}
			if (value is decimal)
			{
				return true;
			}
			return false;
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public interface IJsonSerializerStrategy
	{
		bool TrySerializeNonPrimitiveObject(object input, out object output);

		object DeserializeObject(object value, Type type);
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public class PocoJsonSerializerStrategy : IJsonSerializerStrategy
	{
		internal IDictionary<Type, ReflectionUtils.ConstructorDelegate> ConstructorCache;

		internal IDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>> GetCache;

		internal IDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>> SetCache;

		internal static readonly Type[] EmptyTypes = new Type[0];

		internal static readonly Type[] ArrayConstructorParameterTypes = new Type[1] { typeof(int) };

		private static readonly string[] Iso8601Format = new string[3] { "yyyy-MM-dd\\THH:mm:ss.FFFFFFF\\Z", "yyyy-MM-dd\\THH:mm:ss\\Z", "yyyy-MM-dd\\THH:mm:ssK" };

		public PocoJsonSerializerStrategy()
		{
			ConstructorCache = new ReflectionUtils.ThreadSafeDictionary<Type, ReflectionUtils.ConstructorDelegate>(ContructorDelegateFactory);
			GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
			SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
		}

		protected virtual string MapClrMemberNameToJsonFieldName(string clrPropertyName)
		{
			return clrPropertyName;
		}

		internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory(Type key)
		{
			return ReflectionUtils.GetContructor(key, key.IsArray ? ArrayConstructorParameterTypes : EmptyTypes);
		}

		internal virtual IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
		{
			IDictionary<string, ReflectionUtils.GetDelegate> dictionary = new Dictionary<string, ReflectionUtils.GetDelegate>();
			foreach (PropertyInfo property in ReflectionUtils.GetProperties(type))
			{
				if (property.CanRead)
				{
					MethodInfo getterMethodInfo = ReflectionUtils.GetGetterMethodInfo(property);
					if (!getterMethodInfo.IsStatic && getterMethodInfo.IsPublic)
					{
						dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = ReflectionUtils.GetGetMethod(property);
					}
				}
			}
			foreach (FieldInfo field in ReflectionUtils.GetFields(type))
			{
				if (!field.IsStatic && field.IsPublic)
				{
					dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = ReflectionUtils.GetGetMethod(field);
				}
			}
			return dictionary;
		}

		internal virtual IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
		{
			IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> dictionary = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
			foreach (PropertyInfo property in ReflectionUtils.GetProperties(type))
			{
				if (property.CanWrite)
				{
					MethodInfo setterMethodInfo = ReflectionUtils.GetSetterMethodInfo(property);
					if (!setterMethodInfo.IsStatic && setterMethodInfo.IsPublic)
					{
						dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(property.PropertyType, ReflectionUtils.GetSetMethod(property));
					}
				}
			}
			foreach (FieldInfo field in ReflectionUtils.GetFields(type))
			{
				if (!field.IsInitOnly && !field.IsStatic && field.IsPublic)
				{
					dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(field.FieldType, ReflectionUtils.GetSetMethod(field));
				}
			}
			return dictionary;
		}

		public virtual bool TrySerializeNonPrimitiveObject(object input, out object output)
		{
			if (!TrySerializeKnownTypes(input, out output))
			{
				return TrySerializeUnknownTypes(input, out output);
			}
			return true;
		}

		public virtual object DeserializeObject(object value, Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			string text = value as string;
			if (type == typeof(Guid) && string.IsNullOrEmpty(text))
			{
				return default(Guid);
			}
			if (value == null)
			{
				return null;
			}
			object obj = null;
			if (text != null)
			{
				if (text.Length != 0)
				{
					if (type == typeof(DateTime) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime)))
					{
						return DateTime.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
					}
					if (type == typeof(DateTimeOffset) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTimeOffset)))
					{
						return DateTimeOffset.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
					}
					if (type == typeof(Guid) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid)))
					{
						return new Guid(text);
					}
					if (type == typeof(Uri))
					{
						if (Uri.IsWellFormedUriString(text, UriKind.RelativeOrAbsolute) && Uri.TryCreate(text, UriKind.RelativeOrAbsolute, out Uri result))
						{
							return result;
						}
						return null;
					}
					if (type == typeof(string))
					{
						return text;
					}
					return Convert.ChangeType(text, type, CultureInfo.InvariantCulture);
				}
				obj = ((type == typeof(Guid)) ? ((object)default(Guid)) : ((!ReflectionUtils.IsNullableType(type) || !(Nullable.GetUnderlyingType(type) == typeof(Guid))) ? text : null));
				if (!ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
				{
					return text;
				}
			}
			else if (value is bool)
			{
				return value;
			}
			bool flag = value is long;
			bool flag2 = value is double;
			if ((flag && type == typeof(long)) || (flag2 && type == typeof(double)))
			{
				return value;
			}
			if ((flag2 && type != typeof(double)) || (flag && type != typeof(long)))
			{
				obj = ((type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short)) ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture) : value);
				if (ReflectionUtils.IsNullableType(type))
				{
					return ReflectionUtils.ToNullableType(obj, type);
				}
				return obj;
			}
			if (value is IDictionary<string, object> dictionary)
			{
				IDictionary<string, object> dictionary2 = dictionary;
				if (ReflectionUtils.IsTypeDictionary(type))
				{
					Type[] genericTypeArguments = ReflectionUtils.GetGenericTypeArguments(type);
					Type type2 = genericTypeArguments[0];
					Type type3 = genericTypeArguments[1];
					Type key = typeof(Dictionary<, >).MakeGenericType(type2, type3);
					IDictionary dictionary3 = (IDictionary)ConstructorCache[key]();
					foreach (KeyValuePair<string, object> item in dictionary2)
					{
						dictionary3.Add(item.Key, DeserializeObject(item.Value, type3));
					}
					obj = dictionary3;
				}
				else if (type == typeof(object))
				{
					obj = value;
				}
				else
				{
					obj = ConstructorCache[type]();
					foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> item2 in SetCache[type])
					{
						if (dictionary2.TryGetValue(item2.Key, out var value2))
						{
							value2 = DeserializeObject(value2, item2.Value.Key);
							item2.Value.Value(obj, value2);
						}
					}
				}
			}
			else if (value is IList<object> list)
			{
				IList<object> list2 = list;
				IList list3 = null;
				if (type.IsArray)
				{
					list3 = (IList)ConstructorCache[type](list2.Count);
					int num = 0;
					foreach (object item3 in list2)
					{
						list3[num++] = DeserializeObject(item3, type.GetElementType());
					}
				}
				else if (ReflectionUtils.IsTypeGenericeCollectionInterface(type) || ReflectionUtils.IsAssignableFrom(typeof(IList), type))
				{
					Type genericListElementType = ReflectionUtils.GetGenericListElementType(type);
					list3 = (IList)(ConstructorCache[type] ?? ConstructorCache[typeof(List<>).MakeGenericType(genericListElementType)])(list2.Count);
					foreach (object item4 in list2)
					{
						list3.Add(DeserializeObject(item4, genericListElementType));
					}
				}
				obj = list3;
			}
			return obj;
		}

		protected virtual object SerializeEnum(Enum p)
		{
			return Convert.ToDouble(p, CultureInfo.InvariantCulture);
		}

		protected virtual bool TrySerializeKnownTypes(object input, out object output)
		{
			bool result = true;
			if (input is DateTime)
			{
				output = ((DateTime)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
			}
			else if (input is DateTimeOffset)
			{
				output = ((DateTimeOffset)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
			}
			else if (input is Guid)
			{
				output = ((Guid)input).ToString("D");
			}
			else if (input is Uri)
			{
				output = input.ToString();
			}
			else if (input is Enum p)
			{
				output = SerializeEnum(p);
			}
			else
			{
				result = false;
				output = null;
			}
			return result;
		}

		protected virtual bool TrySerializeUnknownTypes(object input, out object output)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			output = null;
			Type type = input.GetType();
			if (type.FullName == null)
			{
				return false;
			}
			IDictionary<string, object> dictionary = new JsonObject();
			IDictionary<string, ReflectionUtils.GetDelegate> dictionary2 = GetCache[type];
			foreach (KeyValuePair<string, ReflectionUtils.GetDelegate> item in dictionary2)
			{
				if (item.Value != null)
				{
					dictionary.Add(MapClrMemberNameToJsonFieldName(item.Key), item.Value(input));
				}
			}
			output = dictionary;
			return true;
		}
	}
}
namespace SimpleJson.Reflection
{
	[GeneratedCode("reflection-utils", "1.0.0")]
	internal class ReflectionUtils
	{
		public delegate object GetDelegate(object source);

		public delegate void SetDelegate(object source, object value);

		public delegate object ConstructorDelegate(params object[] args);

		public delegate TValue ThreadSafeDictionaryValueFactory<TKey, TValue>(TKey key);

		private static class Assigner<T>
		{
			public static T Assign(ref T left, T right)
			{
				return left = right;
			}
		}

		public sealed class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
		{
			private readonly object _lock = new object();

			private readonly ThreadSafeDictionaryValueFactory<TKey, TValue> _valueFactory;

			private Dictionary<TKey, TValue> _dictionary;

			public ICollection<TKey> Keys => _dictionary.Keys;

			public ICollection<TValue> Values => _dictionary.Values;

			public TValue this[TKey key]
			{
				get
				{
					return Get(key);
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			public int Count => _dictionary.Count;

			public bool IsReadOnly
			{
				get
				{
					throw new NotImplementedException();
				}
			}

			public ThreadSafeDictionary(ThreadSafeDictionaryValueFactory<TKey, TValue> valueFactory)
			{
				_valueFactory = valueFactory;
			}

			private TValue Get(TKey key)
			{
				if (_dictionary == null)
				{
					return AddValue(key);
				}
				if (!_dictionary.TryGetValue(key, out var value))
				{
					return AddValue(key);
				}
				return value;
			}

			private TValue AddValue(TKey key)
			{
				TValue val = _valueFactory(key);
				lock (_lock)
				{
					if (_dictionary == null)
					{
						_dictionary = new Dictionary<TKey, TValue>();
						_dictionary[key] = val;
					}
					else
					{
						if (_dictionary.TryGetValue(key, out var value))
						{
							return value;
						}
						Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(_dictionary);
						dictionary[key] = val;
						_dictionary = dictionary;
					}
				}
				return val;
			}

			public void Add(TKey key, TValue value)
			{
				throw new NotImplementedException();
			}

			public bool ContainsKey(TKey key)
			{
				return _dictionary.ContainsKey(key);
			}

			public bool Remove(TKey key)
			{
				throw new NotImplementedException();
			}

			public bool TryGetValue(TKey key, out TValue value)
			{
				value = this[key];
				return true;
			}

			public void Add(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public void Clear()
			{
				throw new NotImplementedException();
			}

			public bool Contains(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
			{
				throw new NotImplementedException();
			}

			public bool Remove(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
			{
				return _dictionary.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return _dictionary.GetEnumerator();
			}
		}

		private static readonly object[] EmptyObjects = new object[0];

		public static Type GetTypeInfo(Type type)
		{
			return type;
		}

		public static Attribute GetAttribute(MemberInfo info, Type type)
		{
			if (info == null || type == null || !Attribute.IsDefined(info, type))
			{
				return null;
			}
			return Attribute.GetCustomAttribute(info, type);
		}

		public static Type GetGenericListElementType(Type type)
		{
			IEnumerable<Type> interfaces = type.GetInterfaces();
			foreach (Type item in interfaces)
			{
				if (IsTypeGeneric(item) && item.GetGenericTypeDefinition() == typeof(IList<>))
				{
					return GetGenericTypeArguments(item)[0];
				}
			}
			return GetGenericTypeArguments(type)[0];
		}

		public static Attribute GetAttribute(Type objectType, Type attributeType)
		{
			if (objectType == null || attributeType == null || !Attribute.IsDefined(objectType, attributeType))
			{
				return null;
			}
			return Attribute.GetCustomAttribute(objectType, attributeType);
		}

		public static Type[] GetGenericTypeArguments(Type type)
		{
			return type.GetGenericArguments();
		}

		public static bool IsTypeGeneric(Type type)
		{
			return GetTypeInfo(type).IsGenericType;
		}

		public static bool IsTypeGenericeCollectionInterface(Type type)
		{
			if (!IsTypeGeneric(type))
			{
				return false;
			}
			Type genericTypeDefinition = type.GetGenericTypeDefinition();
			if (!(genericTypeDefinition == typeof(IList<>)) && !(genericTypeDefinition == typeof(ICollection<>)))
			{
				return genericTypeDefinition == typeof(IEnumerable<>);
			}
			return true;
		}

		public static bool IsAssignableFrom(Type type1, Type type2)
		{
			return GetTypeInfo(type1).IsAssignableFrom(GetTypeInfo(type2));
		}

		public static bool IsTypeDictionary(Type type)
		{
			if (typeof(IDictionary).IsAssignableFrom(type))
			{
				return true;
			}
			if (!GetTypeInfo(type).IsGenericType)
			{
				return false;
			}
			Type genericTypeDefinition = type.GetGenericTypeDefinition();
			return genericTypeDefinition == typeof(IDictionary<, >);
		}

		public static bool IsNullableType(Type type)
		{
			if (GetTypeInfo(type).IsGenericType)
			{
				return type.GetGenericTypeDefinition() == typeof(Nullable<>);
			}
			return false;
		}

		public static object ToNullableType(object obj, Type nullableType)
		{
			if (obj != null)
			{
				return Convert.ChangeType(obj, Nullable.GetUnderlyingType(nullableType), CultureInfo.InvariantCulture);
			}
			return null;
		}

		public static bool IsValueType(Type type)
		{
			return GetTypeInfo(type).IsValueType;
		}

		public static IEnumerable<ConstructorInfo> GetConstructors(Type type)
		{
			return type.GetConstructors();
		}

		public static ConstructorInfo GetConstructorInfo(Type type, params Type[] argsType)
		{
			IEnumerable<ConstructorInfo> constructors = GetConstructors(type);
			foreach (ConstructorInfo item in constructors)
			{
				ParameterInfo[] parameters = item.GetParameters();
				if (argsType.Length != parameters.Length)
				{
					continue;
				}
				int num = 0;
				bool flag = true;
				ParameterInfo[] parameters2 = item.GetParameters();
				foreach (ParameterInfo parameterInfo in parameters2)
				{
					if (parameterInfo.ParameterType != argsType[num])
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					return item;
				}
			}
			return null;
		}

		public static IEnumerable<PropertyInfo> GetProperties(Type type)
		{
			return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static IEnumerable<FieldInfo> GetFields(Type type)
		{
			return type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static MethodInfo GetGetterMethodInfo(PropertyInfo propertyInfo)
		{
			return propertyInfo.GetGetMethod(nonPublic: true);
		}

		public static MethodInfo GetSetterMethodInfo(PropertyInfo propertyInfo)
		{
			return propertyInfo.GetSetMethod(nonPublic: true);
		}

		public static ConstructorDelegate GetContructor(ConstructorInfo constructorInfo)
		{
			return GetConstructorByExpression(constructorInfo);
		}

		public static ConstructorDelegate GetContructor(Type type, params Type[] argsType)
		{
			return GetConstructorByExpression(type, argsType);
		}

		public static ConstructorDelegate GetConstructorByReflection(ConstructorInfo constructorInfo)
		{
			return (object[] args) => constructorInfo.Invoke(args);
		}

		public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType)
		{
			ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
			if (!(constructorInfo == null))
			{
				return GetConstructorByReflection(constructorInfo);
			}
			return null;
		}

		public static ConstructorDelegate GetConstructorByExpression(ConstructorInfo constructorInfo)
		{
			ParameterInfo[] parameters = constructorInfo.GetParameters();
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object[]), "args");
			Expression[] array = new Expression[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Expression index = Expression.Constant(i);
				Type parameterType = parameters[i].ParameterType;
				Expression expression = Expression.ArrayIndex(parameterExpression, index);
				Expression expression2 = Expression.Convert(expression, parameterType);
				array[i] = expression2;
			}
			NewExpression body = Expression.New(constructorInfo, array);
			Expression<Func<object[], object>> expression3 = Expression.Lambda<Func<object[], object>>(body, new ParameterExpression[1] { parameterExpression });
			Func<object[], object> compiledLambda = expression3.Compile();
			return (object[] args) => compiledLambda(args);
		}

		public static ConstructorDelegate GetConstructorByExpression(Type type, params Type[] argsType)
		{
			ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
			if (!(constructorInfo == null))
			{
				return GetConstructorByExpression(constructorInfo);
			}
			return null;
		}

		public static GetDelegate GetGetMethod(PropertyInfo propertyInfo)
		{
			return GetGetMethodByExpression(propertyInfo);
		}

		public static GetDelegate GetGetMethod(FieldInfo fieldInfo)
		{
			return GetGetMethodByExpression(fieldInfo);
		}

		public static GetDelegate GetGetMethodByReflection(PropertyInfo propertyInfo)
		{
			MethodInfo methodInfo = GetGetterMethodInfo(propertyInfo);
			return (object source) => methodInfo.Invoke(source, EmptyObjects);
		}

		public static GetDelegate GetGetMethodByReflection(FieldInfo fieldInfo)
		{
			return (object source) => fieldInfo.GetValue(source);
		}

		public static GetDelegate GetGetMethodByExpression(PropertyInfo propertyInfo)
		{
			MethodInfo getterMethodInfo = GetGetterMethodInfo(propertyInfo);
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType));
			Func<object, object> compiled = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instance, getterMethodInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile();
			return (object source) => compiled(source);
		}

		public static GetDelegate GetGetMethodByExpression(FieldInfo fieldInfo)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			MemberExpression expression = Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo);
			GetDelegate compiled = Expression.Lambda<GetDelegate>(Expression.Convert(expression, typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile();
			return (object source) => compiled(source);
		}

		public static SetDelegate GetSetMethod(PropertyInfo propertyInfo)
		{
			return GetSetMethodByExpression(propertyInfo);
		}

		public static SetDelegate GetSetMethod(FieldInfo fieldInfo)
		{
			return GetSetMethodByExpression(fieldInfo);
		}

		public static SetDelegate GetSetMethodByReflection(PropertyInfo propertyInfo)
		{
			MethodInfo methodInfo = GetSetterMethodInfo(propertyInfo);
			return delegate(object source, object value)
			{
				methodInfo.Invoke(source, new object[1] { value });
			};
		}

		public static SetDelegate GetSetMethodByReflection(FieldInfo fieldInfo)
		{
			return delegate(object source, object value)
			{
				fieldInfo.SetValue(source, value);
			};
		}

		public static SetDelegate GetSetMethodByExpression(PropertyInfo propertyInfo)
		{
			MethodInfo setterMethodInfo = GetSetterMethodInfo(propertyInfo);
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType));
			UnaryExpression unaryExpression = ((!IsValueType(propertyInfo.PropertyType)) ? Expression.TypeAs(parameterExpression2, propertyInfo.PropertyType) : Expression.Convert(parameterExpression2, propertyInfo.PropertyType));
			Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Expression.Call(instance, setterMethodInfo, unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			return delegate(object source, object val)
			{
				compiled(source, val);
			};
		}

		public static SetDelegate GetSetMethodByExpression(FieldInfo fieldInfo)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Assign(Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo), Expression.Convert(parameterExpression2, fieldInfo.FieldType)), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			return delegate(object source, object val)
			{
				compiled(source, val);
			};
		}

		public static BinaryExpression Assign(Expression left, Expression right)
		{
			MethodInfo method = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign");
			return Expression.Add(left, right, method);
		}
	}
}
namespace Jotunn
{
	public static class ArrayExtensions
	{
		public static T[] Populate<T>(this T[] arr, T value)
		{
			for (int i = 0; i < arr.Length; i++)
			{
				arr[i] = value;
			}
			return arr;
		}
	}
	public static class ConfigEntryBaseExtension
	{
		public static bool IsVisible(this ConfigEntryBase configurationEntry)
		{
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes();
			ConfigDescription description = configurationEntry.Description;
			configurationManagerAttributes.SetFromAttributes((description != null) ? description.Tags : null);
			return configurationManagerAttributes.Browsable != false;
		}

		public static bool IsSyncable(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes) is ConfigurationManagerAttributes configurationManagerAttributes)
			{
				return configurationManagerAttributes.IsAdminOnly;
			}
			return false;
		}

		public static string GetBoundButtonName(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry == null)
			{
				throw new ArgumentNullException("configurationEntry");
			}
			if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton))
			{
				return null;
			}
			if (!InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value))
			{
				return null;
			}
			return value.Name;
		}

		public static ButtonConfig GetButtonConfig(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry == null)
			{
				throw new ArgumentNullException("configurationEntry");
			}
			if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton))
			{
				return null;
			}
			InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value);
			return value;
		}

		internal static object GetLocalValue(this ConfigEntryBase configurationEntry)
		{
			if (SynchronizationManager.Instance.localValues.TryGetValue(configurationEntry, out var value))
			{
				return value;
			}
			return null;
		}

		internal static void SetLocalValue(this ConfigEntryBase configurationEntry, object value)
		{
			SynchronizationManager.Instance.localValues[configurationEntry] = value;
		}

		internal static ConfigurationManagerAttributes GetConfigurationManagerAttributes(this ConfigEntryBase configEntry)
		{
			return (ConfigurationManagerAttributes)configEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes);
		}
	}
	internal static class EventExtensions
	{
		public static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
	public static class ExposedGameObjectExtension
	{
		public static GameObject OrNull(this GameObject @this)
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return null;
			}
			return @this;
		}

		public static T OrNull<T>(this T @this) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return default(T);
			}
			return @this;
		}

		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T result = default(T);
			if (!gameObject.TryGetComponent<T>(ref result))
			{
				return gameObject.AddComponent<T>();
			}
			return result;
		}

		public static Component AddComponentCopy<T>(this GameObject gameObject, T duplicate) where T : Component
		{
			Component val = gameObject.AddComponent(((object)duplicate).GetType());
			PropertyInfo[] properties = ((object)duplicate).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				switch (propertyInfo.Name)
				{
				case "mesh":
					if (duplicate is MeshFilter)
					{
						continue;
					}
					break;
				case "material":
				case "materials":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "bounds":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "name":
				case "rayTracingMode":
				case "tag":
					continue;
				}
				if (propertyInfo.CanWrite && propertyInfo.GetMethod != null)
				{
					propertyInfo.SetValue(val, propertyInfo.GetValue(duplicate));
				}
			}
			FieldInfo[] fields = ((object)duplicate).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo.Name == "rayTracingMode"))
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(duplicate));
				}
			}
			return val;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAllComponents(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren(type, includeInactive)))
				{
					return true;
				}
			}
			return false;
		}

		public static Transform FindDeepChild(this GameObject gameObject, string childName, IterativeSearchType searchType = 1)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return gameObject.transform.FindDeepChild(childName, searchType);
		}

		public static Transform FindDeepChild(this GameObject gameObject, IEnumerable<string> childNames, IterativeSearchType searchType = 1)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Transform val = gameObject.transform;
			foreach (string childName in childNames)
			{
				val = val.FindDeepChild(childName, searchType);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return null;
				}
			}
			return val;
		}
	}
	internal static class GameObjectGUIExtension
	{
		internal static GameObject SetToTextHeight(this GameObject go)
		{
			go.GetComponent<RectTransform>().SetSizeWithCurrentAnchors((Axis)1, go.GetComponentInChildren<Text>().preferredHeight + 3f);
			return go;
		}

		internal static GameObject SetUpperLeft(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 1f);
			component.anchorMin = new Vector2(0f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleLeft(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 0.5f);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.pivot = new Vector2(0f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomLeft(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 0f);
			component.anchorMin = new Vector2(0f, 0f);
			component.pivot = new Vector2(0f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetUpperRight(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 1f);
			component.anchorMin = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleRight(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 0.5f);
			component.anchorMin = new Vector2(1f, 0.5f);
			component.pivot = new Vector2(1f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomRight(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 0f);
			component.anchorMin = new Vector2(1f, 0f);
			component.pivot = new Vector2(1f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetUpperCenter(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 1f);
			component.anchorMin = new Vector2(0.5f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleCenter(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomCenter(this GameObject go)
		{
			//IL_0012: 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_003c: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 0f);
			component.anchorMin = new Vector2(0.5f, 0f);
			component.pivot = new Vector2(0.5f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetSize(this GameObject go, float width, float height)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)0, width);
			component.SetSizeWithCurrentAnchors((Axis)1, height);
			return go;
		}

		internal static GameObject SetWidth(this GameObject go, float width)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)0, width);
			return go;
		}

		internal static GameObject SetHeight(this GameObject go, float height)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)1, height);
			return go;
		}

		internal static float GetWidth(this GameObject go)
		{
			//IL_0008: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			Rect rect = component.rect;
			return ((Rect)(ref rect)).width;
		}

		internal static float GetHeight(this GameObject go)
		{
			//IL_0008: 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)
			RectTransform component = go.GetComponent<RectTransform>();
			Rect rect = component.rect;
			return ((Rect)(ref rect)).height;
		}

		internal static float GetTextHeight(this GameObject go)
		{
			return go.GetComponent<Text>().preferredHeight;
		}

		internal static GameObject SetText(this GameObject go, string text)
		{
			Text component = go.GetComponent<Text>();
			if ((Object)(object)component != (Object)null)
			{
				component.text = text;
			}
			TMP_Text component2 = go.GetComponent<TMP_Text>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.text = text;
			}
			return go;
		}
	}
	public static class GameObjectExtension
	{
		public static bool IsValid(this GameObject self)
		{
			string text = ((Object)self).name;
			if (text.IndexOf('(') > 0)
			{
				text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
			}
			if (string.IsNullOrEmpty(text))
			{
				Logger.LogError("GameObject must have a name!");
				return false;
			}
			if (Object.op_Implicit((Object)(object)self.GetComponent<ZNetView>()) && ((Object)self).name.IndexOfAny(new char[2] { ')', ' ' }) > 0)
			{
				Logger.LogError("GameObject name '" + ((Object)self).name + "' must not contain parenthesis or spaces!");
				return false;
			}
			return true;
		}
	}
	public static class ItemDropExtension
	{
		public static string TokenName(this ItemDrop self)
		{
			return self.m_itemData.m_shared.m_name;
		}
	}
	public static class ItemDataExtension
	{
		public static string TokenName(this ItemData self)
		{
			return self.m_shared.m_name;
		}
	}
	public static class RecipeExtension
	{
		public static bool IsValid(this Recipe self)
		{
			try
			{
				string text = ((Object)self).name;
				if (text.IndexOf('(') > 0)
				{
					text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
				}
				if (string.IsNullOrEmpty(text))
				{
					throw new Exception("Recipe must have a name !");
				}
				return true;
			}
			catch (Exception data)
			{
				Logger.LogError(data);
				return false;
			}
		}
	}
	public static class PieceExtension
	{
		public static string TokenName(this Piece self)
		{
			return self.m_name;
		}
	}
	public static class StatusEffectExtension
	{
		public static string TokenName(this StatusEffect self)
		{
			return self.m_name;
		}

		public static bool IsValid(this StatusEffect self)
		{
			try
			{
				string text = ((Object)self).name;
				if (text.IndexOf('(') > 0)
				{
					text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
				}
				if (string.IsNullOrEmpty(text))
				{
					throw new Exception("StatusEffect must have a name !");
				}
				return true;
			}
			catch (Exception data)
			{
				Logger.LogError(data);
				return false;
			}
		}
	}
	public static class PrefabExtension
	{
		public static void FixReferences(this object objectToFix)
		{
			MockManager.FixReferences(objectToFix, 0);
		}

		public static void FixReferences(this GameObject gameObject)
		{
			gameObject.FixReferences(recursive: false);
		}

		public static void FixReferences(this GameObject gameObject, bool recursive)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Component[] components = gameObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform))
				{
					MockManager.FixReferences(val, 0);
				}
			}
			if (!recursive)
			{
				return;
			}
			List<Tuple<Transform, GameObject>> list = new List<Tuple<Transform, GameObject>>();
			foreach (Transform item in gameObject.transform)
			{
				Transform val2 = item;
				GameObject realPrefabFromMock = MockManager.GetRealPrefabFromMock<GameObject>((Object)(object)((Component)val2).gameObject);
				if (Object.op_Implicit((Object)(object)realPrefabFromMock))
				{
					list.Add(new Tuple<Transform, GameObject>(val2, realPrefabFromMock));
				}
				else
				{
					((Component)val2).gameObject.FixReferences(recursive: true);
				}
			}
			foreach (Tuple<Transform, GameObject> item2 in list)
			{
				MockManager.ReplaceMockGameObject(item2.Item1, item2.Item2, gameObject);
			}
		}

		public static void CloneFields(this GameObject gameObject, GameObject objectToClone)
		{
			Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>();
			Component[] componentsInChildren = objectToClone.GetComponentsInChildren<Component>();
			Component[] array = componentsInChildren;
			foreach (Component val in array)
			{
				FieldInfo[] fields = ((object)val).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
					{
						dictionary.Add(fieldInfo, fieldInfo.GetValue(val));
					}
				}
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(((object)val).GetType())))
				{
					gameObject.AddComponent(((object)val).GetType());
				}
			}
			Component[] componentsInChildren2 = gameObject.GetComponentsInChildren<Component>();
			Component[] array2 = componentsInChildren2;
			foreach (Component val2 in array2)
			{
				FieldInfo[] fields2 = ((object)val2).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo2 in fields2)
				{
					if (dictionary.TryGetValue(fieldInfo2, out var value))
					{
						fieldInfo2.SetValue(val2, value);
					}
				}
			}
		}
	}
	internal static class ObjectExtension
	{
		public static string GetObjectString(this object obj)
		{
			if (obj == null)
			{
				return "null";
			}
			string text = $"{obj}";
			Type type = obj.GetType();
			IEnumerable<FieldInfo> enumerable = from f in type.GetFields()
				where f.IsPublic
				select f;
			foreach (FieldInfo item in enumerable)
			{
				object value = item.GetValue(obj);
				string text2 = ((value == null) ? "null" : value.ToString());
				text = text + "\n " + item.Name + ": " + text2;
			}
			PropertyInfo[] properties = type.GetProperties();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				object value2 = propertyInfo.GetValue(obj, null);
				string text3 = ((value2 == null) ? "null" : value2.ToString());
				text = text + "\n " + propertyInfo.Name + ": " + text3;
			}
			return text;
		}
	}
	public static class RectTransformExtensions
	{
		public static bool Overlaps(this RectTransform a, RectTransform b)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = a.WorldRect();
			return ((Rect)(ref val)).Overlaps(b.WorldRect());
		}

		public static bool Overlaps(this RectTransform a, RectTransform b, bool allowInverse)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = a.WorldRect();
			return ((Rect)(ref val)).Overlaps(b.WorldRect(), allowInverse);
		}

		public static Rect WorldRect(this RectTransform rectTransform)
		{
			//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_0007: 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)
			//IL_001a: 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_002e: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			Vector2 sizeDelta = rectTransform.sizeDelta;
			float num = sizeDelta.x * ((Transform)rectTransform).lossyScale.x;
			float num2 = sizeDelta.y * ((Transform)rectTransform).lossyScale.y;
			Vector3 position = ((Transform)rectTransform).position;
			return new Rect(position.x - num / 2f, position.y - num2 / 2f, num, num2);
		}
	}
	public static class ZNetExtension
	{
		public enum ZNetInstanceType
		{
			Local,
			Client,
			Server
		}

		public static bool IsLocalInstance(this ZNet znet)
		{
			if (znet.IsServer())
			{
				return !znet.IsDedicated();
			}
			return false;
		}

		public static bool IsClientInstance(this ZNet znet)
		{
			if (!znet.IsServer())
			{
				return !znet.IsDedicated();
			}
			return false;
		}

		public static bool IsServerInstance(this ZNet znet)
		{
			if (znet.IsServer())
			{
				return znet.IsDedicated();
			}
			return false;
		}

		public static ZNetInstanceType GetInstanceType(this ZNet znet)
		{
			if (znet.IsLocalInstance())
			{
				return ZNetInstanceType.Local;
			}
			if (znet.IsClientInstance())
			{
				return ZNetInstanceType.Client;
			}
			return ZNetInstanceType.Server;
		}

		public static bool IsAdmin(this ZNet znet, long uid)
		{
			if (!Object.op_Implicit((Object)(object)znet))
			{
				Logger.LogWarning("IsAdmin check failed: ZNet is null");
				return false;
			}
			if (znet.m_adminList == null)
			{
				Logger.LogWarning("IsAdmin check failed: admin list is only available on the server");
				return false;
			}
			ZNetPeer peer = znet.GetPeer(uid);
			if (peer == null)
			{
				Logger.LogWarning($"IsAdmin check failed: peer not found with id {uid}");
				return false;
			}
			string hostName = peer.m_socket.GetHostName();
			if (!string.IsNullOrEmpty(hostName))
			{
				return znet.ListContainsId(znet.m_adminList, hostName);
			}
			return false;
		}
	}
	internal interface IManager
	{
		void Init();
	}
	public class Logger
	{
		public static bool ShowDate = false;

		private static Logger instance = new Logger();

		private readonly Dictionary<string, ManualLogSource> logger = new Dictionary<string, ManualLogSource>();

		internal static void Destroy()
		{
			LogDebug("Destroying Logger");
			foreach (KeyValuePair<string, ManualLogSource> item in instance.logger)
			{
				Logger.Sources.Remove((ILogSource)(object)item.Value);
			}
			instance.logger.Clear();
		}

		private ManualLogSource GetLogger()
		{
			Type declaringType = new StackFrame(3).GetMethod().DeclaringType;
			if (!logger.TryGetValue(declaringType.FullName, out var value))
			{
				value = Logger.CreateLogSource(declaringType.FullName);
				logger.Add(declaringType.FullName, value);
			}
			return value;
		}

		private static void Log(LogLevel level, BepInPlugin sourceMod, object data)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			string text = string.Empty;
			if (ShowDate)
			{
				text = text + "[" + DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo) + "] ";
			}
			if (sourceMod != null)
			{
				text = text + "[" + sourceMod.Name + "] ";
			}
			instance.GetLogger().Log(level, (object)$"{text}{data}");
		}

		public static void LogFatal(object data)
		{
			Log((LogLevel)1, null, data);
		}

		public static void LogFatal(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)1, sourceMod, data);
		}

		public static void LogError(object data)
		{
			Log((LogLevel)2, null, data);
		}

		public static void LogError(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)2, sourceMod, data);
		}

		public static void LogWarning(object data)
		{
			Log((LogLevel)4, null, data);
		}

		public static void LogWarning(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)4, sourceMod, data);
		}

		public static void LogMessage(object data)
		{
			Log((LogLevel)8, null, data);
		}

		public static void LogMessage(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)8, sourceMod, data);
		}

		public static void LogInfo(object data)
		{
			Log((LogLevel)16, null, data);
		}

		public static void LogInfo(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)16, sourceMod, data);
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, null, data);
		}

		public static void LogDebug(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)32, sourceMod, data);
		}
	}
	[BepInPlugin("com.jotunn.jotunn", "Jotunn", "2.19.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(CompatibilityLevel.VersionCheckOnly, VersionStrictness.Minor)]
	public class Main : BaseUnityPlugin
	{
		public const string Version = "2.19.3";

		public const string ModName = "Jotunn";

		public const string ModGuid = "com.jotunn.jotunn";

		internal static Main Instance;

		internal static Harmony Harmony = new Harmony("com.jotunn.jotunn");

		private static GameObject rootObject;

		internal static GameObject RootObject => GetRootObject();

		private void Awake()
		{
			Instance = this;
			GetRootObject();
			ModCompatibility.Init();
			((IManager)SynchronizationManager.Instance).Init();
			Runtime.MakeAllAssetsLoadable();
			Game.isModded = true;
		}

		private void Start()
		{
			PatchInit.InitializePatches();
			AutomaticLocalizationsLoading.Init();
		}

		private void OnApplicationQuit()
		{
			AssetBundle.UnloadAllAssetBundles(false);
		}

		private static GameObject GetRootObject()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)rootObject))
			{
				return rootObject;
			}
			rootObject = new GameObject("_JotunnRoot");
			Object.DontDestroyOnLoad((Object)(object)rootObject);
			return rootObject;
		}

		internal static void LogInit(string module)
		{
			Logger.LogInfo("Initializing " + module);
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				string data = module + " was accessed before Jotunn Awake, this can cause unexpected behaviour. Please make sure to add `[BepInDependency(Jotunn.Main.ModGuid)]` next to your BaseUnityPlugin";
				Logger.LogWarning(BepInExUtils.GetSourceModMetadata(), data);
			}
		}
	}
	internal class ClassMember
	{
		private static readonly Dictionary<Type, ClassMember> CachedClassMembers = new Dictionary<Type, ClassMember>();

		public List<MemberBase> Members { get; private set; } = new List<MemberBase>();


		public Type Type { get; private set; }

		private ClassMember(Type type, IEnumerable<FieldInfo> fieldInfos, IEnumerable<PropertyInfo> propertyInfos)
		{
			Type = type;
			foreach (FieldInfo fieldInfo in fieldInfos)
			{
				AddMember(new FieldMember(fieldInfo));
			}
			foreach (PropertyInfo propertyInfo in propertyInfos)
			{
				AddMember(new PropertyMember(propertyInfo));
			}
		}

		private void AddMember(MemberBase member)
		{
			if (member.IsClass && !(member.MemberType == typeof(string)) && (!(member.EnumeratedType != null) || (member.IsEnumeratedClass && !(member.EnumeratedType == typeof(string)))) && !member.HasCustomAttribute<NonSerializedAttribute>())
			{
				Members.Add(member);
			}
		}

		private static T[] GetMembersFromType<T>(Type type, Func<Type, T[]> getMembers)
		{
			T[] array = getMembers(type);
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				T[] second = getMembers(baseType);
				array = array.Union(second).ToArray();
				baseType = baseType.BaseType;
			}
			return array;
		}

		public static ClassMember GetClassMember(Type type)
		{
			if (CachedClassMembers.TryGetValue(type, out var value))
			{
				return value;
			}
			FieldInfo[] membersFromType = GetMembersFromType(type, (Type t) => t.GetFields(~BindingFlags.Static));
			PropertyInfo[] membersFromType2 = GetMembersFromType(type, (Type t) => t.GetProperties(~BindingFlags.Static));
			value = new ClassMember(type, membersFromType, membersFromType2);
			CachedClassMembers[type] = value;
			return value;
		}
	}
	internal class FieldMember : MemberBase
	{
		private readonly FieldInfo fieldInfo;

		public FieldMember(FieldInfo fieldInfo)
		{
			this.fieldInfo = fieldInfo;
			base.MemberType = fieldInfo.FieldType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = true;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return fieldInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			fieldInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return fieldInfo.GetCustomAttribute<T>() != null;
		}
	}
	internal abstract class MemberBase
	{
		public bool HasGetMethod { get; protected set; }

		public Type MemberType { get; protected set; }

		public Type EnumeratedType { get; protected set; }

		public bool IsUnityObject { get; protected set; }

		public bool IsClass { get; protected set; }

		public bool IsEnumerableOfUnityObjects { get; protected set; }

		public bool IsEnumeratedClass { get; protected set; }

		public abstract object GetValue(object obj);

		public abstract void SetValue(object obj, object value);

		public abstract bool HasCustomAttribute<T>() where T : Attribute;
	}
	internal class PropertyMember : MemberBase
	{
		private readonly PropertyInfo propertyInfo;

		public PropertyMember(PropertyInfo propertyInfo)
		{
			this.propertyInfo = propertyInfo;
			base.MemberType = propertyInfo.PropertyType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.GetMethod != null;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return propertyInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			propertyInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return propertyInfo.GetCustomAttribute<T>() != null;
		}
	}
}
namespace Jotunn.Utils
{
	public static class AssetUtils
	{
		public const char AssetBundlePathSeparator = '$';

		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			string text = texturePath;
			if (relativePath)
			{
				text = Path.Combine(Paths.PluginPath, texturePath);
			}
			if (!File.Exists(text))
			{
				return null;
			}
			if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
			{
				throw new Exception("LoadTexture can only load png or jpg textures");
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		public static Sprite LoadSpriteFromFile(string spritePath)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return LoadSpriteFromFile(spritePath, Vector2.zero);
		}

		public static Sprite LoadSpriteFromFile(string spritePath, Vector2 pivot)
		{
			//IL_002a: 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)
			Texture2D val = LoadTexture(spritePath);
			if ((Object)(object)val != (Object)null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), pivot);
			}
			return null;
		}

		public static Mesh LoadMesh(string meshPath)
		{
			string text = Path.Combine(Paths.PluginPath, meshPath);
			if (!File.Exists(text))
			{
				return null;
			}
			return ObjImporter.ImportFile(text);
		}

		public static AssetBundle LoadAssetBundle(string bundlePath)
		{
			string text = Path.Combine(Paths.PluginPath, bundlePath);
			if (!File.Exists(text))
			{
				return null;
			}
			return AssetBundle.LoadFromFile(text);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Logger.LogError("AssetBundle " + bundleName + " not found in assembly manifest");
				return null;
			}
			using Stream stream = resourceAssembly.GetManifestResourceStream(text);
			return AssetBundle.LoadFromStream(stream);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName)
		{
			return LoadAssetBundleFromResources(bundleName, ReflectionHelper.GetCallingAssembly());
		}

		public static string LoadTextFromResources(string fileName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Logger.LogError("File " + fileName + " not found in assembly manifest");
				return null;
			}
			using Stream stream = resourceAssembly.GetManifestResourceStream(text);
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}

		public static string LoadTextFromResources(string fileName)
		{
			return LoadTextFromResources(fileName, ReflectionHelper.GetCallingAssembly());
		}

		public static string LoadText(string path)
		{
			string text = Path.Combine(Paths.PluginPath, path);
			if (!File.Exists(text))
			{
				Logger.LogError("Error, failed to load contents from non-existant path: $" + text);
				return null;
			}
			return File.ReadAllText(text);
		}

		public static Sprite LoadSprite(string assetPath)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Paths.PluginPath, assetPath);
			if (!File.Exists(text))
			{
				return null;
			}
			if (text.Contains('$'.ToString()))
			{
				string[] array = text.Split(new char[1] { '$' });
				string text2 = array[0];
				string text3 = array[1];
				AssetBundle val = AssetBundle.LoadFromFile(text2);
				Sprite result = val.LoadAsset<Sprite>(text3);
				val.Unload(false);
				return result;
			}
			Texture2D val2 = LoadTexture(text, relativePath: false);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return null;
			}
			return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero);
		}

		internal static bool TryLoadPrefab(BepInPlugin sourceMod, AssetBundle assetBundle, string assetName, out GameObject prefab)
		{
			try
			{
				prefab = assetBundle.LoadAsset<GameObject>(assetName);
			}
			catch (Exception arg)
			{
				prefab = null;
				Logger.LogError(sourceMod, $"Failed to load prefab '{assetName}' from AssetBundle {assetBundle}:\n{arg}");
				return false;
			}
			if (!Object.op_Implicit((Object)(object