Decompiled source of CustomGamemodes v0.2.0

plugins/monksilly.CustomGamemodes.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using CustomGameModes;
using CustomGameModes.Config;
using CustomGameModes.Controllers;
using CustomGameModes.Factories;
using CustomGameModes.Patches;
using CustomGameModes.UI;
using HarmonyLib;
using Imui.Controls;
using Imui.Core;
using Imui.Rendering;
using Microsoft.CodeAnalysis;
using MonoMod.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WKLib.API;
using WKLib.API.Assets;
using WKLib.API.Input;
using WKLib.API.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("monksilly.CustomGamemodes")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+5a044d12c13908e99abe6844b5aa4f50b969496f")]
[assembly: AssemblyProduct("Custom Gamemodes")]
[assembly: AssemblyTitle("monksilly.CustomGamemodes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.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;
		}
	}
}
public class MainWindow : WKLibWindow
{
	public bool TestBool = false;

	public float TestValue = 20f;

	public KeyBind TestKeybind = new KeyBind((KeyCode)112);

	public MainWindow()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		base.isOpen = false;
	}

	public override void Draw(ImGui gui, bool isRootPanelOpen)
	{
		//IL_0024: 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_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		if (isRootPanelOpen && ImWindow.BeginWindow(gui, "Custom Gamemodes Information", ref base.isOpen, new ImSize(400f, 400f), (ImWindowFlag)0))
		{
			ImSeparator.Separator(gui, "Basic Info".AsSpan());
			ImText.Text(gui, "Hewwwo :3".AsSpan(), false, (ImTextOverflow)0);
			if (ImCheckbox.Checkbox(gui, ref TestBool, "mrrow? ".AsSpan(), default(ImSize)))
			{
				Debug.Log((object)"Changed bool!!");
			}
			if (TestBool)
			{
				ref float testValue = ref TestValue;
				ReadOnlySpan<char> readOnlySpan = "0.0".AsSpan();
				ImNumericEdit.NumericEdit(gui, ref testValue, default(ImSize), readOnlySpan, 0.1f, 0f, float.MaxValue, (ImNumericEditFlag)2);
			}
			UIUtility.SimpleKeybind(gui, "Reload Gamemodes", ref TestKeybind);
			ImWindow.EndWindow(gui);
		}
	}

	public override void HandleInput(ImGui gui)
	{
		if (InputUtility.GetKeyDown((KeyCode)306))
		{
			LogManager.Info("Left control is pressed!");
		}
	}
}
namespace CustomGameModes
{
	[RequireComponent(typeof(Image))]
	public class DynamicSpriteSwitcher : MonoBehaviour
	{
		public enum DisplayMode
		{
			Random,
			Slideshow
		}

		[CompilerGenerated]
		private sealed class <FadeAlpha>d__15 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float from;

			public float to;

			public DynamicSpriteSwitcher <>4__this;

			private float <elapsed>5__1;

			private Color <c>5__2;

