Decompiled source of BigCG v1.0.0

plugins/Big CG/BigCG.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using Configgy;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BigCG")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+38bc30309c03e62ffb632e8cfea8fd8a886767cf")]
[assembly: AssemblyProduct("BigCG")]
[assembly: AssemblyTitle("BigCG")]
[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 BigCG
{
	public static class MeshBaking
	{
		public const int MaxCubesPerMesh = 150;

		public const int MaxStairsPerMesh = 150;

		private static void CreateCombinedObject(out GameObject gameObject, out MeshRenderer renderer, out MeshFilter filter)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			GameObject val = new GameObject("Combined Static Mesh (BigCG)");
			val.transform.parent = ((Component)MonoSingleton<EndlessGrid>.Instance).transform;
			val.layer = LayerMask.NameToLayer("Outdoors");
			gameObject = val;
			renderer = gameObject.AddComponent<MeshRenderer>();
			filter = gameObject.AddComponent<MeshFilter>();
		}

		private static void CompleteMesh(Mesh mesh, CombineInstance[] combineInstances)
		{
			mesh.CombineMeshes(combineInstances, true, true);
			mesh.Optimize();
			mesh.RecalculateBounds();
			mesh.RecalculateNormals();
			mesh.UploadMeshData(false);
		}

		public static GameObject CreateCubeMesh(int start, int amount)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0079: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			CreateCombinedObject(out var gameObject, out var renderer, out var filter);
			List<CombineInstance> list = new List<CombineInstance>();
			Material[] sharedMaterials = ((Renderer)MonoSingleton<EndlessGrid>.Instance.cubes[0][0].MeshRenderer).sharedMaterials;
			for (int i = 0; i < sharedMaterials.Length; i++)
			{
				for (int j = 0; j < amount; j++)
				{
					int num = (j + start) / Plugin.GridSize;
					EndlessCube val = MonoSingleton<EndlessGrid>.Instance.cubes[num][j + start - num * Plugin.GridSize];
					if (Object.op_Implicit((Object)(object)val))
					{
						CombineInstance item = default(CombineInstance);
						((CombineInstance)(ref item)).transform = ((Renderer)val.MeshRenderer).localToWorldMatrix;
						((CombineInstance)(ref item)).mesh = val.MeshFilter.sharedMesh;
						((CombineInstance)(ref item)).subMeshIndex = i;
						list.Add(item);
						((Renderer)val.MeshRenderer).enabled = false;
					}
				}
			}
			Mesh val2 = new Mesh();
			CompleteMesh(val2, list.ToArray());
			filter.sharedMesh = val2;
			((Renderer)renderer).sharedMaterials = sharedMaterials;
			((Renderer)renderer).enabled = true;
			return gameObject;
		}

		public static GameObject CreateStairsMesh(int start, int amount)
		{
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_00b0: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			CreateCombinedObject(out var gameObject, out var renderer, out var filter);
			List<CombineInstance> list = new List<CombineInstance>();
			Material[] sharedMaterials = ((Renderer)MonoSingleton<EndlessGrid>.Instance.cubes[0][0].MeshRenderer).sharedMaterials;
			int num = 0;
			foreach (GameObject item2 in MonoSingleton<EndlessGrid>.Instance.spawnedPrefabs.Where((GameObject x) => (Object)(object)x.GetComponent<EndlessStairs>() != (Object)null))
			{
				if (num <= start + amount && num >= start)
				{
					num++;
					EndlessStairs component = item2.GetComponent<EndlessStairs>();
					CombineInstance item;
					if (component.ActivateFirst)
					{
						item = default(CombineInstance);
						((CombineInstance)(ref item)).transform = ((Renderer)component.PrimaryMeshRenderer).localToWorldMatrix;
						((CombineInstance)(ref item)).mesh = component.PrimaryMeshFilter.sharedMesh;
						list.Add(item);
						((Renderer)component.PrimaryMeshRenderer).enabled = false;
					}
					if (component.ActivateSecond)
					{
						item = default(CombineInstance);
						((CombineInstance)(ref item)).transform = ((Renderer)component.SecondaryMeshRenderer).localToWorldMatrix;
						((CombineInstance)(ref item)).mesh = component.SecondaryMeshFilter.sharedMesh;
						list.Add(item);
						((Renderer)component.SecondaryMeshRenderer).enabled = false;
					}
				}
			}
			Mesh val = new Mesh();
			CompleteMesh(val, list.ToArray());
			filter.sharedMesh = val;
			((Renderer)renderer).sharedMaterials = sharedMaterials;
			((Renderer)renderer).enabled = true;
			return gameObject;
		}
	}
	public static class PatternFixer
	{
		public static void FixPattern(ArenaPattern pattern)
		{
			if ((Object)(object)pattern == (Object)null)
			{
				Debug.LogWarning((object)"Pattern is null,,, guh?");
				return;
			}
			pattern.heights = string.Join("\n", FixPatternHeights(pattern.heights.Split(new char[1] { '\n' }).ToList()));
			pattern.prefabs = string.Join("\n", FixPatternEnemies(pattern.prefabs.Split(new char[1] { '\n' }).ToList()));
		}

		public static string[] FixStringPattern(string[] pattern)
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			List<string> list4 = list2;
			foreach (string text in pattern)
			{
				if (text == string.Empty)
				{
					list4 = list3;
				}
				else
				{
					list4.Add(text);
				}
			}
			list.AddRange(FixPatternHeights(list2));
			list.Add(string.Empty);
			list.AddRange(FixPatternEnemies(list3));
			return list.ToArray();
		}

		private static List<string> FixPatternHeights(List<string> pattern)
		{
			List<List<int>> list = ParseStringArray(pattern);
			foreach (List<int> item in list)
			{
				if (item.Count < Plugin.GridSize)
				{
					int num = 0;
					while (item.Count != Plugin.GridSize)
					{
						item.Add(item[num]);
						num++;
					}
				}
				else if (item.Count > Plugin.GridSize)
				{
					int num2 = item.Count - Plugin.GridSize;
					item.RemoveRange(item.Count - num2 - 1, num2);
				}
			}
			if (list.Count < Plugin.GridSize)
			{
				int num3 = 0;
				while (list.Count != Plugin.GridSize)
				{
					list.Add(list[num3]);
					num3++;
				}
			}
			else if (list.Count > Plugin.GridSize)
			{
				int num4 = list.Count - Plugin.GridSize;
				list.RemoveRange(list.Count - num4, num4);
			}
			return ListIntPatternToStringListPattern(list);
		}

		private static List<string> FixPatternEnemies(List<string> pattern)
		{
			List<string> list = new List<string>();
			foreach (string item in pattern)
			{
				string text = item;
				if (text.Length < Plugin.GridSize)
				{
					int num = 0;
					while (text.Length != Plugin.GridSize)
					{
						text += text[num];
						num++;
					}
				}
				else if (item.Length > Plugin.GridSize)
				{
					text = text.Substring(0, Plugin.GridSize);
				}
				list.Add(text);
			}
			if (list.Count < Plugin.GridSize)
			{
				int num2 = 0;
				while (list.Count != Plugin.GridSize)
				{
					list.Add(list[num2]);
					num2++;
				}
			}
			else if (list.Count > Plugin.GridSize)
			{
				int num3 = list.Count - Plugin.GridSize;
				list.RemoveRange(list.Count - num3 - 1, num3);
			}
			return list;
		}

		private static List<List<int>> ParseStringArray(List<string> pattern)
		{
			List<List<int>> list = new List<List<int>>();
			foreach (string item in pattern)
			{
				if (!CorrectlyClosedBrackets(item))
				{
					Debug.LogError((object)"Brackets don't close in pattern.");
					return null;
				}
				if (!MinusesInValidPositions(item))
				{
					Debug.LogError((object)"Minuses are invalid in pattern.");
					return null;
				}
				List<int> list2 = new List<int>();
				list.Add(list2);
				bool flag = false;
				bool flag2 = false;
				bool flag3 = false;
				string text = item;
				for (int i = 0; i < text.Length; i++)
				{
					char c = text[i];
					if ((c == '(' || c == ')') ? true : false)
					{
						flag2 = false;
						flag = !flag;
						continue;
					}
					if (!flag)
					{
						list2.Add(int.Parse(c.ToString()));
						continue;
					}
					if (!flag2)
					{
						if (c == '-')
						{
							flag3 = true;
							continue;
						}
						list2.Add(int.Parse(c.ToString()) * ((!flag3) ? 1 : (-1)));
						flag2 = true;
						continue;
					}
					list2[list2.Count - 1] = int.Parse(string.Concat(list2[list2.Count - 1], c));
					if (flag3)
					{
						list2[list2.Count - 1] *= -1;
						flag3 = false;
					}
				}
			}
			Debug.Log((object)"SEPERATOR ---");
			foreach (List<int> item2 in list)
			{
				Debug.Log((object)string.Join(" ", item2));
			}
			return list;
		}

		private static List<string> ListIntPatternToStringListPattern(List<List<int>> pattern)
		{
			List<string> list = new List<string>();
			foreach (List<int> item in pattern)
			{
				string text = string.Empty;
				foreach (int item2 in item)
				{
					text = ((item2.ToString().Length != 1) ? (text + $"({item2})") : (text + item2));
				}
				list.Add(text);
			}
			return list;
		}

		private static bool CorrectlyClosedBrackets(string line)
		{
			return Regex.Matches(line, "\\(").Count == Regex.Matches(line, "\\)").Count;
		}

		private static bool MinusesInValidPositions(string line)
		{
			for (int i = 0; i < line.Length; i++)
			{
				if (line[i] == '-' && !char.IsDigit(line[i + 1]) && line[i - 1] != '(')
				{
					return false;
				}
			}
			return true;
		}
	}
	[BepInPlugin("waffle.ultrakill.bigcg", "Big Cybergrind", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "waffle.ultrakill.bigcg";

		public const string Name = "Big Cybergrind";

		public const string Version = "1.0.0";

		[Configgable("", "Enable Big CG", 0, "Enable features of the mod.\nDisable this to reenable score submission.")]
		public static ConfigToggle ModEnabled = new ConfigToggle(true);

		[Configgable("", "Grid Length", 0, "Length of the grid - default is 16.\nThis starts lagging really bad at high values.")]
		public static int GridSize = 32;

		[Configgable("", "Budget Multiplier", 1, "Increase the budget allocated to enemy spawns to offset the size of the map.")]
		public static int Multiplier = 2;

		[Configgable("Optimisations", "Optimised Cube Model", 2, "Replaces the grid cube model with one that has 1/5th of the tris.\nLooks worse when using texture or vertex warping.")]
		public static bool OptimizedModel = true;

		[Configgable("Optimisations", "Optimised Stair Model", 3, "Replaces the stairs with a ramp that has 1/10th of the tris.\nLooks worse generally and when using texture or vertex warping.")]
		public static bool OptimizedStairs = false;

		[Configgable("Optimisations", "Fast Animation", 4, "Animations between waves are buggy, but lag less.\nGood for performance, but not recommended.")]
		public static bool FastAnim = false;

		private static Harmony s_harmony = new Harmony("waffle.ultrakill.bigcg");

		private static FieldInfo s_gridSize = AccessTools.Field(typeof(Plugin), "GridSize");

		private static MethodInfo s_mainGridSize = AccessTools.Method(typeof(Plugin), "get_MainGridSize", (Type[])null, (Type[])null);

		private static MethodInfo s_getFiles = AccessTools.Method(typeof(Directory), "GetFiles", new Type[3]
		{
			typeof(string),
			typeof(string),
			typeof(SearchOption)
		}, (Type[])null);

		private static MethodInfo s_getFilesReplacement = AccessTools.Method(typeof(Plugin), "GetFilesReplacement", (Type[])null, (Type[])null);

		private static MethodInfo s_fixStringPattern = AccessTools.Method(typeof(PatternFixer), "FixStringPattern", (Type[])null, (Type[])null);

		private static MethodInfo s_readAllLines = AccessTools.Method(typeof(File), "ReadAllLines", new Type[1] { typeof(string) }, (Type[])null);

		private static string[] s_extensions = new string[2] { ".cgp", ".cgpe" };

		private static List<GameObject> s_mergedMeshes = new List<GameObject>();

		private static AssetBundle s_modBundle;

		private static Mesh s_optimizedCube;

		private static Mesh s_optimizedStairs;

		public static int MainGridSize => (GridSize >= 16) ? 16 : GridSize;

		private void Start()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			string path = Assembly.GetExecutingAssembly().Location.Substring(0, Assembly.GetExecutingAssembly().Location.LastIndexOf(Path.DirectorySeparatorChar));
			s_modBundle = AssetBundle.LoadFromFile(Path.Combine(path, "bigcgassets.bundle"));
			s_optimizedCube = s_modBundle.LoadAsset<Mesh>("optimizedgridcube.dae");
			s_optimizedStairs = s_modBundle.LoadAsset<Mesh>("optimizedstairs.dae");
			ConfigBuilder val = new ConfigBuilder("waffle.ultrakill.bigcg", "Big Cybergrind");
			val.Build();
			((ConfigValueElement<bool>)(object)ModEnabled).OnValueChanged = delegate(bool value)
			{
				if (value)
				{
					s_harmony.PatchAll(typeof(Plugin));
				}
				else
				{
					s_harmony.UnpatchSelf();
				}
			};
		}

		[HarmonyPatch(typeof(LeaderboardController), "SubmitCyberGrindScore")]
		[HarmonyPatch(typeof(LeaderboardController), "SubmitLevelScore")]
		[HarmonyPrefix]
		private static bool DisableCg()
		{
			Debug.Log((object)"BCG patches enabled, disable CG ‼\ufe0f");
			return false;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(CustomPatterns), "GeneratePatternPreview")]
		[HarmonyPatch(typeof(EndlessGrid), "LoadPattern")]
		[HarmonyPatch(typeof(EndlessGrid), "MakeGridDynamic")]
		[HarmonyPatch(typeof(EndlessGrid), "OneDone")]
		[HarmonyPatch(typeof(EndlessGrid), "Start")]
		private static IEnumerable<CodeInstruction> ReplaceGridSize(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_S && (sbyte)instruction.operand == 16)
				{
					instruction.opcode = OpCodes.Ldsfld;
					instruction.operand = s_gridSize;
				}
				yield return instruction;
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "SetupStaticGridMesh")]
		private static IEnumerable<CodeInstruction> ReplaceMainGridSize(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_S && (sbyte)instruction.operand == 16)
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = s_mainGridSize;
				}
				yield return instruction;
			}
		}

		[HarmonyPatch(typeof(CustomPatterns), "BuildButtons")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> FixButtonSize(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_R4 && CodeInstructionExtensions.OperandIs(instruction, (object)48f))
				{
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)s_gridSize);
					yield return new CodeInstruction(OpCodes.Ldc_I4_3, (object)null);
					yield return new CodeInstruction(OpCodes.Mul, (object)null);
					yield return new CodeInstruction(OpCodes.Conv_R4, (object)null);
				}
				else if (instruction.opcode == OpCodes.Ldc_I4_S && CodeInstructionExtensions.OperandIs(instruction, (object)48))
				{
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)s_gridSize);
					yield return new CodeInstruction(OpCodes.Ldc_I4_3, (object)null);
					yield return new CodeInstruction(OpCodes.Mul, (object)null);
				}
				else
				{
					yield return instruction;
				}
			}
		}

		[HarmonyPatch(typeof(CustomPatterns), "LoadPattern")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> CustomPatternsLoadPattern(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_I4_S)
				{
					switch ((sbyte)instruction.operand)
					{
					case 15:
						instruction.opcode = OpCodes.Ldsfld;
						instruction.operand = s_gridSize;
						yield return instruction;
						yield return new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
						yield return new CodeInstruction(OpCodes.Sub, (object)null);
						continue;
					case 16:
						instruction.opcode = OpCodes.Ldsfld;
						instruction.operand = s_gridSize;
						yield return instruction;
						continue;
					case 17:
						instruction.opcode = OpCodes.Ldsfld;
						instruction.operand = s_gridSize;
						yield return instruction;
						yield return new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
						yield return new CodeInstruction(OpCodes.Add, (object)null);
						continue;
					case 32:
						instruction.opcode = OpCodes.Ldsfld;
						instruction.operand = s_gridSize;
						yield return instruction;
						yield return new CodeInstruction(OpCodes.Ldc_I4_2, (object)null);
						yield return new CodeInstruction(OpCodes.Mul, (object)null);
						continue;
					case 33:
						instruction.opcode = OpCodes.Ldsfld;
						instruction.operand = s_gridSize;
						yield return instruction;
						yield return new CodeInstruction(OpCodes.Ldc_I4_2, (object)null);
						yield return new CodeInstruction(OpCodes.Mul, (object)null);
						yield return new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
						yield return new CodeInstruction(OpCodes.Add, (object)null);
						continue;
					}
				}
				yield return instruction;
				if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)s_readAllLines))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)s_fixStringPattern);
				}
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "LoadPattern")]
		[HarmonyPrefix]
		private static void FixPatterns(EndlessGrid __instance, ArenaPattern pattern)
		{
			PatternFixer.FixPattern(pattern);
		}

		[HarmonyPatch(typeof(EndlessGrid), "NextWave")]
		[HarmonyPostfix]
		private static void DestroyBakedMeshes()
		{
			s_mergedMeshes.RemoveAll((GameObject x) => (Object)(object)x == (Object)null);
			foreach (GameObject s_mergedMesh in s_mergedMeshes)
			{
				Object.Destroy((Object)(object)s_mergedMesh);
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "SetupStaticGridMesh")]
		[HarmonyPostfix]
		private static void DoOtherBakes()
		{
			int num = GridSize * GridSize;
			int num3;
			for (int i = MainGridSize * MainGridSize; i != num; i += num3)
			{
				int num2 = num - i;
				num3 = ((150 > num2) ? num2 : 150);
				s_mergedMeshes.Add(MeshBaking.CreateCubeMesh(i - 1, num3));
			}
			int num4 = MonoSingleton<EndlessGrid>.Instance.spawnedPrefabs.Count((GameObject x) => (Object)(object)x.GetComponent<EndlessStairs>() != (Object)null);
			int num6;
			for (int j = 0; j != num4; j += num6)
			{
				int num5 = num4 - j;
				num6 = ((150 > num5) ? num5 : 150);
				s_mergedMeshes.Add(MeshBaking.CreateStairsMesh(j - 1, num6));
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "SetupStaticGridMesh")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PreventStairCreation(IEnumerable<CodeInstruction> instructions)
		{
			CodeInstruction[] ciArray = instructions.ToArray();
			for (int i = 0; i < ciArray.Length; i++)
			{
				if (i < 2)
				{
					yield return ciArray[i];
					continue;
				}
				if (ciArray[i - 2].opcode == OpCodes.Ldloc_S && ciArray[i - 1].opcode == OpCodes.Ldc_I4_1 && ciArray[i].opcode == OpCodes.Bne_Un)
				{
					yield return new CodeInstruction(OpCodes.Pop, (object)null);
					yield return new CodeInstruction(OpCodes.Ldc_I4, (object)100);
				}
				yield return ciArray[i];
			}
		}

		[HarmonyPatch(typeof(EndlessCube), "Update")]
		[HarmonyPostfix]
		private static void FixSlowMoveCube(EndlessCube __instance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (FastAnim && __instance.active)
			{
				__instance.tf.position = __instance.targetPos;
			}
		}

		[HarmonyPatch(typeof(EndlessStairs), "Update")]
		[HarmonyPostfix]
		private static void FixSlowMoveStairs(EndlessStairs __instance)
		{
			//IL_0032: 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)
			if (FastAnim && __instance.moving)
			{
				if (__instance.activateFirst)
				{
					__instance.primaryStairs.position = ((Component)__instance).transform.position;
				}
				if (__instance.activateSecond)
				{
					__instance.secondaryStairs.position = ((Component)__instance).transform.position;
				}
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "GetEnemies")]
		[HarmonyPrefix]
		private static void MultiplyPoints(EndlessGrid __instance)
		{
			__instance.maxPoints *= Multiplier;
			Debug.Log((object)("Multiplying points to " + __instance.maxPoints));
		}

		[HarmonyPatch(typeof(EndlessGrid), "GetNextEnemy")]
		[HarmonyPrefix]
		private static void CheckIfWasLastEnemy(EndlessGrid __instance, ref bool __state)
		{
			__state = __instance.enemyAmount == __instance.tempEnemyAmount;
		}

		[HarmonyPatch(typeof(EndlessGrid), "GetNextEnemy")]
		[HarmonyPostfix]
		private static void DividePoints(EndlessGrid __instance, ref bool __state)
		{
			if (!__state && __instance.enemyAmount == __instance.tempEnemyAmount)
			{
				__instance.maxPoints /= Multiplier;
				Debug.Log((object)("Dividing points to " + __instance.maxPoints));
			}
		}

		[HarmonyPatch(typeof(EndlessCube), "Awake")]
		[HarmonyPostfix]
		private static void ReplaceCubeModel(EndlessCube __instance)
		{
			if (OptimizedModel)
			{
				__instance.MeshFilter.mesh = s_optimizedCube;
			}
		}

		[HarmonyPatch(typeof(EndlessStairs), "Start")]
		[HarmonyPostfix]
		private static void ReplaceStairModel(EndlessStairs __instance)
		{
			if (OptimizedStairs)
			{
				__instance.PrimaryMeshFilter.mesh = s_optimizedStairs;
				__instance.SecondaryMeshFilter.mesh = s_optimizedStairs;
			}
		}

		[HarmonyPatch(typeof(CustomPatterns), "BuildButtons")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> AddCgpeFiles(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)s_getFiles))
				{
					instruction.operand = s_getFilesReplacement;
				}
				yield return instruction;
			}
		}

		[HarmonyPatch(typeof(CustomPatterns), "OpenEditor")]
		[HarmonyPrefix]
		private static bool OpenCustomEditor()
		{
			Application.OpenURL("https://wafflethings.github.io/CGPEditor/");
			return false;
		}

		private static string[] GetFilesReplacement(string path, string filter, SearchOption option)
		{
			return (from f in new DirectoryInfo(path).EnumerateFiles()
				where s_extensions.Contains(f.Extension.ToLower())
				select f.ToString()).ToArray();
		}
	}
}