Decompiled source of Sandling Invasion v0.1.8

SandlingInvasion.dll

Decompiled a week 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.Security;
using System.Security.Permissions;
using Alexandria.DungeonAPI;
using Alexandria.ItemAPI;
using BepInEx;
using Dungeonator;
using Gungeon;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SandlingInvasion")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SandlingInvasion")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d6d7a494-722e-4763-959b-c2d6b6a42b01")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SandlingInvasion
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("sandlings-united.etg.sandling-invasion", "Sandling Invasion!", "0.1.8")]
	public class Plugin : BaseUnityPlugin
	{
		public static class UI
		{
			public class SpriteHolder
			{
				public const int SpriteRowLimit = 8;

				public readonly Canvas canvas;

				public HorizontalLayoutGroup Layout
				{
					get
					{
						//IL_002d: Unknown result type (might be due to invalid IL or missing references)
						//IL_007d: Unknown result type (might be due to invalid IL or missing references)
						int childCount = ((Component)canvas).transform.childCount;
						if (childCount == 0)
						{
							return new GameObject($"Layout - {childCount + 1}").AddComponent<HorizontalLayoutGroup>();
						}
						HorizontalLayoutGroup val = ((Component)((Component)canvas).transform.GetChild(childCount - 1)).GetComponent<HorizontalLayoutGroup>();
						if (((Component)val).transform.childCount >= 8)
						{
							val = new GameObject($"Layout - {childCount + 1}").AddComponent<HorizontalLayoutGroup>();
							((HorizontalOrVerticalLayoutGroup)val).spacing = 10f;
						}
						return val;
					}
				}

				public SpriteHolder(Canvas canvas)
				{
					this.canvas = canvas;
					base..ctor();
				}

				public T AddComponent<T>() where T : Component
				{
					//IL_0010: 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)
					T val = new GameObject(typeof(T).ToString()).AddComponent<T>();
					((Component)val).transform.localPosition = Vector3.zero;
					((Component)val).transform.SetParent(((Component)Layout).transform, false);
					return val;
				}
			}

			private static SpriteHolder holder;

			public static SpriteHolder Holder
			{
				get
				{
					if (holder == null)
					{
						Canvas canvas = CreateCanvas();
						holder = new SpriteHolder(canvas);
					}
					return holder;
				}
			}

			public static void ShowSprite(Sprite sprite)
			{
				Holder.AddComponent<Image>().sprite = sprite;
			}

			public static void ShowSprite(tk2dBaseSprite sprite)
			{
				Texture[] textures = sprite.Collection.textures;
				foreach (Texture texture in textures)
				{
					Holder.AddComponent<RawImage>().texture = texture;
				}
			}

			public static Sprite ConvertTk2dToUISprite(tk2dBaseSprite tk2dSprite)
			{
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				tk2dSpriteCollectionData collection = tk2dSprite.Collection;
				int spriteId = tk2dSprite.spriteId;
				tk2dSpriteDefinition val = collection.spriteDefinitions[spriteId];
				Texture mainTexture = val.material.mainTexture;
				Texture2D val2 = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
				Rect val3 = default(Rect);
				((Rect)(ref val3))..ctor(val.uvs[0].x * (float)((Texture)val2).width, val.uvs[0].y * (float)((Texture)val2).height, Mathf.Abs(val.uvs[1].x - val.uvs[0].x) * (float)((Texture)val2).width, Mathf.Abs(val.uvs[3].y - val.uvs[0].y) * (float)((Texture)val2).height);
				return Sprite.Create(val2, val3, new Vector2(0.5f, 0.5f), tk2dSprite.Collection.invOrthoSize * 25f);
			}

			private static Canvas CreateCanvas()
			{
				//IL_000d: 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_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Expected O, but got Unknown
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				//IL_0112: Expected O, but got Unknown
				Canvas canvas = new GameObject("Sprite Holder").AddComponent<Canvas>();
				((Component)canvas).transform.localPosition = new Vector3(((Component)canvas).transform.localPosition.x, ((Component)canvas).transform.localPosition.y, -50f);
				canvas.sortingOrder = -10000;
				VerticalLayoutGroup val = ((Component)canvas).gameObject.AddComponent<VerticalLayoutGroup>();
				((LayoutGroup)val).childAlignment = (TextAnchor)4;
				((HorizontalOrVerticalLayoutGroup)val).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = true;
				Image val2 = ((Component)canvas).gameObject.AddComponent<Image>();
				((Graphic)val2).color = new Color(1f, 1f, 1f, 0.6f);
				EventTrigger val3 = ((Component)val2).gameObject.AddComponent<EventTrigger>();
				TriggerEvent val4 = new TriggerEvent();
				((UnityEvent<BaseEventData>)(object)val4).AddListener((UnityAction<BaseEventData>)delegate
				{
					Object.Destroy((Object)(object)((Component)canvas).gameObject);
				});
				val3.triggers.Add(new Entry
				{
					eventID = (EventTriggerType)4,
					callback = val4
				});
				return canvas;
			}
		}

		public static class Debug
		{
			public static void LogItems()
			{
				foreach (KeyValuePair<string, PickupObject> pair in Game.Items.Pairs)
				{
					Log($"{pair.Key}: {pair.Value}");
				}
			}

			public static void LogEnemies()
			{
				foreach (KeyValuePair<string, AIActor> pair in Game.Enemies.Pairs)
				{
					Log($"{pair.Key}: {pair.Value}");
				}
			}
		}

		public const string GUID = "sandlings-united.etg.sandling-invasion";

		public const string NAME = "Sandling Invasion!";

		public const string API = "SandlingAPI";

		public const string VERSION = "0.1.8";

		public const string TEXT_COLOR = "#FFD97F";

		private static bool isRegistered = false;

		private static readonly char[] SplitSeparators = new char[2] { '\n', '\r' };

		public const string WarningColor = "#FF5656";

		private static readonly Dictionary<string, int> counters = new Dictionary<string, int>();

		public void Start()
		{
			ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GMStart);
		}

		public void GMStart(GameManager manager)
		{
			try
			{
				Utils.Initialize();
				Register();
			}
			catch (Exception ex)
			{
				Warning("Sandling Invasion! v0.1.8 was NOT loaded successfully! See the exception:");
				Warning(ex.Message);
				Warning(ex.StackTrace);
			}
			finally
			{
				Log("Sandling Invasion! v0.1.8 started successfully.", "#FFD97F");
			}
		}

		private static void Register()
		{
			if (!isRegistered)
			{
				isRegistered = true;
				Sandling.Register();
			}
		}

		public static void Log()
		{
			Log(string.Empty);
		}

		public static void Log(object value)
		{
			Log(value.ToString());
		}

		public static void Log<T>(ICollection<T> values, string color = "#FFFFFF")
		{
			Log(values, (T v) => ETGMod.ToStringSafe((object)v), color);
		}

		public static void Log<T>(ICollection<T> values, Func<T, string> func, string color = "#FFFFFF")
		{
			foreach (T value in values)
			{
				Log(func(value), color);
			}
		}

		public static void Log<T>(IEnumerable<T> values, string color = "#FFFFFF")
		{
			Log(values, (T v) => ETGMod.ToStringSafe((object)v), color);
		}

		public static void Log<T>(IEnumerable<T> values, Func<T, string> func, string color = "#FFFFFF")
		{
			foreach (T value in values)
			{
				Log(func(value), color);
			}
		}

		public static void Log<T>(T[] values, string color = "#FFFFFF")
		{
			Log(values, (T v) => ETGMod.ToStringSafe((object)v), color);
		}

		public static void Log<T>(T[] values, Func<T, string> func, string color = "#FFFFFF")
		{
			for (int i = 0; i < values.Length; i++)
			{
				Log(func(values[i]), color);
			}
		}

		public static void Log(object obj, string color = "#FFFFFF")
		{
			Log(ETGMod.ToStringSafe(obj), color);
		}

		public static void Log(string text, string color = "#FFFFFF")
		{
			if (Enumerable.Contains(text, '\n'))
			{
				string[] array = text.Split(SplitSeparators, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text2 in array)
				{
					if (!string.IsNullOrEmpty(text2))
					{
						ETGModConsole.Log((object)("[SI] <color=" + color + ">" + text2 + "</color>"), false);
					}
				}
			}
			else
			{
				ETGModConsole.Log((object)("[SI] <color=" + color + ">" + text + "</color>"), false);
			}
		}

		public static void LogFields(object obj, Type type = null)
		{
			if ((object)type == null)
			{
				type = obj.GetType();
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Log("Logging fields of type: " + type.Name);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				object value = fieldInfo.GetValue(obj);
				Log(fieldInfo.Name + " = " + FormatValue(value));
			}
		}

		private static string FormatValue(object value)
		{
			if (value == null)
			{
				return "null";
			}
			if (value is Array array)
			{
				return $"[{array.Length} items]";
			}
			return value.ToString();
		}

		public static void Warning()
		{
			Warning(string.Empty);
		}

		public static void Warning<T>(ICollection<T> values)
		{
			Warning(values, (T v) => ETGMod.ToStringSafe((object)v));
		}

		public static void Warning<T>(ICollection<T> values, Func<T, string> func)
		{
			foreach (T value in values)
			{
				Warning(func(value));
			}
		}

		public static void Warning<T>(IEnumerable<T> values)
		{
			Warning(values, (T v) => ETGMod.ToStringSafe((object)v));
		}

		public static void Warning<T>(IEnumerable<T> values, Func<T, string> func)
		{
			foreach (T value in values)
			{
				Warning(func(value));
			}
		}

		public static void Warning<T>(T[] values)
		{
			Warning(values, (T v) => ETGMod.ToStringSafe((object)v));
		}

		public static void Warning<T>(T[] values, Func<T, string> func)
		{
			for (int i = 0; i < values.Length; i++)
			{
				Log(func(values[i]));
			}
		}

		public static void Warning(object obj)
		{
			Warning(ETGMod.ToStringSafe(obj));
		}

		public static void Warning(string text)
		{
			if (Enumerable.Contains(text, '\n'))
			{
				string[] array = text.Split(SplitSeparators, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text2 in array)
				{
					if (!string.IsNullOrEmpty(text2))
					{
						ETGModConsole.Log((object)("[SI] <color=#FF5656>Warning: " + text2 + "</color>"), false);
					}
				}
			}
			else
			{
				ETGModConsole.Log((object)("[SI] <color=#FF5656>Warning: " + text + "</color>"), false);
			}
		}

		public static void ResetCount(string key = "")
		{
			counters[key] = 0;
		}

		public static void Count(string key = "")
		{
			Count(string.Empty, key);
		}

		public static void Count<T>(ICollection<T> values, string key = "", string color = "#FFFFFF")
		{
			Count(values, (T v) => ETGMod.ToStringSafe((object)v), key, color);
		}

		public static void Count<T>(ICollection<T> values, Func<T, string> func, string key = "", string color = "#FFFFFF")
		{
			foreach (T value in values)
			{
				Count(func(value), key, color);
			}
		}

		public static void Count<T>(IEnumerable<T> values, string color = "#FFFFFF")
		{
			Count(values, (T v) => ETGMod.ToStringSafe((object)v), color);
		}

		public static void Count<T>(IEnumerable<T> values, Func<T, string> func, string color = "#FFFFFF")
		{
			foreach (T value in values)
			{
				Count(func(value), color);
			}
		}

		public static void Count(object obj, string key = "", string color = "#FFFFFF")
		{
			Count(ETGMod.ToStringSafe(obj), key, color);
		}

		public static void Count(string text, string key = "", string color = "#FFFFFF")
		{
			int num = counters[key] + 1;
			if (Enumerable.Contains(text, '\n'))
			{
				string[] array = text.Split(SplitSeparators, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text2 in array)
				{
					if (!string.IsNullOrEmpty(text2))
					{
						ETGModConsole.Log((object)$"[SI] [{num}] <color={color}>{text2}</color>", false);
					}
				}
			}
			else
			{
				ETGModConsole.Log((object)$"[SI] [{num}] <color={color}>{text}</color>", false);
			}
			counters[key] = num;
		}

		public static void Log(Exception exception)
		{
			Warning(exception.Message);
			Warning(exception.StackTrace);
		}

		public static void Log(string prefix, Exception exception)
		{
			Warning(prefix + " " + exception.Message);
			Warning(exception.StackTrace);
		}
	}
	public static class Sandling
	{
		public const string ItemName = "Sandling";

		public const string ShortDescription = "Simply Sandling";

		public const string LongDescription = "A curious creature, that came from a realm of endless sands.\n\nHow is he ended-up here? Where is he going? What is he looking for?\n\nA mysterious destination that one can dare to find, remains secret until reached.";

		public const string InternalItemName = "sandling_compass_001";

		public const string InternalFullItemName = "sandling_compass_001.png";

		private static readonly int[] DefaultOdds = new int[5] { 10, 40, 100, 240, 480 };

		private static int currentOdds = 0;

		private static readonly List<AIActor> trackers = new List<AIActor>();

		public static void Register()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00b1: 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_00c3: 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_00e4: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0126: 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)
			PickupObject obj = Game.Items.Get("gungeon:dog");
			CompanionItem val = (CompanionItem)(object)((obj is CompanionItem) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				GunExt.SetName((PickupObject)(object)val, "Sandling");
				GunExt.SetShortDescription((PickupObject)(object)val, "Simply Sandling");
				GunExt.SetLongDescription((PickupObject)(object)val, "A curious creature, that came from a realm of endless sands.\n\nHow is he ended-up here? Where is he going? What is he looking for?\n\nA mysterious destination that one can dare to find, remains secret until reached.");
			}
			Texture2D textureFromResource = ResourceExtractor.GetTextureFromResource("SandlingInvasion/Resources/dog_item_001.png", (Assembly)null);
			tk2dSpriteDefinition currentSpriteDef = ((BraveBehaviour)val).sprite.GetCurrentSpriteDef();
			ETGMod.ReplaceTexture(currentSpriteDef, textureFromResource, true);
			currentSpriteDef.texelSize = new Vector2(17f, 17f);
			float num = 17f / 32f;
			currentSpriteDef.boundsDataCenter = new Vector3(num, num, 0f);
			currentSpriteDef.boundsDataExtents = new Vector3(num, num, 0f);
			currentSpriteDef.untrimmedBoundsDataCenter = new Vector3(num, num, 0f);
			currentSpriteDef.untrimmedBoundsDataExtents = new Vector3(num, num, 0f);
			float num2 = 1.0625f;
			currentSpriteDef.position0 = new Vector3(0f, 0f, 0f);
			currentSpriteDef.position1 = new Vector3(num2, 0f, 0f);
			currentSpriteDef.position2 = new Vector3(0f, num2, 0f);
			currentSpriteDef.position3 = new Vector3(num2, num2, 0f);
			SetupSpawn();
		}

		private static void SetupSpawn()
		{
			PickupObject sandling = Game.Items.Get("gungeon:dog");
			DungeonHooks.OnPostDungeonGeneration += delegate
			{
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Expected O, but got Unknown
				if (GameManager.Instance.InTutorial)
				{
					currentOdds = 0;
					Plugin.Log("No Sandlings in a tutorial! We need no tutorial!");
					return;
				}
				try
				{
					foreach (RoomHandler room2 in GameManager.Instance.Dungeon.data.rooms)
					{
						RoomHandler room = room2;
						RoomHandler obj = room;
						obj.OnEnemiesCleared = (Action)Delegate.Combine(obj.OnEnemiesCleared, (Action)delegate
						{
							currentOdds++;
						});
						room.Entered += (OnEnteredEventHandler)delegate
						{
							if (room.GetActiveEnemiesCount((ActiveEnemyType)0) != 0)
							{
								foreach (AIActor activeEnemy in room.GetActiveEnemies((ActiveEnemyType)0))
								{
									TrackEnemy(activeEnemy);
								}
							}
						};
						RoomHandler obj2 = room;
						obj2.OnEnemyRegistered = (Action<AIActor>)Delegate.Combine(obj2.OnEnemyRegistered, new Action<AIActor>(TrackEnemy));
						void TrackEnemy(AIActor enemy)
						{
							if ((Object)(object)enemy != (Object)null && (Object)(object)((BraveBehaviour)enemy).healthHaver != (Object)null)
							{
								trackers.Add(enemy);
								((BraveBehaviour)enemy).healthHaver.OnDeath += delegate
								{
									//IL_008a: Unknown result type (might be due to invalid IL or missing references)
									for (int num = trackers.Count - 1; num >= 0; num--)
									{
										if ((Object)(object)trackers[num] == (Object)null)
										{
											trackers.RemoveAt(num);
										}
									}
									if (trackers.Remove(enemy) && trackers.Count == 0)
									{
										TrySpawnItem(sandling, room, ((GameActor)enemy).CenterPosition);
									}
								};
							}
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Warning("Cannot attach sandling spawn events! Sandlings spawn on this level.");
					Plugin.Warning(ex.Message);
					Plugin.Warning(ex.StackTrace);
				}
			};
		}

		private static void TrySpawnItem(PickupObject sandling, RoomHandler room, Vector2 around)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			PlayerController[] allPlayers = GameManager.Instance.AllPlayers;
			foreach (PlayerController val in allPlayers)
			{
				num += val.passiveItems.Count((PassiveItem item) => ((PickupObject)item).itemName == sandling.itemName);
			}
			int spawnOdds = GetSpawnOdds(num);
			if (currentOdds >= Random.Range(0, spawnOdds))
			{
				CellArea area = room.area;
				Dungeon dungeon = GameManager.Instance.Dungeon;
				IntVector2 source = default(IntVector2);
				((IntVector2)(ref source))..ctor(Mathf.Clamp(Mathf.RoundToInt(around.x), area.basePosition.x, area.basePosition.x + area.dimensions.x - 1), Mathf.Clamp(Mathf.RoundToInt(around.y), area.basePosition.y, area.basePosition.y + area.dimensions.y - 1));
				if (Utils.TryFindClosest(source, (IntVector2 pos) => dungeon.data.CheckInBoundsAndValid(pos) && (int)dungeon.data[pos].type == 2, out var cell))
				{
					LootEngine.SpawnItem(((Component)sandling).gameObject, ((IntVector2)(ref cell)).ToVector3(), Vector2.up, 0f, true, false, false);
					currentOdds = 0;
				}
				else
				{
					currentOdds = spawnOdds;
				}
			}
			else
			{
				currentOdds++;
			}
		}

		private static int GetSpawnOdds(int stage)
		{
			int[] defaultOdds = DefaultOdds;
			if (stage < 0)
			{
				return defaultOdds[0];
			}
			if (stage < defaultOdds.Length)
			{
				return defaultOdds[stage];
			}
			if (defaultOdds.Length >= 2)
			{
				int num = defaultOdds[^1];
				int num2 = num - defaultOdds[^2];
				return num + num2 * (stage - defaultOdds.Length + 1);
			}
			return defaultOdds[^1] * (stage - defaultOdds.Length + 1);
		}
	}
	public static class Utils
	{
		private static IntVector2[] offsets;

		public static void Initialize()
		{
		}

		static Utils()
		{
			CreateOffsets();
		}

		public static T Find<T>(ICollection<T> collection, Predicate<T> predicate)
		{
			foreach (T item in collection)
			{
				if (predicate(item))
				{
					return item;
				}
			}
			return default(T);
		}

		public static bool TryFind<T>(ICollection<T> collection, Predicate<T> predicate, out T result)
		{
			foreach (T item in collection)
			{
				if (predicate(item))
				{
					result = item;
					return true;
				}
			}
			result = default(T);
			return false;
		}

		private static void CreateOffsets()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			offsets = (IntVector2[])(object)new IntVector2[49];
			int num = 0;
			for (int i = -3; i <= 3; i++)
			{
				for (int j = -3; j <= 3; j++)
				{
					offsets[num++] = new IntVector2(j, i);
				}
			}
			Array.Sort(offsets, delegate(IntVector2 a, IntVector2 b)
			{
				//IL_0001: 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_0019: 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)
				//IL_004a: 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_0057: 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_0067: 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_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				int num2 = Mathf.Abs(a.x) + Mathf.Abs(a.y);
				int num3 = Mathf.Abs(b.x) + Mathf.Abs(b.y);
				if (num2 != num3)
				{
					return num2.CompareTo(num3);
				}
				float num4 = a.x * a.x + a.y * a.y;
				float value = b.x * b.x + b.y * b.y;
				return num4.CompareTo(value);
			});
		}

		public static bool TryFindClosest(IntVector2 source, Func<IntVector2, bool> validator, out IntVector2 cell)
		{
			//IL_000b: 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_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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (validator == null)
			{
				cell = source;
				return false;
			}
			IntVector2 val2 = default(IntVector2);
			for (int i = 0; i < offsets.Length; i++)
			{
				IntVector2 val = offsets[i];
				int num = source.x + val.x;
				int num2 = source.y + val.y;
				((IntVector2)(ref val2))..ctor(num, num2);
				if (validator(val2))
				{
					cell = val2;
					return true;
				}
			}
			cell = source;
			return false;
		}
	}
}