			private float <t>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FadeAlpha>d__15(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003a: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0167: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<elapsed>5__1 = 0f;
					<c>5__2 = ((Graphic)<>4__this._image).color;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__1 < <>4__this.fadeDuration)
				{
					<elapsed>5__1 += Time.deltaTime;
					<t>5__3 = Mathf.Clamp01(<elapsed>5__1 / <>4__this.fadeDuration);
					<c>5__2.r = Mathf.Lerp(from, to, <t>5__3);
					<c>5__2.g = Mathf.Lerp(from, to, <t>5__3);
					<c>5__2.b = Mathf.Lerp(from, to, <t>5__3);
					((Graphic)<>4__this._image).color = <c>5__2;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				<c>5__2.r = to;
				<c>5__2.g = to;
				<c>5__2.b = to;
				((Graphic)<>4__this._image).color = <c>5__2;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SlideshowLoop>d__14 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DynamicSpriteSwitcher <>4__this;

			private int <index>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SlideshowLoop>d__14(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!<>4__this._coroRunning)
					{
						<>4__this._coroRunning = true;
					}
					<index>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					<>4__this._image.sprite = <>4__this.sprites[<index>5__1];
					<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeAlpha(0.2f, 1f));
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(<>4__this.displayDuration);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<index>5__1 = (<index>5__1 + 1) % <>4__this.sprites.Count;
					break;
				}
				<>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.FadeAlpha(1f, 0.2f));
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public List<Sprite> sprites;

		public DisplayMode mode = DisplayMode.Random;

		public float displayDuration = 10f;

		public float fadeDuration = 1.5f;

		private Image _image;

		private Coroutine _cycleCoroutine;

		private string _key;

		private bool _coroRunning;

		public void Initialize()
		{
			_image = ((Component)this).GetComponent<Image>();
			if (sprites == null || sprites.Count < 1)
			{
				LogManager.Debug("[DynamicSpriteSwitcher] No sprites assigned");
				((Behaviour)this).enabled = false;
			}
			else
			{
				_key = ((Object)((Component)this).gameObject.transform.parent).name + ":" + ((Object)((Component)this).gameObject).name;
				Enable();
			}
		}

		private void Enable()
		{
			if (sprites.Count < 2)
			{
				_image.sprite = sprites[0];
				return;
			}
			_image.sprite = sprites[1];
			switch (mode)
			{
			case DisplayMode.Random:
				ShowRandomSprite();
				break;
			case DisplayMode.Slideshow:
				_cycleCoroutine = ((MonoBehaviour)this).StartCoroutine(SlideshowLoop());
				break;
			}
		}

		private void OnDisable()
		{
			if (_cycleCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_cycleCoroutine);
				_cycleCoroutine = null;
			}
		}

		private async void Update()
		{
			if (((Component)this).gameObject.activeSelf && _cycleCoroutine == null)
			{
				try
				{
					Initialize();
				}
				catch
				{
				}
				await Task.Delay(5000);
			}
		}

		private void ShowRandomSprite()
		{
			GameModeController instance = GameModeController.Instance;
			if (instance == null)
			{
				LogManager.Error("[DynamicSpriteSwitcher] GameModeController.Instance is null");
				return;
			}
			if (instance.LastChosenSpriteIndices.ContainsKey(_key))
			{
				instance.LastChosenSpriteIndices[_key] = -1;
			}
			int num = instance.LastChosenSpriteIndices[_key];
			int num2 = Random.Range(0, sprites.Count);
			if (sprites.Count > 1)
			{
				int num3 = 0;
				while (num2 == num && num3 < 5)
				{
					num2 = Random.Range(0, sprites.Count);
					num3++;
				}
			}
			_image.sprite = sprites[num2];
			instance.LastChosenSpriteIndices[_key] = num2;
		}

		[IteratorStateMachine(typeof(<SlideshowLoop>d__14))]
		private IEnumerator SlideshowLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SlideshowLoop>d__14(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<FadeAlpha>d__15))]
		private IEnumerator FadeAlpha(float from, float to)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FadeAlpha>d__15(0)
			{
				<>4__this = this,
				from = from,
				to = to
			};
		}
	}
	public static class LogManager
	{
		private static ManualLogSource _logSource;

		public static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		public static void Info(object msg)
		{
			_logSource.LogInfo(msg);
		}

		public static void Warn(object msg)
		{
			_logSource.LogWarning(msg);
		}

		public static void Error(object msg)
		{
			_logSource.LogError(msg);
		}

		public static void Debug(object msg)
		{
			_logSource.LogDebug(msg);
		}
	}
	[BepInIncompatibility("com.validaq.loadintolevel")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.monksilly.CustomGamemodes", "CustomGamemodes", "0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.monksilly.CustomGamemodes";

		public const string NAME = "CustomGamemodes";

		public const string VERSION = "0.2.0";

		public static Plugin Instance;

		public static WKLibAPI LibAPI = WKLibAPI.Create("CustomGamemodes", "com.monksilly.CustomGamemodes", "CustomGamemodes");

		public GameObject stuffHolder;

		private bool _isObjectInitialized;

		private bool _isGameModeManagerInitialized;

		private bool _isCustomItemsInitialized;

		private void Awake()
		{
			Instance = this;
			LibAPI.AddToModList((ModTab)(object)new ModListTab());
			LibAPI.AddWindow((WKLibWindow)(object)WindowDeclarations.MainWin);
			LogManager.Init(((BaseUnityPlugin)this).Logger);
			LogManager.Info("Plugin monksilly.CustomGamemodes v0.2.0 is loaded!");
			SceneManager.sceneLoaded += OnSceneLoaded;
			Harmony.CreateAndPatchAll(typeof(ModPatches), (string)null);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			SetupMainObject();
			string name = ((Scene)(ref scene)).name;
			string text = name;
			if (!(text == "Game-Main"))
			{
				if (text == "Intro")
				{
					SetupGameModeController();
				}
			}
			else
			{
				SetupCustomItemHolder();
			}
		}

		private void SetupMainObject()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			if (!_isObjectInitialized)
			{
				_isObjectInitialized = true;
				stuffHolder = new GameObject("CustomGamemodesManager");
				Object.DontDestroyOnLoad((Object)(object)stuffHolder);
			}
		}

		private void SetupCustomItemHolder()
		{
			if (!_isCustomItemsInitialized)
			{
				_isCustomItemsInitialized = true;
				stuffHolder.AddComponent<SpawnController>();
			}
		}

		private void SetupGameModeController()
		{
			if (!_isGameModeManagerInitialized)
			{
				_isGameModeManagerInitialized = true;
				stuffHolder.AddComponent<GameModeController>();
				stuffHolder.AddComponent<TextLoading>();
			}
		}

		private void OnDestroy()
		{
			LibAPI.Destroy();
		}
	}
	public class SpawnController : MonoBehaviour
	{
	}
	public class TextLoading : MonoBehaviour
	{
		public static GameObject LoadingInstance;

		private void Awake()
		{
			//IL_0059: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)LoadingInstance))
			{
				GameObject val = GameObject.Find("Canvas/Loading");
				if (Object.op_Implicit((Object)(object)val))
				{
					LoadingInstance = Object.Instantiate<GameObject>(val);
					((Object)LoadingInstance).name = "LoadingPrefab";
					LoadingInstance.SetActive(false);
					Image component = LoadingInstance.GetComponent<Image>();
					((Graphic)component).color = ((Graphic)component).color + new Color(0f, 0f, 0f, 0.4f);
					Object.DontDestroyOnLoad((Object)(object)LoadingInstance);
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "monksilly.CustomGamemodes";

		public const string PLUGIN_NAME = "Custom Gamemodes";

		public const string PLUGIN_VERSION = "0.2.0";
	}
}
namespace CustomGameModes.UI
{
	public class ModListTab : ModTab
	{
		public override string DisplayName => "Custom Gamemodes";

		public override void DrawSubMenu(ImGui gui)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (ImButton.Button(gui, "Main Info".AsSpan(), default(ImSize), (ImButtonFlag)0))
			{
				((WKLibWindow)WindowDeclarations.MainWin).isOpen = !((WKLibWindow)WindowDeclarations.MainWin).isOpen;
			}
		}
	}
	public static class WindowDeclarations
	{
		public static MainWindow MainWin = new MainWindow();
	}
}
namespace CustomGameModes.Patches
{
	internal class ModPatches
	{
		[HarmonyPatch(typeof(CL_AssetManager), "UnloadAllLevels")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		private static bool BlockAddressableUnload()
		{
			return false;
		}
	}
}
namespace CustomGameModes.Factories
{
	public class CapsuleFactory
	{
		private class Builder
		{
			private class GiveMeMyUnlocksPls : MonoBehaviour
			{
				private UI_CapsuleButton capsuleButton;

				public string author;

				private void Awake()
				{
					capsuleButton = ((Component)this).GetComponent<UI_CapsuleButton>();
					ForceUnlock();
				}

				private void Update()
				{
					ForceUnlock();
				}

				private void OnEnable()
				{
					ForceUnlock();
					if (!string.IsNullOrEmpty(author))
					{
						Transform val = ((Component)this).transform.Find("Author Name Holder");
						Transform val2 = ((val != null) ? val.Find("Author Name") : null);
						if (val2 != null)
						{
							((TMP_Text)((Component)val2).gameObject.GetComponent<TextMeshProUGUI>()).text = author;
						}
					}
				}

				private void OnDisable()
				{
					ForceUnlock();
				}

				private void ForceUnlock()
				{
					if (capsuleButton != null && string.IsNullOrEmpty(capsuleButton.unlockAchievement))
					{
						capsuleButton.unlockAchievement = "ACH_TUTORIAL";
					}
				}
			}

			private readonly M_Gamemode _gameMode;

			private string _category = "default";

			private List<Sprite> _sprites;

			private string _author;

			private Transform _contentTransform;

			private Transform _template;

			private Transform _categoryHolder;

			private Transform _newCapsule;

			public Builder(M_Gamemode gameMode)
			{
				_gameMode = gameMode;
			}

			public Builder WithCategory(string category)
			{
				_category = category;
				return this;
			}

			public Builder WithSprites(List<Sprite> sprites)
			{
				_sprites = sprites;
				return this;
			}

			public Builder WithAuthor(string author)
			{
				_author = author;
				return this;
			}

			public void Build()
			{
				if (ValidateInputs())
				{
					LocateContentAndTemplate();
					PrepareCategoryHolder();
					InstantiateCapsule();
					ConfigureSprites();
					UpdateTextAndName();
					AttachUIComponents();
					ConfigureRoachCounter();
					ConfigureAuthor();
					RebuildLayouts();
				}
			}

			private bool ValidateInputs()
			{
				if (GameModeController.Instance.currentScene != "Main-Menu")
				{
					return false;
				}
				if (_gameMode != null)
				{
					return true;
				}
				LogManager.Error("[CapsuleFactory] gameMode is null; cannot create capsule.");
				return false;
			}

			private void LocateContentAndTemplate()
			{
				GameObject obj = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Custom/Viewport/Content");
				_contentTransform = ((obj != null) ? obj.transform : null);
				if (_contentTransform == null)
				{
					LogManager.Error("[CapsuleFactory] Content transform not found.");
					return;
				}
				GameObject obj2 = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Endless Variant/Viewport/Content");
				Transform val = ((obj2 != null) ? obj2.transform : null);
				_template = ((val != null) ? val.Find("Mode Selection Button - Endless") : null);
				if (_template == null)
				{
					LogManager.Error("[CapsuleFactory] Template not found.");
				}
			}

			private void PrepareCategoryHolder()
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				Transform contentTransform = _contentTransform;
				if (_category != "default")
				{
					_categoryHolder = contentTransform.Find(_category + " Holder");
					if (_categoryHolder == null)
					{
						_categoryHolder = CreateCategoryHolder(_category).transform;
						_categoryHolder.SetParent(contentTransform);
						_categoryHolder.localScale = Vector3.one;
					}
				}
				else
				{
					_categoryHolder = contentTransform;
				}
			}

			private void InstantiateCapsule()
			{
				_newCapsule = Object.Instantiate<Transform>(_template, _categoryHolder);
				Object.Destroy((Object)(object)((Component)_newCapsule).gameObject.GetComponent<UI_Gamemode_Button>());
				Object.Destroy((Object)(object)((Component)_newCapsule).gameObject.GetComponent<UI_CapsuleButton>());
				((Component)_newCapsule).gameObject.SetActive(true);
			}

			private void ConfigureSprites()
			{
				if (_sprites != null)
				{
					DynamicSpriteSwitcher dynamicSpriteSwitcher = ((Component)_newCapsule).gameObject.AddComponent<DynamicSpriteSwitcher>();
					dynamicSpriteSwitcher.sprites = _sprites;
					dynamicSpriteSwitcher.mode = DynamicSpriteSwitcher.DisplayMode.Slideshow;
					dynamicSpriteSwitcher.Initialize();
				}
			}

			private void UpdateTextAndName()
			{
				((Object)_newCapsule).name = "Mode Selection Button - " + _gameMode.gamemodeName;
				Transform obj = _newCapsule.Find("Mode Name");
				TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
				if (val != null)
				{
					val.text = _gameMode.gamemodeName;
				}
			}

			private void AttachUIComponents()
			{
				UI_CapsuleButton val = ((Component)_newCapsule).gameObject.AddComponent<UI_CapsuleButton>();
				val.unlockIcon = ((Component)_newCapsule.Find("Lock Image")).GetComponent<Image>();
				val.showDelayAnimation = 10f;
				val.unlockAchievement = "ACH_TUTORIAL";
				((Component)_newCapsule).gameObject.AddComponent<GiveMeMyUnlocksPls>();
				((Component)_newCapsule).gameObject.SetActive(false);
				UI_Gamemode_Button val2 = ((Component)_newCapsule).gameObject.AddComponent<UI_Gamemode_Button>();
				val2.gamemode = _gameMode;
				val2.title = ((Component)_newCapsule.Find("Mode Name")).GetComponent<TMP_Text>();
				val2.unlockText = (TMP_Text)(object)((Component)_newCapsule.Find("Lock Image/Unlock Requirement")).GetComponent<TextMeshProUGUI>();
				GameObject obj = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Endless/Viewport/Content/Mode Selection Button - Endless");
				Transform val3 = ((obj != null) ? obj.transform : null);
				UI_Gamemode_Button val4 = ((val3 != null) ? ((Component)val3).GetComponent<UI_Gamemode_Button>() : null);
				if (val3 != null && val4 != null)
				{
					val2.medalImage = val4.medalImage;
					val2.medals = val4.medals;
					val2.showMedals = false;
				}
				((Component)_newCapsule).gameObject.SetActive(true);
			}

			private void ConfigureRoachCounter()
			{
				Transform val = _newCapsule.Find("Roach Counter/Roaches");
				if (val != null)
				{
					((Component)val.parent).gameObject.SetActive(true);
					((Component)val).gameObject.SetActive(true);
					UI_RoachBankAmount val2 = ((Component)val).gameObject.AddComponent<UI_RoachBankAmount>();
					val2.roachBankID = "custom-" + _gameMode.gamemodeName;
				}
			}

			private void ConfigureAuthor()
			{
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				if (string.IsNullOrEmpty(_author))
				{
					return;
				}
				Transform val = _newCapsule.Find("Roach Counter/Roaches");
				Transform val2 = ((val != null) ? val.parent : null);
				if (val2 != null)
				{
					Transform val3 = Object.Instantiate<Transform>(val2, _newCapsule);
					((Object)val3).name = "Author Name Holder";
					Object.Destroy((Object)(object)((Component)val3).gameObject.GetComponent<Image>());
					RectTransform component = ((Component)val3).GetComponent<RectTransform>();
					component.anchoredPosition = new Vector2(2.5f, -55f);
					Transform child = val3.GetChild(0);
					((Object)child).name = "Author Name";
					Object.Destroy((Object)(object)((Component)child).gameObject.GetComponent<UI_RoachBankAmount>());
					TextMeshProUGUI component2 = ((Component)child).GetComponent<TextMeshProUGUI>();
					LogManager.Debug($"Text compotnent is: {component2 != null}");
					if (component2 != null)
					{
						((Component)child).gameObject.SetActive(true);
						((TMP_Text)component2).fontSizeMin = 10f;
						((TMP_Text)component2).maxVisibleLines = 2;
						((TMP_Text)component2).alignment = (TextAlignmentOptions)4097;
						((Graphic)component2).color = new Color(1f, 1f, 1f, 1f);
						((TMP_Text)component2).text = "By: " + _author;
					}
				}
			}

			private void RebuildLayouts()
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_categoryHolder).GetComponent<RectTransform>());
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_contentTransform).GetComponent<RectTransform>());
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_contentTransform.parent).gameObject.GetComponent<RectTransform>());
			}

			private static GameObject CreateCategoryHolder(string category)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Expected O, but got Unknown
				//IL_001f: 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_0039: 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_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Expected O, but got Unknown
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_01df: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
				string text = category + " Holder";
				GameObject val = new GameObject(text);
				try
				{
					RectTransform val2 = val.AddComponent<RectTransform>();
					val2.anchorMin = Vector2.one;
					val2.anchorMax = Vector2.one;
					val2.anchoredPosition = Vector2.zero;
					val2.pivot = Vector2.one * 0.5f;
					HorizontalLayoutGroup val3 = val.AddComponent<HorizontalLayoutGroup>();
					((HorizontalOrVerticalLayoutGroup)val3).spacing = 15f;
					((LayoutGroup)val3).childAlignment = (TextAnchor)3;
					((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = true;
					((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = false;
					((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = false;
					((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = false;
					((LayoutGroup)val3).padding = new RectOffset(15, 20, 0, 0);
					ContentSizeFitter val4 = val.AddComponent<ContentSizeFitter>();
					val4.horizontalFit = (FitMode)1;
					val4.verticalFit = (FitMode)0;
					val.transform.localScale = Vector3.one;
					((Transform)val2).localScale = Vector3.one;
				}
				catch (Exception ex)
				{
					LogManager.Error("[CapsuleFactory] Error creating category holder: " + ex.Message);
				}
				GameObject obj = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Endless/Viewport/Content");
				Transform val5 = ((obj != null) ? obj.transform : null);
				if (val5 == null)
				{
					LogManager.Error("[CapsuleFactory] Cannot find Content for category.");
					return val;
				}
				Transform val6 = val5.Find("Mode - Major Section Break - Endless");
				if (val6 == null)
				{
					LogManager.Error("[CapsuleFactory] Section break template missing.");
					return val;
				}
				Transform val7 = Object.Instantiate<Transform>(val6, val.transform);
				((Object)val7).name = "Major Section Break.Custom-GameModes";
				val7.localScale = Vector3.one;
				((Component)val7).gameObject.SetActive(true);
				Transform val8 = val7.Find("Section Title/Mode Name");
				TextMeshProUGUI component = ((Component)val8).GetComponent<TextMeshProUGUI>();
				if (component != null)
				{
					((TMP_Text)component).text = category;
					((TMP_Text)component).faceColor = Color32.op_Implicit(new Color(20f / 51f, 20f / 51f, 20f / 51f, 1f));
					((TMP_Text)component).fontSize = 28f;
				}
				Transform val9 = val7.Find("Section Title/Roach Counter - Regular");
				Transform val10 = val7.Find("Section Title/Roach Counter - Hard");
				Object.Destroy((Object)(object)((val9 != null) ? ((Component)val9).gameObject : null));
				Object.Destroy((Object)(object)((val10 != null) ? ((Component)val10).gameObject : null));
				return val;
			}
		}

		public void CreateCapsuleForGameMode(M_Gamemode gameMode, string category = "default", List<Sprite> sprites = null, string author = null)
		{
			new Builder(gameMode).WithCategory(category).WithSprites(sprites).WithAuthor(author)
				.Build();
		}
	}
}
namespace CustomGameModes.Controllers
{
	public class GameModeController : MonoBehaviour
	{
		private enum ConfigKind
		{
			Standard,
			Premade,
			Unknown
		}

		public static GameModeController Instance;

		public string currentScene;

		private CapsuleFactory _capsuleFactory;

		private AssetService _assetService;

		private const string ConfigFileName = "config.json";

		private readonly Dictionary<ConfigKind, Func<string, JObject, Task>> _configHandlers;

		private const string GameModesRoot = "Gamemodes";

		private const string PlayPane = "Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane";

		private readonly Dictionary<string, float> _progressPhases = new Dictionary<string, float>();

		private int _expectedPhaseCount;

		private Transform _customLoadingGamemodes;

		private string _customRoot;

		private float _lastUpdateHeader;

		private float _wait;

		private readonly Dictionary<string, GameObject> _customCategories = new Dictionary<string, GameObject>();

		public Dictionary<string, int> LastChosenSpriteIndices { get; } = new Dictionary<string, int>();


		public GameModeController()
		{
			_configHandlers = new Dictionary<ConfigKind, Func<string, JObject, Task>>
			{
				{
					ConfigKind.Premade,
					HandlePremadeConfigAsync
				},
				{
					ConfigKind.Standard,
					HandleStandardConfigAsync
				}
			};
		}

		private void Awake()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			if (Instance == null || (Object)(object)Instance != (Object)(object)this)
			{
				Instance = this;
			}
			else
			{
				Object.Destroy((Object)(object)this);
			}
			LogManager.Info("[GameModeController] Awake()");
			_assetService = new AssetService(Plugin.LibAPI);
			_capsuleFactory = new CapsuleFactory();
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "Gamemodes");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			_customRoot = text;
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			currentScene = ((Scene)(ref scene)).name;
			if (!(((Scene)(ref scene)).name != "Main-Menu"))
			{
				SetupStuff();
				((Component)this).gameObject.SetActive(true);
				_expectedPhaseCount = 0;
			}
		}

		private async void SetupStuff()
		{
			LogManager.Info("[GameModeController] Setting up menu!");
			PrepareLoadingText();
			PreparePlaySection();
			PrepareMenuTab();
			string baseFolder = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Gamemodes");
			string[] folders = Directory.GetDirectories(baseFolder);
			string[] array = folders;
			for (int i = 0; i < array.Length; i++)
			{
				await ProcessGamemodeFolderAsync(Path.Combine(path2: array[i], path1: Assembly.GetExecutingAssembly().Location));
			}
			string[] foldersPlugins = Directory.GetDirectories(Paths.PluginPath);
			string[] array2 = foldersPlugins;
			for (int j = 0; j < array2.Length; j++)
			{
				await ProcessGamemodeFolderAsync(Path.Combine(path2: array2[j], path1: Paths.PluginPath));
			}
		}

		private void PrepareLoadingText()
		{
			//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_0088: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = GameObject.Find("Canvas - Main Menu").transform;
			GameObject loadingInstance = TextLoading.LoadingInstance;
			GameObject val = Object.Instantiate<GameObject>(loadingInstance, transform);
			val.SetActive(true);
			((Object)val).name = "Loading Gamemodes";
			RectTransform component = val.GetComponent<RectTransform>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.offsetMin = new Vector2(-250f, -360f);
				component.offsetMax = new Vector2(250f, -255f);
				((Component)component).transform.localPosition = new Vector3(0f, -306f, 0f);
			}
			bool flag = _progressPhases.All((KeyValuePair<string, float> x) => x.Value >= 1f) && _progressPhases.Count == _expectedPhaseCount;
			val.gameObject.SetActive(!flag);
			_customLoadingGamemodes = val.transform;
		}

		private void UpdateLoadingText(Dictionary<string, float> progressPhases)
		{
			if (Time.time - _lastUpdateHeader < _wait)
			{
				return;
			}
			_wait = (float)Random.Range(15, 30) / 100f;
			_lastUpdateHeader = Time.time;
			if (_customLoadingGamemodes == null || currentScene != "Main-Menu")
			{
				return;
			}
			TextMeshProUGUI component = ((Component)_customLoadingGamemodes.Find("Load Title")).GetComponent<TextMeshProUGUI>();
			StringBuilder stringBuilder = new StringBuilder();
			List<string> list = progressPhases.Keys.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				string text = list[i];
				float num = progressPhases[text];
				if (!(num >= 1f))
				{
					stringBuilder.AppendLine($"({i + 1}/{_expectedPhaseCount}) {text}: {num * 100f:0}%");
				}
			}
			((TMP_Text)component).fontSize = 35f;
			((TMP_Text)component).text = stringBuilder.ToString();
			bool flag = progressPhases.All((KeyValuePair<string, float> x) => x.Value >= 1f) && progressPhases.Count == _expectedPhaseCount;
			((Component)_customLoadingGamemodes).gameObject.SetActive(!flag);
		}

		private async Task CheckIfAllLoaded()
		{
			if (_progressPhases.All((KeyValuePair<string, float> x) => x.Value >= 1f) && _progressPhases.Count == _expectedPhaseCount)
			{
				((Component)_customLoadingGamemodes).gameObject.SetActive(false);
				return;
			}
			await Task.Delay(1000);
			await Task.Run((Func<Task?>)CheckIfAllLoaded);
		}

		private async Task ProcessGamemodeFolderAsync(string folderPath)
		{
			string configPath = Path.Combine(folderPath, "config.json");
			if (File.Exists(configPath))
			{
				string jsonText;
				try
				{
					jsonText = await File.ReadAllTextAsync(configPath);
				}
				catch (Exception ex)
				{
					Exception e2 = ex;
					LogManager.Error("[GameModeLoader] Failed reading " + configPath + ": " + e2.Message);
					return;
				}
				JObject root;
				try
				{
					root = JObject.Parse(jsonText);
				}
				catch (Exception e)
				{
					LogManager.Error("[GameModeLoader] Invalid JSON in " + configPath + ": " + e.Message);
					return;
				}
				ConfigKind kind = DetectConfigKind(root);
				if (!_configHandlers.TryGetValue(kind, out var handler))
				{
					LogManager.Error($"[GameModeLoader] No handler for config kind {kind}");
				}
				else
				{
					await handler(folderPath, root);
				}
			}
		}

		private async Task HandleStandardConfigAsync(string folderPath, JObject root)
		{
			_expectedPhaseCount += 2;
			try
			{
				GamemodeConfig cfg;
				try
				{
					cfg = ((JToken)root).ToObject<GamemodeConfig>();
				}
				catch (Exception ex)
				{
					Exception e2 = ex;
					LogManager.Error($"[GameModeLoader] Invalid Standard Config Structure: {e2}");
					return;
				}
				if (cfg.regions == null)
				{
					LogManager.Error("[GameModeLoader] Standard Config is missing regions");
					return;
				}
				string assetsFolder = Path.Combine(folderPath, "Assets");
				if (cfg.assetBundleFileName != null && !File.Exists(Path.Combine(assetsFolder, cfg.assetBundleFileName)))
				{
					LogManager.Error("[GameModeLoader] Standard Config is missing asset bundle file");
					return;
				}
				string gmName = cfg.gamemodeName;
				string levelPhaseKey = "Loading Levels for \"" + gmName + "\"";
				_progressPhases[levelPhaseKey] = 0f;
				IProgress<float> levelProgress = new Progress<float>(delegate(float p)
				{
					_progressPhases[levelPhaseKey] = p;
					UpdateLoadingText(_progressPhases);
				});
				Sprite capsuleSprite = _assetService.LoadPngAsSprite(Path.Combine(assetsFolder, cfg.capsuleIcon));
				Sprite screenSprite = _assetService.LoadPngAsSprite(Path.Combine(assetsFolder, cfg.screenIcon));
				Dictionary<string, M_Level> allLevels = new Dictionary<string, M_Level>();
				foreach (LevelAssetHolder inGameLevel in CL_AssetManager.GetFullCombinedAssetDatabase().levelAssets)
				{
					allLevels.TryAdd(((Object)inGameLevel.level).name, inGameLevel.level);
				}
				if (!string.IsNullOrEmpty(cfg.assetBundleFileName))
				{
					AssetBundle bundle = await _assetService.LoadBundleRelativeAsync(Path.Combine(assetsFolder, cfg.assetBundleFileName), levelProgress);
					Dictionary<string, M_Level> levelsToAdd = (await _assetService.LoadAllLevelsFromBundle(bundle, levelProgress)).Where((KeyValuePair<string, M_Level> x) => !allLevels.Contains(x)).ToDictionary((KeyValuePair<string, M_Level> x) => x.Key, (KeyValuePair<string, M_Level> x) => x.Value);
					Extensions.AddRange<string, M_Level>(allLevels, levelsToAdd);
				}
				List<M_Region> regions = cfg.regions.Select((RegionConfig rc) => BuildRegion(rc, allLevels)).ToList();
				string gmPhaseKey = "Loading Gamemode for \"" + gmName + "\"";
				_progressPhases[gmPhaseKey] = 0f;
				IProgress<float> gmProgress = new Progress<float>(delegate(float p)
				{
					_progressPhases[gmPhaseKey] = p;
					UpdateLoadingText(_progressPhases);
				});
				M_Gamemode gm = ScriptableObject.CreateInstance<M_Gamemode>();
				gm.allowAchievements = false;
				gm.allowCheatedScores = false;
				gm.allowCheats = true;
				gm.allowLeaderboardScoring = true;
				gm.steamLeaderboardName = "";
				gm.allowHeightAchievements = false;
				gm.baseGamemode = true;
				gm.modeType = (GameType)((!cfg.isEndless) ? 1 : 3);
				gm.capsuleName = cfg.gamemodeName;
				gm.gamemodeName = cfg.gamemodeName;
				gm.introText = cfg.introText;
				gm.isEndless = cfg.isEndless;
				gm.hasPerks = cfg.hasPerks;
				gm.hasRevives = cfg.hasRevives;
				gm.gamemodeScene = "Game-Main";
				gm.roachBankID = "custom-" + cfg.gamemodeName;
				gm.gamemodePanel = ((IEnumerable<UI_GamemodeScreen_Panel>)Resources.FindObjectsOfTypeAll<UI_GamemodeScreen_Panel>()).FirstOrDefault((Func<UI_GamemodeScreen_Panel, bool>)((UI_GamemodeScreen_Panel x) => ((Object)x).name == "Gamemode_Panel_Base"));
				gm.loseScreen = ((IEnumerable<UI_ScoreScreen>)Resources.FindObjectsOfTypeAll<UI_ScoreScreen>()).FirstOrDefault((Func<UI_ScoreScreen, bool>)((UI_ScoreScreen x) => ((Object)x).name == "ScorePanel_Standard_Death"));
				gm.winScreen = ((IEnumerable<UI_ScoreScreen>)Resources.FindObjectsOfTypeAll<UI_ScoreScreen>()).FirstOrDefault((Func<UI_ScoreScreen, bool>)((UI_ScoreScreen x) => ((Object)x).name == "ScorePanel_Standard_Win"));
				gm.modeTags = new List<string>(1) { "" };
				gm.unlockAchievement = "";
				gm.gamemodeModule = (GamemodeModule)new GamemodeModule_Standard
				{
					winScoreMultiplier = 1f
				};
				gm.startItems = new List<SpawnItem>(1)
				{
					new SpawnItem
					{
						itemid = "Item_Hammer"
					}
				};
				((Object)gm).name = cfg.gamemodeName;
				gm.capsuleArt = capsuleSprite;
				gm.screenArt = screenSprite;
				gm.regions = regions;
				GameType GameType = (GameType)4;
				switch (cfg.gameType.ToLower() ?? "single")
				{
				case "endless":
					GameType = (GameType)3;
					break;
				case "standard":
					GameType = (GameType)0;
					break;
				case "playlist":
					GameType = (GameType)1;
					break;
				case "playlist-shuffle":
					GameType = (GameType)2;
					break;
				case "single":
					GameType = (GameType)4;
					break;
				}
				int numLevelsToLoad = 0;
				regions.ForEach(delegate(M_Region reg)
				{
					reg.subregionGroups.ForEach(delegate(SubregionGroup subRegGroup)
					{
						subRegGroup.subregions.ForEach(delegate(M_Subregion subReg)
						{
							numLevelsToLoad += subReg.levelReferences.Count;
						});
					});
				});
				LogManager.Debug($"[Gamemode Builder] Will load {numLevelsToLoad} levels for {cfg.gamemodeName}");
				int num = numLevelsToLoad;
				int num2 = num;
				if (num2 <= 1)
				{
					if (num2 == 1)
					{
						gm.modeType = (GameType)4;
						gm.playlistLevelAssets = new List<LevelAssetHolder>(1) { regions[0].subregionGroups[0].subregions[0].levelReferences[0] };
						LogManager.Debug("[Gamemode Builder] Loading one singular level");
					}
				}
				else if ((int)GameType == 4)
				{
					gm.modeType = (GameType)1;
					regions.ForEach(delegate(M_Region reg)
					{
						reg.subregionGroups.ForEach(delegate(SubregionGroup subRegGroup)
						{
							subRegGroup.subregions.ForEach(delegate(M_Subregion subReg)
							{
								gm.playlistLevelAssets.AddRange(subReg.levelReferences);
							});
						});
					});
				}
				else
				{
					gm.modeType = GameType;
					List<LevelAssetHolder> levels = new List<LevelAssetHolder>();
					int loadedLevels = 0;
					foreach (LevelAssetHolder level2 in from region in regions
						from subRegionGroup in region.subregionGroups
						from subRegion in subRegionGroup.subregions
						from level in subRegion.levelReferences
						select level)
					{
						try
						{
							levels.Add(level2);
							loadedLevels++;
						}
						catch (Exception e)
						{
							Debug.LogError((object)e);
							LogManager.Error("[Gamemode Builder] Failed to load: " + e.Message);
						}
					}
					LogManager.Debug($"[Gamemode Builder] Loaded {loadedLevels}/{numLevelsToLoad} levels");
					regions.ForEach(delegate(M_Region reg)
					{
						reg.subregionGroups.ForEach(delegate(SubregionGroup subRegGroup)
						{
							subRegGroup.subregions.ForEach(delegate(M_Subregion subReg)
							{
								gm.playlistLevelAssets.AddRange(subReg.levelReferences);
							});
						});
					});
				}
				gm.levelsToGenerate = numLevelsToLoad;
				GameObject worldRoot = ((IEnumerable<GameObject>)Resources.FindObjectsOfTypeAll<GameObject>()).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => ((Object)go).name == "World_Root"));
				gm.gamemodeObjects = ((worldRoot != null) ? new List<GameObject>(1) { worldRoot } : new List<GameObject>());
				levelProgress.Report(1f);
				gmProgress.Report(1f);
				_capsuleFactory.CreateCapsuleForGameMode(gm, cfg.category ?? "default", null, cfg.author);
			}
			catch
			{
				LogManager.Error("Couldn't process " + folderPath);
			}
		}

		private async Task HandlePremadeConfigAsync(string folderPath, JObject root)
		{
			_expectedPhaseCount += 3;
			try
			{
				PremadeGamemodeConfig cfg;
				try
				{
					cfg = ((JToken)root).ToObject<PremadeGamemodeConfig>();
				}
				catch (Exception ex)
				{
					Exception e = ex;
					LogManager.Error($"[GameModeLoader] Invalid Premade Config Structure: {e}");
					return;
				}
				if (string.IsNullOrEmpty(cfg.assetBundle) || string.IsNullOrEmpty(cfg.gamemodeName))
				{
					LogManager.Error("[GamemodeLoader] Premade config is missing required fields");
					return;
				}
				string assetsFolder = Path.Combine(folderPath, "Assets");
				if (!Directory.Exists(assetsFolder))
				{
					LogManager.Error("[GamemodeLoader] Premade Assets folder is missing");
					return;
				}
				string gmName = cfg.gamemodeName;
				string assetPhaseProgress = "Loading Assets for \"" + gmName + "\"";
				_progressPhases[assetPhaseProgress] = 0f;
				IProgress<float> assetProgress = new Progress<float>(delegate(float p)
				{
					_progressPhases[assetPhaseProgress] = p;
					UpdateLoadingText(_progressPhases);
				});
				AssetBundle bundle = await _assetService.LoadBundleRelativeAsync(Path.Combine(assetsFolder, cfg.assetBundle), assetProgress);
				string levelPhaseKey = "Loading Levels for \"" + gmName + "\"";
				_progressPhases[levelPhaseKey] = 0f;
				IProgress<float> levelProgress = new Progress<float>(delegate(float p)
				{
					_progressPhases[levelPhaseKey] = p;
					UpdateLoadingText(_progressPhases);
				});
				await _assetService.LoadAllLevelsFromBundle(bundle, levelProgress);
				string gmPhaseKey = "Loading Gamemode \"" + gmName + "\"";
				_progressPhases[gmPhaseKey] = 0f;
				IProgress<float> gmProgress = new Progress<float>(delegate(float p)
				{
					_progressPhases[gmPhaseKey] = p;
					UpdateLoadingText(_progressPhases);
				});
				M_Gamemode gm = await _assetService.LoadGameModeFromBundle(bundle, cfg.gamemodeName, gmProgress);
				gm.playlistLevelAssets = ((IEnumerable<M_Level>)gm.playlistLevels).Select((Func<M_Level, LevelAssetHolder>)LevelAssetHolder.GetNewHolderFromLevel).ToList();
				List<Sprite> capsuleArtsFinal = null;
				if (cfg.capsuleArts != null)
				{
					if (cfg.capsuleArts.Count == 1)
					{
						Sprite loadedArt = _assetService.LoadPngAsSprite(cfg.capsuleArts[0]);
						if (loadedArt == null)
						{
							LogManager.Error("Failed to load " + cfg.capsuleArts[0] + " for the capsule art! (gamemode: " + cfg.gamemodeName + ")");
						}
						else
						{
							gm.capsuleArt = _assetService.LoadPngAsSprite(cfg.capsuleArts[0]);
						}
					}
					else
					{
						List<Sprite> capsuleArts = new List<Sprite>();
						capsuleArts.AddRange(from capsuleArt in cfg.capsuleArts
							select _assetService.LoadPngAsSprite(Path.Combine(assetsFolder, capsuleArt)) into x
							where x != null
							select x);
						capsuleArtsFinal = capsuleArts;
					}
				}
				ApplyRandomArt(cfg.screenArts, assetsFolder, delegate(string a)
				{
					gm.screenArt = _assetService.LoadPngAsSprite(a);
				});
				levelProgress.Report(1f);
				gmProgress.Report(1f);
				_capsuleFactory.CreateCapsuleForGameMode(gm, cfg.category ?? "default", capsuleArtsFinal, cfg.author);
			}
			catch
			{
				LogManager.Error("Couldn't process " + folderPath);
			}
		}

		private static ConfigKind DetectConfigKind(JObject j)
		{
			if (j["assetBundle"] != null && j["gamemodeName"] != null)
			{
				return ConfigKind.Premade;
			}
			if (j["regions"] != null)
			{
				return ConfigKind.Standard;
			}
			return ConfigKind.Unknown;
		}

		private static void ApplyRandomArt(List<string> paths, string baseFolder, Action<string> apply)
		{
			if (paths != null && paths.Count != 0)
			{
				string path = ((paths.Count == 1) ? paths[0] : paths[Random.Range(0, paths.Count - 1)]);
				string obj = Path.Combine(baseFolder, path);
				apply(obj);
			}
		}

		private M_Region BuildRegion(RegionConfig rc, Dictionary<string, M_Level> levels)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			List<M_Subregion> list = (rc.subregions ?? new List<SubregionConfig>()).Select(delegate(SubregionConfig src)
			{
				List<M_Level> source = FindMatchingLevels(src, levels);
				M_Subregion val4 = ScriptableObject.CreateInstance<M_Subregion>();
				val4.subregionName = src.subregionName;
				((Object)val4).name = src.subregionName;
				val4.levelReferences = source.Select((M_Level l) => LevelAssetHolder.GetNewHolderFromLevel(l)).ToList();
				val4.subregionHeight = val4.levelReferences.Sum((LevelAssetHolder lv) => lv.level.GetHeight());
				val4.sessionEventLists = val4.levelReferences.SelectMany((LevelAssetHolder lv) => lv.level.sessionEventLists).ToList();
				return val4;
			}).ToList();
			M_Region val = ScriptableObject.CreateInstance<M_Region>();
			val.regionName = rc.regionName;
			((Object)val).name = rc.regionName;
			List<SubregionGroup> list2 = new List<SubregionGroup>();
			foreach (M_Subregion item in list)
			{
				list2.Add(new SubregionGroup
				{
					subregions = new List<M_Subregion>(1) { item }
				});
			}
			val.subregionGroups = list2;
			if (list.Count > 1 && list[0].levelReferences.Count > 1)
			{
				List<TransitionLevels> list3 = new List<TransitionLevels>(1);
				TransitionLevels val2 = new TransitionLevels
				{
					fromRegion = rc.regionName
				};
				List<M_Level> list4 = new List<M_Level>(1);
				List<LevelAssetHolder> levelReferences = list[0].levelReferences;
				list4.Add(levelReferences[levelReferences.Count - 1].level);
				val2.levels = list4;
				list3.Add(val2);
				val.transitionLevels = list3;
				list[0].levelReferences.RemoveAt(list[0].levelReferences.Count - 1);
			}
			val.regionHeight = list.Sum((M_Subregion sr) => sr.subregionHeight);
			M_Level val3 = ((IEnumerable<LevelAssetHolder>)CL_AssetManager.GetFullCombinedAssetDatabase().levelAssets).FirstOrDefault((Func<LevelAssetHolder, bool>)((LevelAssetHolder pref) => pref.level.levelName == "M1_Intro_01"))?.level;
			if (val3 != null)
			{
				val.startLevels = new List<M_Level>(1) { val3 };
			}
			val.regionOrder = (RegionOrder)1;
			val.introText = rc.regionName;
			val.sessionEventLists = list.SelectMany((M_Subregion sr) => sr.sessionEventLists).ToList();
			return val;
		}

		private List<M_Level> FindMatchingLevels(SubregionConfig src, Dictionary<string, M_Level> levels)
		{
			if (levels != null && src.levelNameContains != null)
			{
				return (from kv in levels
					where kv.Key.IndexOf(src.levelNameContains, StringComparison.OrdinalIgnoreCase) >= 0
					select kv.Value).ToList();
			}
			if (src.levels != null)
			{
				return ((IEnumerable<string>)src.levels).SelectMany((Func<string, IEnumerable<M_Level>>)_assetService.FindLevelsByName).ToList();
			}
			LogManager.Error("[GamemodeLoader] No matching rule for subregion " + src.subregionName);
			return new List<M_Level>();
		}

		private void PrepareMenuTab()
		{
			GameObject val = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tabs/Tab Buttons");
			if (val != null)
			{
				Transform obj = val.transform.Find("ModeButton_Custom");
				GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null);
				if (val2 != null)
				{
					val2.gameObject.SetActive(true);
				}
			}
		}

		private void PreparePlaySection()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_011e: 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_0138: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Custom/Viewport/Content");
			Transform val = ((obj != null) ? obj.transform : null);
			if (val == null)
			{
				LogManager.Error("[GameModeController] Cannot find Play Menu content.");
				return;
			}
			for (int i = 0; i < val.childCount; i++)
			{
				((Component)val.GetChild(i)).gameObject.SetActive(false);
			}
			GameObject obj2 = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Play/Play Menu/Play Pane/Tab Objects/Play Pane - Scroll View Tab - Endless Variant/Viewport/Content");
			Transform val2 = ((obj2 != null) ? obj2.transform : null);
			if (val2 == null)
			{
				LogManager.Error("[GameModeController] Cannot find content To Copy From.");
				return;
			}
			Transform val3 = val2.Find("Mode - Major Section Break - Endless");
			if (val3 == null)
			{
				LogManager.Error("[GameModeController] Cannot find section‐break template.");
				return;
			}
			Transform val4 = Object.Instantiate<Transform>(val3, val);
			((Object)val4).name = "Major Section Break.Custom-GameModes";
			val4.localScale = Vector3.one;
			((Component)val4).gameObject.SetActive(false);
			Transform obj3 = val4.Find("Break.02");
			if (obj3 != null)
			{
				((Component)obj3).gameObject.SetActive(true);
			}
			GameObject val5 = new GameObject("Custom Gamemodes Holder");
			RectTransform val6 = val5.AddComponent<RectTransform>();
			val6.anchorMin = Vector2.one;
			val6.anchorMax = Vector2.one;
			val6.anchoredPosition = Vector2.zero;
			val6.pivot = Vector2.one * 0.5f;
			HorizontalLayoutGroup val7 = val5.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val7).spacing = 7.5f;
			((LayoutGroup)val7).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)val7).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)val7).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)val7).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)val7).childControlHeight = false;
			((LayoutGroup)val7).padding = new RectOffset(5, 10, 0, 0);
			val5.transform.SetParent(((Component)val).transform);
			ContentSizeFitter val8 = val5.AddComponent<ContentSizeFitter>();
			val8.verticalFit = (FitMode)0;
			val8.horizontalFit = (FitMode)1;
			val5.transform.localScale = Vector3.one;
			((Transform)val6).localScale = Vector3.one;
			Transform val9 = val4.Find("Section Title/Mode Name");
			TextMeshProUGUI val10 = ((val9 != null) ? ((Component)val9).GetComponent<TextMeshProUGUI>() : null);
			if (val10 != null)
			{
				((TMP_Text)val10).text = "Custom GameModes".ToUpper();
			}
			Transform val11 = val4.Find("Section Title/Roach Counter - Regular");
			Transform val12 = val4.Find("Section Title/Roach Counter - Hard");
			object obj4;
			if (val11 == null)
			{
				obj4 = null;
			}
			else
			{
				GameObject gameObject = ((Component)val11).gameObject;
				obj4 = ((gameObject != null) ? gameObject.GetComponent<UT_HardModeEnable>() : null);
			}
			Object.Destroy((Object)obj4);
			Object.Destroy((Object)(object)((val11 != null) ? ((Component)val11.GetChild(0)).GetComponent<UI_RoachBankAmount>() : null));
			Object.Destroy((Object)(object)((val11 != null) ? ((Component)val11).gameObject : null));
			Object.Destroy((Object)(object)((val12 != null) ? ((Component)val12).gameObject : null));
		}
	}
}
namespace CustomGameModes.Config
{
	[Serializable]
	public class CampaignExtensionConfig
	{
		public string extensionName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string author;

		public string capsuleIcon;

		public string screenIcon;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string assetBundleFileName;

		public List<RegionConfig> regions;
	}
	[Serializable]
	public class GamemodeConfig
	{
		public string gamemodeName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string author;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string category;

		public string introText;

		public bool isEndless;

		public bool hasPerks;

		public bool hasRevives;

		public string capsuleIcon;

		public string screenIcon;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string assetBundleFileName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string gameType;

		public List<RegionConfig> regions;
	}
	[Serializable]
	public class PremadeGamemodeConfig
	{
		public string assetBundle;

		public string gamemodeName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string author;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string category;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<string> capsuleArts;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<string> screenArts;
	}
	[Serializable]
	public class RegionConfig
	{
		public string regionName;

		public List<SubregionConfig> subregions;
	}
	[Serializable]
	public class SubregionConfig
	{
		public string subregionName;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string levelNameContains;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<string> levels;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public List<string> blacklist;
	}
}