Decompiled source of CustomContent RoguelikeMode Patch v0.3.4

CustomContentRoguelike.dll

Decompiled a week ago
using System;
using System.Collections;
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 BepInEx;
using BepInEx.Configuration;
using DM;
using HarmonyLib;
using Landfall.TABS;
using Landfall.TABS.Workshop;
using Microsoft.CodeAnalysis;
using RoguelikeMode.Roguelike;
using Sirenix.Serialization;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CustomContentRoguelike")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomContentRoguelike")]
[assembly: AssemblyTitle("CustomContentRoguelike")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CustomContentRoguelike
{
	[BepInPlugin("customcontent.roguelike.compat", "RoguelikeMode Custom Content Compatibility", "0.3.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		private sealed class FilterState
		{
			public HashSet<string> DisabledFactionIds = new HashSet<string>();

			public HashSet<string> DisabledCampaignIds = new HashSet<string>();
		}

		private enum ContentSource
		{
			Vanilla,
			Mod,
			Custom
		}

		private sealed class FilterEntry
		{
			public string Id;

			public string Name;

			public ContentSource Source;

			public bool Disabled;
		}

		private sealed class CampaignInfo
		{
			public DatabaseID Id;

			public string Name;

			public List<DatabaseID> LevelIds = new List<DatabaseID>();

			public object RawObject;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__DrawFilterWindow;

			public static Func<Faction, bool> <1>__IsPlayableFactionCompat;
		}

		public const string PluginGuid = "customcontent.roguelike.compat";

		public const string PluginName = "RoguelikeMode Custom Content Compatibility";

		public const string PluginVersion = "0.3.4";

		private const int FilterWindowId = 173920;

		private const float FilterWindowWidth = 760f;

		private const float FilterWindowHeight = 620f;

		private static readonly string FilterStatePath = Path.Combine(Paths.ConfigPath, "CustomContentRoguelike.filters.dat");

		private static FilterState filterState = new FilterState();

		private static ConfigEntry<KeyCode> filterMenuKey;

		private static GUIStyle filterWindowStyle;

		private static GUIStyle filterTitleStyle;

		private static GUISkin filterGuiSkin;

		private static GUIStyle filterPanelStyle;

		private static GUIStyle filterLabelStyle;

		private static GUIStyle filterSmallLabelStyle;

		private static GUIStyle filterButtonStyle;

		private static GUIStyle filterTextFieldStyle;

		private static GUIStyle filterCheckboxStyle;

		private static GUIStyle filterVerticalScrollbarStyle;

		private static GUIStyle filterVerticalScrollbarThumbStyle;

		private static GUIStyle filterHorizontalScrollbarStyle;

		private static GUIStyle filterHorizontalScrollbarThumbStyle;

		private static GUIStyle filterScrollViewStyle;

		private static GUIStyle[] filterTabStyles;

		private static Texture2D filterWindowBackground;

		private static Texture2D filterPanelBackground;

		private static Texture2D filterButtonBackground;

		private static Texture2D filterButtonHoverBackground;

		private static Texture2D filterButtonActiveBackground;

		private static Texture2D filterFieldBackground;

		private static bool filterMenuOpen;

		private static int filterTab;

		private static string searchText = string.Empty;

		private static Vector2 contentScroll;

		private static bool showVanilla = true;

		private static bool showMod = true;

		private static bool showCustom = true;

		private static List<FilterEntry> cachedEntries = new List<FilterEntry>();

		private static bool entriesDirty = true;

		private static string lastLevelIndexSummary;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00bc: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			LoadFilterState();
			filterMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Content Filter", "Menu Key", (KeyCode)289, "Keyboard key used to open the Roguelike Content Filter. Set to None to disable the hotkey.");
			Harmony val = new Harmony("customcontent.roguelike.compat");
			PatchPlayableFactions(val);
			Patch(val, "RoguelikeMode.Roguelike.CardPools", "GetUnitFromRosters", "PatchGetUnitFromRosters");
			PatchPrefix(val, "RoguelikeMode.Roguelike.CardPools", "GetLevel", "PatchGetLevel");
			PatchPrefix(val, "RoguelikeMode.Roguelike.CardPools", "EligibleUnits", "PatchEligibleUnits");
			PatchPrefix(val, "RoguelikeMode.Roguelike.FactionLookup", "PrimaryFactionForUnit", "PatchPrimaryFactionForUnit");
			PatchPrefix(val, "RoguelikeMode.Roguelike.FactionLookup", "DominantFaction", "PatchDominantFaction");
			PatchPrefix(val, "RoguelikeMode.Roguelike.CardChoices", "LevelIconLoader", "PatchLevelIconLoader");
			PatchLevelPoolBuildDifficultyIndex(val);
			LoggerStatic("RoguelikeMode Custom Content Compatibility 0.3.4 loaded.");
			LoggerStatic($"Content filter menu key: {filterMenuKey.Value}.");
		}

		private IEnumerator DiagnosticsWhenDatabaseReady()
		{
			for (int i = 1; i <= 1800; i++)
			{
				if (i % 120 == 0)
				{
					try
					{
						ContentDatabase val = ContentDatabase.Instance();
						IEnumerable<Faction> enumerable = ((val != null) ? val.GetAllFactions() : null);
						IEnumerable<CampaignInfo> enumerable2 = ((val != null) ? GetCampaignInfos(val) : null);
						LoggerStatic("[CLASSIFY2] wait=" + i / 60 + "s factions=" + (enumerable?.Count() ?? (-1)) + " campaigns=" + (enumerable2?.Count() ?? (-1)));
					}
					catch (Exception ex)
					{
						LoggerStatic("[CLASSIFY2] waiting: " + ex.GetBaseException().Message);
					}
				}
				yield return null;
			}
			DumpContentClassificationDiagnostics();
		}

		private void Update()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (filterMenuKey != null && (int)filterMenuKey.Value != 0 && Input.GetKeyDown(filterMenuKey.Value))
			{
				filterMenuOpen = !filterMenuOpen;
				entriesDirty = true;
				if (!filterMenuOpen)
				{
					SaveFilterState();
				}
			}
		}

		private void OnGUI()
		{
			//IL_004f: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			if (filterMenuOpen)
			{
				EnsureGuiStyles();
				GUISkin skin = GUI.skin;
				GUI.skin = filterGuiSkin;
				Rect val = new Rect(((float)Screen.width - 760f) / 2f, ((float)Screen.height - 620f) / 2f, 760f, 620f);
				object obj = <>O.<0>__DrawFilterWindow;
				if (obj == null)
				{
					WindowFunction val2 = DrawFilterWindow;
					<>O.<0>__DrawFilterWindow = val2;
					obj = (object)val2;
				}
				GUI.Window(173920, val, (WindowFunction)obj, string.Empty, filterWindowStyle);
				GUI.skin = skin;
			}
		}

		private static void EnsureGuiStyles()
		{
			//IL_001c: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Expected O, but got Unknown
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Expected O, but got Unknown
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Expected O, but got Unknown
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Expected O, but got Unknown
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Expected O, but got Unknown
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Expected O, but got Unknown
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Expected O, but got Unknown
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			//IL_054e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Expected O, but got Unknown
			//IL_0561: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Expected O, but got Unknown
			//IL_0575: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Expected O, but got Unknown
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_059c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a6: Expected O, but got Unknown
			//IL_05af: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Expected O, but got Unknown
			//IL_05c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cd: Expected O, but got Unknown
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Expected O, but got Unknown
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Expected O, but got Unknown
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Expected O, but got Unknown
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_0651: Expected O, but got Unknown
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Expected O, but got Unknown
			//IL_069b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Expected O, but got Unknown
			//IL_06af: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Expected O, but got Unknown
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Expected O, but got Unknown
			//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f3: Expected O, but got Unknown
			//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0725: Unknown result type (might be due to invalid IL or missing references)
			//IL_074f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0759: Expected O, but got Unknown
			//IL_0762: Unknown result type (might be due to invalid IL or missing references)
			//IL_076c: Expected O, but got Unknown
			//IL_0776: Unknown result type (might be due to invalid IL or missing references)
			//IL_0780: Expected O, but got Unknown
			//IL_078a: Unknown result type (might be due to invalid IL or missing references)
			//IL_07da: Unknown result type (might be due to invalid IL or missing references)
			//IL_082c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0836: Expected O, but got Unknown
			//IL_083f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0849: Expected O, but got Unknown
			if (filterWindowStyle == null)
			{
				filterWindowBackground = MakeGuiTexture(new Color(0.035f, 0.04f, 0.05f, 0.99f));
				filterPanelBackground = MakeGuiTexture(new Color(0.09f, 0.1f, 0.12f, 1f));
				filterButtonBackground = MakeGuiTexture(new Color(0.15f, 0.17f, 0.2f, 1f));
				filterButtonHoverBackground = MakeGuiTexture(new Color(0.4f, 0.62f, 0.16f, 1f));
				filterButtonActiveBackground = MakeGuiTexture(new Color(0.62f, 0.88f, 0.28f, 1f));
				filterFieldBackground = MakeGuiTexture(new Color(0.06f, 0.07f, 0.085f, 1f));
				filterWindowStyle = new GUIStyle(GUI.skin.window);
				SetStyleState(filterWindowStyle, filterWindowBackground, Color.white);
				filterWindowStyle.onNormal.background = filterWindowBackground;
				filterWindowStyle.onNormal.textColor = Color.white;
				filterWindowStyle.fontSize = 18;
				filterWindowStyle.fontStyle = (FontStyle)1;
				filterWindowStyle.alignment = (TextAnchor)1;
				filterWindowStyle.padding = new RectOffset(14, 14, 12, 14);
				filterWindowStyle.contentOffset = Vector2.zero;
				filterWindowStyle.border = new RectOffset(0, 0, 0, 0);
				filterTitleStyle = new GUIStyle(GUI.skin.label);
				filterTitleStyle.normal.textColor = Color.white;
				filterTitleStyle.alignment = (TextAnchor)4;
				filterTitleStyle.fontSize = 20;
				filterTitleStyle.fontStyle = (FontStyle)1;
				filterTitleStyle.margin = new RectOffset(0, 0, 0, 8);
				filterTitleStyle.fixedHeight = 34f;
				filterPanelStyle = new GUIStyle(GUI.skin.box);
				SetStyleState(filterPanelStyle, filterPanelBackground, Color.white);
				filterPanelStyle.fontSize = 15;
				filterPanelStyle.fontStyle = (FontStyle)1;
				filterPanelStyle.padding = new RectOffset(10, 10, 8, 8);
				filterPanelStyle.border = new RectOffset(0, 0, 0, 0);
				filterLabelStyle = new GUIStyle(GUI.skin.label);
				filterLabelStyle.normal.textColor = Color.white;
				filterLabelStyle.hover.textColor = Color.white;
				filterLabelStyle.fontSize = 15;
				filterLabelStyle.fontStyle = (FontStyle)1;
				filterLabelStyle.wordWrap = true;
				filterSmallLabelStyle = new GUIStyle(filterLabelStyle);
				filterSmallLabelStyle.fontSize = 12;
				filterSmallLabelStyle.fontStyle = (FontStyle)1;
				filterSmallLabelStyle.normal.textColor = new Color(0.78f, 0.82f, 0.86f, 1f);
				filterButtonStyle = new GUIStyle(GUI.skin.button);
				SetStyleState(filterButtonStyle, filterButtonBackground, Color.white);
				filterButtonStyle.hover.background = filterButtonHoverBackground;
				filterButtonStyle.hover.textColor = Color.black;
				filterButtonStyle.active.background = filterButtonActiveBackground;
				filterButtonStyle.active.textColor = Color.black;
				filterButtonStyle.onNormal.background = filterButtonActiveBackground;
				filterButtonStyle.onNormal.textColor = Color.black;
				filterButtonStyle.onHover.background = filterButtonActiveBackground;
				filterButtonStyle.onHover.textColor = Color.black;
				filterButtonStyle.onActive.background = filterButtonActiveBackground;
				filterButtonStyle.onActive.textColor = Color.black;
				filterButtonStyle.fontSize = 14;
				filterButtonStyle.fontStyle = (FontStyle)1;
				filterButtonStyle.alignment = (TextAnchor)4;
				filterButtonStyle.padding = new RectOffset(8, 8, 6, 6);
				filterButtonStyle.border = new RectOffset(0, 0, 0, 0);
				filterButtonStyle.margin = new RectOffset(2, 2, 2, 2);
				filterButtonStyle.stretchWidth = true;
				filterButtonStyle.stretchHeight = true;
				GUIStyle val = new GUIStyle(filterButtonStyle);
				SetStyleState(val, filterButtonBackground, Color.white);
				val.hover.background = filterButtonHoverBackground;
				val.active.background = filterButtonHoverBackground;
				GUIStyle val2 = new GUIStyle(filterButtonStyle);
				SetStyleState(val2, filterButtonActiveBackground, Color.black);
				val2.hover.background = filterButtonActiveBackground;
				val2.hover.textColor = Color.black;
				val2.active.background = filterButtonActiveBackground;
				val2.active.textColor = Color.black;
				filterTabStyles = (GUIStyle[])(object)new GUIStyle[2] { val, val2 };
				filterVerticalScrollbarStyle = new GUIStyle(GUI.skin.verticalScrollbar);
				SetStyleState(filterVerticalScrollbarStyle, filterButtonBackground, Color.white);
				filterVerticalScrollbarStyle.fixedWidth = 14f;
				filterVerticalScrollbarStyle.padding = new RectOffset(0, 0, 0, 0);
				filterVerticalScrollbarStyle.border = new RectOffset(0, 0, 0, 0);
				filterVerticalScrollbarThumbStyle = new GUIStyle(GUI.skin.verticalScrollbarThumb);
				SetStyleState(filterVerticalScrollbarThumbStyle, filterButtonHoverBackground, Color.white);
				filterVerticalScrollbarThumbStyle.border = new RectOffset(0, 0, 0, 0);
				filterVerticalScrollbarThumbStyle.margin = new RectOffset(0, 0, 0, 0);
				filterHorizontalScrollbarStyle = new GUIStyle(GUI.skin.horizontalScrollbar);
				SetStyleState(filterHorizontalScrollbarStyle, filterButtonBackground, Color.white);
				filterHorizontalScrollbarStyle.fixedHeight = 14f;
				filterHorizontalScrollbarStyle.padding = new RectOffset(0, 0, 0, 0);
				filterHorizontalScrollbarStyle.border = new RectOffset(0, 0, 0, 0);
				filterHorizontalScrollbarThumbStyle = new GUIStyle(GUI.skin.horizontalScrollbarThumb);
				SetStyleState(filterHorizontalScrollbarThumbStyle, filterButtonHoverBackground, Color.white);
				filterHorizontalScrollbarThumbStyle.border = new RectOffset(0, 0, 0, 0);
				filterHorizontalScrollbarThumbStyle.margin = new RectOffset(0, 0, 0, 0);
				filterGuiSkin = Object.Instantiate<GUISkin>(GUI.skin);
				filterGuiSkin.verticalScrollbarThumb = filterVerticalScrollbarThumbStyle;
				filterGuiSkin.horizontalScrollbarThumb = filterHorizontalScrollbarThumbStyle;
				filterScrollViewStyle = new GUIStyle(GUI.skin.box);
				SetStyleState(filterScrollViewStyle, filterFieldBackground, Color.white);
				filterScrollViewStyle.border = new RectOffset(0, 0, 0, 0);
				filterScrollViewStyle.padding = new RectOffset(4, 4, 4, 4);
				filterTextFieldStyle = new GUIStyle(GUI.skin.textField);
				SetStyleState(filterTextFieldStyle, filterFieldBackground, Color.white);
				filterTextFieldStyle.focused.background = filterButtonBackground;
				filterTextFieldStyle.focused.textColor = Color.white;
				filterTextFieldStyle.fontSize = 15;
				filterTextFieldStyle.fontStyle = (FontStyle)1;
				filterTextFieldStyle.padding = new RectOffset(8, 8, 5, 5);
				filterTextFieldStyle.border = new RectOffset(0, 0, 0, 0);
				filterCheckboxStyle = new GUIStyle(GUI.skin.toggle);
				SetStyleState(filterCheckboxStyle, filterButtonBackground, Color.white);
				filterCheckboxStyle.hover.background = filterButtonHoverBackground;
				filterCheckboxStyle.active.background = filterButtonActiveBackground;
				filterCheckboxStyle.onNormal.background = filterButtonActiveBackground;
				filterCheckboxStyle.onNormal.textColor = Color.white;
				filterCheckboxStyle.onHover.background = filterButtonActiveBackground;
				filterCheckboxStyle.onActive.background = filterButtonActiveBackground;
				filterCheckboxStyle.fontSize = 14;
				filterCheckboxStyle.fontStyle = (FontStyle)1;
				filterCheckboxStyle.border = new RectOffset(0, 0, 0, 0);
				filterCheckboxStyle.padding = new RectOffset(6, 6, 4, 4);
			}
		}

		private static void SetStyleState(GUIStyle style, Texture2D background, Color textColor)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			style.normal.background = background;
			style.normal.textColor = textColor;
			style.hover.background = background;
			style.hover.textColor = textColor;
			style.active.background = background;
			style.active.textColor = textColor;
			style.focused.background = background;
			style.focused.textColor = textColor;
			style.onNormal.background = background;
			style.onNormal.textColor = textColor;
			style.onHover.background = background;
			style.onHover.textColor = textColor;
			style.onActive.background = background;
			style.onActive.textColor = textColor;
			style.onFocused.background = background;
			style.onFocused.textColor = textColor;
		}

		private static Texture2D MakeGuiTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			((Object)val).hideFlags = (HideFlags)61;
			return val;
		}

		private static void DrawFilterWindow(int windowId)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Roguelike Content Filter", filterTitleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) });
			GUILayout.BeginVertical(filterPanelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Choose what Roguelike Mode may select. Changes are saved automatically.", filterLabelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Shortcut: " + ((filterMenuKey != null) ? ((object)filterMenuKey.Value/*cast due to .constrained prefix*/).ToString() : "None") + " (change in BepInEx config).", filterSmallLabelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Factions", filterTabStyles[(filterTab == 0) ? 1u : 0u], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }) && filterTab != 0)
			{
				filterTab = 0;
				searchText = string.Empty;
				contentScroll = Vector2.zero;
				entriesDirty = true;
			}
			if (GUILayout.Button("Campaigns", filterTabStyles[(filterTab == 1) ? 1u : 0u], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }) && filterTab != 1)
			{
				filterTab = 1;
				searchText = string.Empty;
				contentScroll = Vector2.zero;
				entriesDirty = true;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", filterLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			string text = GUILayout.TextField(searchText ?? string.Empty, filterTextFieldStyle, Array.Empty<GUILayoutOption>());
			if (text != searchText)
			{
				searchText = text;
				entriesDirty = true;
			}
			if (GUILayout.Button("Clear", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
			{
				searchText = string.Empty;
				entriesDirty = true;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Category:", filterLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
			bool flag = GUILayout.Toggle(showVanilla, "Vanilla", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			bool flag2 = GUILayout.Toggle(showMod, "Modded", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			bool flag3 = GUILayout.Toggle(showCustom, "Custom", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) });
			if (flag != showVanilla || flag2 != showMod || flag3 != showCustom)
			{
				showVanilla = flag;
				showMod = flag2;
				showCustom = flag3;
				entriesDirty = true;
			}
			if (GUILayout.Button("Show all", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
			{
				showVanilla = (showMod = (showCustom = true));
				entriesDirty = true;
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Enable all", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
			{
				if (filterTab == 0)
				{
					filterState.DisabledFactionIds.Clear();
				}
				else
				{
					filterState.DisabledCampaignIds.Clear();
				}
				SaveFilterState();
				entriesDirty = true;
			}
			if (GUILayout.Button("Exclude visible", filterButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) }))
			{
				EnsureEntries();
				foreach (FilterEntry cachedEntry in cachedEntries)
				{
					if (filterTab == 0)
					{
						filterState.DisabledFactionIds.Add(cachedEntry.Id);
					}
					else
					{
						filterState.DisabledCampaignIds.Add(cachedEntry.Id);
					}
				}
				SaveFilterState();
				entriesDirty = true;
			}
			GUILayout.FlexibleSpace();
			GUILayout.Label(GetDisabledCountLabel(), filterLabelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			EnsureEntries();
			GUILayout.Label("Showing " + cachedEntries.Count + " matching items · " + GetEnabledContentCount(filterTab) + " enabled in total", filterSmallLabelStyle, Array.Empty<GUILayoutOption>());
			if (GetEnabledContentCount(filterTab) == 0)
			{
				GUILayout.Label("WARNING: all " + ((filterTab == 0) ? "factions" : "campaigns") + " are disabled. Roguelike may have nothing to select.", filterSmallLabelStyle, Array.Empty<GUILayoutOption>());
			}
			contentScroll = GUILayout.BeginScrollView(contentScroll, false, true, filterHorizontalScrollbarStyle, filterVerticalScrollbarStyle, filterScrollViewStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			if (cachedEntries.Count == 0)
			{
				GUILayout.Label("No matching content found.", filterLabelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				foreach (FilterEntry cachedEntry2 in cachedEntries)
				{
					GUILayout.BeginHorizontal(filterPanelStyle, Array.Empty<GUILayoutOption>());
					bool disabled = cachedEntry2.Disabled;
					bool flag4 = GUILayout.Toggle(disabled, string.Empty, filterCheckboxStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(32f),
						GUILayout.Height(28f)
					});
					if (flag4 != disabled)
					{
						SetEntryDisabled(cachedEntry2.Id, flag4);
						cachedEntry2.Disabled = flag4;
						SaveFilterState();
					}
					GUILayout.Label(GetSourceTag(cachedEntry2.Source) + cachedEntry2.Name, filterLabelStyle, Array.Empty<GUILayoutOption>());
					GUILayout.FlexibleSpace();
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUI.DragWindow(new Rect(0f, 0f, 760f, 24f));
		}

		private static string GetDisabledCountLabel()
		{
			return "Disabled: " + ((filterTab == 0) ? filterState.DisabledFactionIds.Count : filterState.DisabledCampaignIds.Count);
		}

		private static void EnsureEntries()
		{
			if (entriesDirty)
			{
				cachedEntries = ((filterTab == 0) ? BuildFactionEntries() : BuildCampaignEntries());
				entriesDirty = false;
			}
		}

		private static List<FilterEntry> BuildFactionEntries()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			List<FilterEntry> list = new List<FilterEntry>();
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return list;
			}
			IEnumerable<Faction> allFactions = val.GetAllFactions();
			if (allFactions == null)
			{
				return list;
			}
			HashSet<DatabaseID> userContentIds = GetUserContentIds(val, "GetUserFactions");
			HashSet<DatabaseID> vanillaFactionIds = GetVanillaFactionIds(val);
			foreach (Faction item in allFactions)
			{
				if (!((Object)(object)item == (Object)null) && item.Entity != null && item.m_displayFaction)
				{
					string text = IdToStringCompat(item.Entity.GUID);
					list.Add(new FilterEntry
					{
						Id = text,
						Name = GetDisplayName(item),
						Source = GetFactionContentSource(item, userContentIds.Contains(item.Entity.GUID), vanillaFactionIds.Contains(item.Entity.GUID)),
						Disabled = filterState.DisabledFactionIds.Contains(text)
					});
				}
			}
			return FilterEntries(list);
		}

		private static HashSet<DatabaseID> GetUserContentIds(ContentDatabase db, string methodName)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			HashSet<DatabaseID> hashSet = new HashSet<DatabaseID>();
			foreach (object item in EnumerateDatabaseMethod(db, methodName))
			{
				if (TryGetDatabaseId(item, out var id))
				{
					hashSet.Add(id);
				}
			}
			return hashSet;
		}

		private static List<FilterEntry> BuildCampaignEntries()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			List<FilterEntry> list = new List<FilterEntry>();
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return list;
			}
			HashSet<DatabaseID> userContentIds = GetUserContentIds(val, "GetUserCampaigns");
			HashSet<DatabaseID> vanillaCampaignIds = GetVanillaCampaignIds(val);
			foreach (CampaignInfo campaignInfo in GetCampaignInfos(val))
			{
				string text = IdToStringCompat(campaignInfo.Id);
				list.Add(new FilterEntry
				{
					Id = text,
					Name = campaignInfo.Name,
					Source = GetCampaignContentSource(campaignInfo, userContentIds.Contains(campaignInfo.Id), vanillaCampaignIds.Contains(campaignInfo.Id)),
					Disabled = filterState.DisabledCampaignIds.Contains(text)
				});
			}
			return FilterEntries(list);
		}

		private static List<FilterEntry> FilterEntries(List<FilterEntry> entries)
		{
			entries = entries.Where((FilterEntry e) => (e.Source == ContentSource.Vanilla && showVanilla) || (e.Source == ContentSource.Mod && showMod) || (e.Source == ContentSource.Custom && showCustom)).ToList();
			string query = (searchText ?? string.Empty).Trim();
			if (!string.IsNullOrEmpty(query))
			{
				entries = entries.Where((FilterEntry e) => e.Name.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0 || e.Id.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
			}
			return entries.OrderBy((FilterEntry e) => e.Source).ThenBy<FilterEntry, string>((FilterEntry e) => e.Name, StringComparer.OrdinalIgnoreCase).ToList();
		}

		private static int GetEnabledContentCount(int tab)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return 0;
			}
			if (tab == 0)
			{
				int num = 0;
				{
					foreach (Faction allFaction in val.GetAllFactions())
					{
						if (!((Object)(object)allFaction == (Object)null) && allFaction.Entity != null && allFaction.m_displayFaction && !filterState.DisabledFactionIds.Contains(IdToStringCompat(allFaction.Entity.GUID)))
						{
							num++;
						}
					}
					return num;
				}
			}
			int num2 = 0;
			foreach (CampaignInfo campaignInfo in GetCampaignInfos(val))
			{
				if (!filterState.DisabledCampaignIds.Contains(IdToStringCompat(campaignInfo.Id)))
				{
					num2++;
				}
			}
			return num2;
		}

		private static void SetEntryDisabled(string id, bool disabled)
		{
			HashSet<string> hashSet = ((filterTab == 0) ? filterState.DisabledFactionIds : filterState.DisabledCampaignIds);
			if (disabled)
			{
				hashSet.Add(id);
			}
			else
			{
				hashSet.Remove(id);
			}
		}

		private static HashSet<DatabaseID> GetVanillaFactionIds(ContentDatabase db)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			HashSet<DatabaseID> hashSet = new HashSet<DatabaseID>();
			if (db == null || db.LandfallContentDatabase == null)
			{
				return hashSet;
			}
			try
			{
				IEnumerable<Faction> factions = db.LandfallContentDatabase.GetFactions();
				if (factions != null)
				{
					foreach (Faction item in factions)
					{
						if ((Object)(object)item != (Object)null && item.Entity != null)
						{
							hashSet.Add(item.Entity.GUID);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[CustomContentRoguelike] Could not enumerate vanilla factions: " + ex.Message));
			}
			return hashSet;
		}

		private static HashSet<DatabaseID> GetVanillaCampaignIds(ContentDatabase db)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			HashSet<DatabaseID> hashSet = new HashSet<DatabaseID>();
			if (db == null)
			{
				return hashSet;
			}
			try
			{
				foreach (object item in EnumerateDatabaseMethod(db, "GetAllCampaigns"))
				{
					if (TryGetDatabaseId(item, out var id))
					{
						hashSet.Add(id);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[CustomContentRoguelike] Could not enumerate vanilla campaigns: " + ex.Message));
			}
			return hashSet;
		}

		private static bool? TryGetBoolMember(object obj, string memberName)
		{
			if (obj == null)
			{
				return null;
			}
			object memberValue = GetMemberValue(obj, memberName);
			if (memberValue is bool)
			{
				return (bool)memberValue;
			}
			return null;
		}

		private static ContentSource GetFactionContentSource(Faction faction, bool isUserContent, bool isLandfallContent)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			DatabaseEntity val = (((Object)(object)faction != (Object)null) ? faction.Entity : null);
			if (isUserContent || TryGetBoolMember(faction, "IsCustom") == true)
			{
				return ContentSource.Custom;
			}
			int num = ((val != null) ? val.GUID.m_modID : 0);
			switch (num)
			{
			case -1:
				return ContentSource.Vanilla;
			case -2:
				return ContentSource.Mod;
			default:
			{
				bool? flag = TryGetBoolMember(faction, "IsModFaction");
				if (!flag.HasValue)
				{
					flag = TryGetBoolMember(val, "IsModFaction");
				}
				if (flag == true)
				{
					return ContentSource.Mod;
				}
				ContentSource? contentSource = TryGetEntityContentSource(val);
				if (contentSource.HasValue)
				{
					return contentSource.Value;
				}
				if (num != 0)
				{
					return ContentSource.Mod;
				}
				if (isLandfallContent)
				{
					return ContentSource.Vanilla;
				}
				return ContentSource.Mod;
			}
			}
		}

		private static ContentSource GetCampaignContentSource(CampaignInfo campaign, bool isUserContent, bool isLandfallContent)
		{
			//IL_0037: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			object obj = campaign?.RawObject;
			bool? flag = TryGetBoolMember(obj, "IsCustomCampaign");
			if (isUserContent || flag == true)
			{
				return ContentSource.Custom;
			}
			DatabaseID val = (DatabaseID)(((??)campaign?.Id) ?? default(DatabaseID));
			if (val.m_modID == -1)
			{
				return ContentSource.Vanilla;
			}
			if (val.m_modID == -2)
			{
				return ContentSource.Mod;
			}
			bool? flag2 = TryGetBoolMember(obj, "IsModCampaign");
			if (!flag2.HasValue)
			{
				flag2 = TryGetBoolMember(GetMemberValue(obj, "Entity"), "IsModCampaign");
			}
			if (flag2 == true)
			{
				return ContentSource.Mod;
			}
			ContentSource? contentSource = TryGetEntityContentSource(GetMemberValue(obj, "Entity"));
			if (contentSource.HasValue)
			{
				return contentSource.Value;
			}
			if (val.m_modID != 0)
			{
				return ContentSource.Mod;
			}
			if (isLandfallContent)
			{
				return ContentSource.Vanilla;
			}
			return ContentSource.Mod;
		}

		private static ContentSource? TryGetEntityContentSource(object entity)
		{
			if (entity == null)
			{
				return null;
			}
			string[] array = new string[4] { "ContentType", "WorkshopContentType", "m_entityContentType", "m_workshopContentType" };
			foreach (string memberName in array)
			{
				object memberValue = GetMemberValue(entity, memberName);
				if (memberValue == null)
				{
					continue;
				}
				string text = memberValue.ToString();
				if (!string.IsNullOrEmpty(text))
				{
					if (text.IndexOf("Mod", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return ContentSource.Mod;
					}
					if (text.IndexOf("Landfall", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Vanilla", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Default", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return ContentSource.Vanilla;
					}
				}
			}
			return null;
		}

		private static void DumpContentClassificationDiagnostics()
		{
			//IL_00dc: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ContentDatabase val = ContentDatabase.Instance();
				if (val == null)
				{
					LoggerStatic("[CLASSIFY2] ContentDatabase.Instance() returned NULL.");
					return;
				}
				HashSet<DatabaseID> userContentIds = GetUserContentIds(val, "GetUserFactions");
				HashSet<DatabaseID> vanillaFactionIds = GetVanillaFactionIds(val);
				IEnumerable<Faction> enumerable = val.GetAllFactions() ?? Array.Empty<Faction>();
				LoggerStatic("[CLASSIFY2] ===== FACTION DIAGNOSTICS =====");
				LoggerStatic("[CLASSIFY2] total=" + enumerable.Count() + " user=" + userContentIds.Count + " vanilla=" + vanillaFactionIds.Count);
				int num = 0;
				foreach (Faction item in enumerable)
				{
					if (!((Object)(object)item == (Object)null) && item.Entity != null && item.m_displayFaction)
					{
						DatabaseID gUID = item.Entity.GUID;
						bool isUser = userContentIds.Contains(gUID);
						bool isVanillaDb = vanillaFactionIds.Contains(gUID);
						if (num < 120)
						{
							LogDeepClassification("Faction", GetDisplayName(item), item, item.Entity, isUser, isVanillaDb);
							num++;
						}
					}
				}
				LoggerStatic("[CLASSIFY2] ===== CAMPAIGN DIAGNOSTICS =====");
				HashSet<DatabaseID> userContentIds2 = GetUserContentIds(val, "GetUserCampaigns");
				HashSet<DatabaseID> vanillaCampaignIds = GetVanillaCampaignIds(val);
				int num2 = 0;
				foreach (CampaignInfo campaignInfo in GetCampaignInfos(val))
				{
					bool isUser2 = userContentIds2.Contains(campaignInfo.Id);
					bool isVanillaDb2 = vanillaCampaignIds.Contains(campaignInfo.Id);
					if (num2 < 100)
					{
						object memberValue = GetMemberValue(campaignInfo.RawObject, "Entity");
						LogDeepClassification("Campaign", campaignInfo.Name, campaignInfo.RawObject, memberValue, isUser2, isVanillaDb2);
						num2++;
					}
				}
				LoggerStatic("[CLASSIFY2] ===== END DIAGNOSTICS =====");
			}
			catch (Exception ex)
			{
				LoggerStatic("[CLASSIFY2] Diagnostics failed: " + ex);
			}
		}

		private static void LogDeepClassification(string kind, string name, object owner, object entity, bool isUser, bool isVanillaDb)
		{
			try
			{
				object obj = ((entity != null) ? GetMemberValue(entity, "GUID") : null);
				object obj2 = ((obj != null) ? GetMemberValue(obj, "m_modID") : null);
				LoggerStatic("[CLASSIFY2] " + kind + " | " + name + " | guid=" + obj?.ToString() + " | modID=" + obj2?.ToString() + " | user=" + isUser + " | vanillaDB=" + isVanillaDb);
				DumpInterestingMembers("owner", owner);
				DumpInterestingMembers("entity", entity);
				if (IsDeepDiagnosticSample(kind, name))
				{
					LoggerStatic("[CLASSIFY2] ===== DEEP REFLECTION " + kind + " | " + name + " =====");
					DumpAllReflectedMembers("owner", owner);
					DumpAllReflectedMembers("entity", entity);
					if (entity != null)
					{
						DumpAllReflectedMembers("guid", GetMemberValue(entity, "GUID"));
					}
					LoggerStatic("[CLASSIFY2] ===== END DEEP REFLECTION " + kind + " | " + name + " =====");
				}
			}
			catch (Exception ex)
			{
				LoggerStatic("[CLASSIFY2] Failed to inspect " + kind + " " + name + ": " + ex.Message);
			}
		}

		private static bool IsDeepDiagnosticSample(string kind, string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (kind == "Faction")
			{
				if (!name.Equals("Tribal", StringComparison.OrdinalIgnoreCase) && !name.Equals("HiddenUnits", StringComparison.OrdinalIgnoreCase))
				{
					return name.Equals("Стоунпанк (почти)", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			if (kind == "Campaign")
			{
				if (!name.Equals("CAMPAIGN_01_THE_INTRODUCTION", StringComparison.OrdinalIgnoreCase) && !name.Equals("Egypt", StringComparison.OrdinalIgnoreCase))
				{
					return name.Equals("Стоунпанк (почти)", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}

		private static void DumpAllReflectedMembers(string label, object obj)
		{
			if (obj == null)
			{
				LoggerStatic("[CLASSIFY2]   deep." + label + "=NULL");
				return;
			}
			Type type = obj.GetType();
			LoggerStatic("[CLASSIFY2]   deep." + label + ".type=" + type.FullName);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			Type type2 = type;
			while (type2 != null)
			{
				FieldInfo[] array;
				try
				{
					array = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					array = Array.Empty<FieldInfo>();
				}
				FieldInfo[] array2 = array;
				foreach (FieldInfo fieldInfo in array2)
				{
					if (hashSet.Add("F:" + fieldInfo.Name))
					{
						try
						{
							object value = fieldInfo.GetValue(obj);
							LoggerStatic("[CLASSIFY2]   deep." + label + ".field " + type2.Name + "." + fieldInfo.Name + "=" + DescribeMemberValue(value));
						}
						catch (Exception ex)
						{
							LoggerStatic("[CLASSIFY2]   deep." + label + ".field " + type2.Name + "." + fieldInfo.Name + "=<THREW " + ex.GetBaseException().GetType().Name + ">");
						}
					}
				}
				PropertyInfo[] array3;
				try
				{
					array3 = type2.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					array3 = Array.Empty<PropertyInfo>();
				}
				PropertyInfo[] array4 = array3;
				foreach (PropertyInfo propertyInfo in array4)
				{
					if (hashSet.Add("P:" + propertyInfo.Name) && propertyInfo.GetIndexParameters().Length == 0 && !(propertyInfo.GetGetMethod(nonPublic: true) == null))
					{
						try
						{
							object value2 = propertyInfo.GetValue(obj, null);
							LoggerStatic("[CLASSIFY2]   deep." + label + ".property " + type2.Name + "." + propertyInfo.Name + "=" + DescribeMemberValue(value2));
						}
						catch (Exception ex2)
						{
							LoggerStatic("[CLASSIFY2]   deep." + label + ".property " + type2.Name + "." + propertyInfo.Name + "=<THREW " + ex2.GetBaseException().GetType().Name + ">");
						}
					}
				}
				MethodInfo[] array5;
				try
				{
					array5 = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					array5 = Array.Empty<MethodInfo>();
				}
				MethodInfo[] array6 = array5;
				foreach (MethodInfo methodInfo in array6)
				{
					string name = methodInfo.Name;
					if (name.IndexOf("mod", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("profile", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("content", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("workshop", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("source", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						string text = name + "(" + string.Join(",", (from p in methodInfo.GetParameters()
							select p.ParameterType.Name).ToArray()) + ")";
						if (hashSet.Add("M:" + text))
						{
							LoggerStatic("[CLASSIFY2]   deep." + label + ".method " + type2.Name + "." + text);
						}
					}
				}
				type2 = type2.BaseType;
			}
		}

		private static string DescribeMemberValue(object value)
		{
			if (value == null)
			{
				return "NULL";
			}
			Type type = value.GetType();
			if (type.IsEnum || value is string || value is bool || value is byte || value is sbyte || value is short || value is ushort || value is int || value is uint || value is long || value is ulong || value is float || value is double || value is decimal || value is Guid)
			{
				return value?.ToString() + " [" + type.FullName + "]";
			}
			if (type.IsValueType)
			{
				return value?.ToString() + " [" + type.FullName + "]";
			}
			if (value is ICollection collection)
			{
				return "<collection count=" + collection.Count + " type=" + type.FullName + ">";
			}
			return "<object type=" + type.FullName + ">";
		}

		private static void DumpInterestingMembers(string label, object obj)
		{
			if (obj == null)
			{
				LoggerStatic("[CLASSIFY2]   " + label + "=NULL");
				return;
			}
			Type type = obj.GetType();
			string[] array = new string[12]
			{
				"ModProfile", "modProfile", "m_modProfile", "ContentType", "WorkshopContentType", "m_entityContentType", "m_workshopContentType", "IsModFaction", "IsModCampaign", "IsMod",
				"ModID", "m_modID"
			};
			foreach (string text in array)
			{
				try
				{
					object memberValue = GetMemberValue(obj, text);
					if (memberValue != null)
					{
						LoggerStatic("[CLASSIFY2]   " + label + "." + text + "=" + DescribeRaw(memberValue));
					}
				}
				catch
				{
				}
			}
			array = new string[2] { "GetModProfile", "GetContentTypeFromModProfile" };
			foreach (string text2 in array)
			{
				try
				{
					MethodInfo method = type.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
					if (method != null)
					{
						object value = method.Invoke(obj, null);
						LoggerStatic("[CLASSIFY2]   " + label + "." + text2 + "()=" + DescribeRaw(value));
					}
				}
				catch (Exception ex)
				{
					LoggerStatic("[CLASSIFY2]   " + label + "." + text2 + "()=THREW " + ex.GetBaseException().Message);
				}
			}
		}

		private static string DescribeRaw(object value)
		{
			if (value == null)
			{
				return "NULL";
			}
			try
			{
				return value?.ToString() + " (" + Convert.ToInt32(value) + ") [" + value.GetType().FullName + "]";
			}
			catch
			{
				return value?.ToString() + " [" + value.GetType().FullName + "]";
			}
		}

		private static string GetSourceTag(ContentSource source)
		{
			return source switch
			{
				ContentSource.Custom => "[Custom] ", 
				ContentSource.Mod => "[Mod] ", 
				_ => "[Vanilla] ", 
			};
		}

		private static void LoadFilterState()
		{
			Plugin.filterState = new FilterState();
			try
			{
				if (!File.Exists(FilterStatePath))
				{
					return;
				}
				byte[] array = File.ReadAllBytes(FilterStatePath);
				if (array.Length != 0)
				{
					FilterState filterState = SerializationUtility.DeserializeValue<FilterState>(array, (DataFormat)0, (DeserializationContext)null);
					if (filterState != null)
					{
						Plugin.filterState = filterState;
					}
					Plugin.filterState.DisabledFactionIds = Plugin.filterState.DisabledFactionIds ?? new HashSet<string>();
					Plugin.filterState.DisabledCampaignIds = Plugin.filterState.DisabledCampaignIds ?? new HashSet<string>();
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[CustomContentRoguelike] Could not load filter state: " + ex.Message));
				Plugin.filterState = new FilterState();
			}
		}

		private static void SaveFilterState()
		{
			try
			{
				Directory.CreateDirectory(Paths.ConfigPath);
				byte[] bytes = SerializationUtility.SerializeValue<FilterState>(filterState, (DataFormat)0, (SerializationContext)null);
				File.WriteAllBytes(FilterStatePath, bytes);
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[CustomContentRoguelike] Could not save filter state: " + ex.Message));
			}
		}

		private static void PatchPlayableFactions(Harmony harmony)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("RoguelikeMode.Roguelike.FactionLookup");
			if (type == null)
			{
				throw new Exception("Could not find FactionLookup");
			}
			MethodInfo methodInfo = AccessTools.Method(type, "PlayableFactions", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new Exception("Could not find PlayableFactions");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "PlayableFactionsPrefix", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool PlayableFactionsPrefix(ref IEnumerable<Faction> __result)
		{
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				__result = Enumerable.Empty<Faction>();
				return false;
			}
			__result = from f in val.GetAllFactions().Where(IsPlayableFactionCompat)
				where !IsFactionDisabled(f)
				select f;
			return false;
		}

		private static bool IsPlayableFactionCompat(Faction faction)
		{
			if ((Object)(object)faction == (Object)null || faction.Entity == null || !faction.m_displayFaction)
			{
				return false;
			}
			string name = faction.Entity.Name;
			if (name == null || !name.StartsWith("FACTION_"))
			{
				return IsModFactionCompat(faction);
			}
			return true;
		}

		private static bool IsModFactionCompat(Faction faction)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)faction != (Object)null && faction.Entity != null)
			{
				return faction.Entity.GUID.m_modID != 0;
			}
			return false;
		}

		private static bool IsFactionDisabled(Faction faction)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)faction != (Object)null && faction.Entity != null)
			{
				return filterState.DisabledFactionIds.Contains(IdToStringCompat(faction.Entity.GUID));
			}
			return false;
		}

		private static bool PatchDominantFaction(TABSCampaignLevelAsset level, ref Faction __result)
		{
			__result = FindDominantFactionCompat(level);
			return false;
		}

		private static Faction FindDominantFactionCompat(TABSCampaignLevelAsset level)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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)
			if ((Object)(object)level == (Object)null || level.Entity == null || level.BlueUnits == null)
			{
				return null;
			}
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return null;
			}
			Dictionary<DatabaseID, long> totals = new Dictionary<DatabaseID, long>();
			Dictionary<DatabaseID, Faction> dictionary = new Dictionary<DatabaseID, Faction>();
			TABSLayoutUnit[] blueUnits = level.BlueUnits;
			foreach (TABSLayoutUnit val2 in blueUnits)
			{
				if (val2 == null || (Object)(object)val2.m_unitBlueprint == (Object)null || val2.m_unitBlueprint.Entity == null)
				{
					continue;
				}
				IEnumerable<Faction> factionsByUnit = val.GetFactionsByUnit(val2.m_unitBlueprint.Entity.GUID);
				if (factionsByUnit == null)
				{
					continue;
				}
				Faction val3 = ((IEnumerable<Faction>)(from f in factionsByUnit
					where (Object)(object)f != (Object)null && f.Entity != null && f.m_displayFaction
					orderby f.index
					select f)).FirstOrDefault((Func<Faction, bool>)IsPlayableFactionCompat);
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = (from f in factionsByUnit
						where (Object)(object)f != (Object)null && f.Entity != null && f.m_displayFaction
						orderby f.index
						select f).FirstOrDefault();
				}
				if (!((Object)(object)val3 == (Object)null) && val3.Entity != null)
				{
					DatabaseID gUID = val3.Entity.GUID;
					dictionary[gUID] = val3;
					totals.TryGetValue(gUID, out var value);
					totals[gUID] = value + val2.m_unitBlueprint.GetUnitCost(true);
				}
			}
			return (from f in dictionary.Values
				orderby totals[f.Entity.GUID] descending, f.index
				select f).FirstOrDefault();
		}

		private static bool PatchPrimaryFactionForUnit(UnitBlueprint unit, ref Faction __result)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)unit == (Object)null || unit.Entity == null)
			{
				return true;
			}
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return true;
			}
			IEnumerable<Faction> factionsByUnit = val.GetFactionsByUnit(unit.Entity.GUID);
			if (factionsByUnit == null)
			{
				__result = null;
				return false;
			}
			List<Faction> source = (from f in factionsByUnit
				where (Object)(object)f != (Object)null && f.Entity != null && f.m_displayFaction && !IsFactionDisabled(f)
				orderby f.index
				select f).ToList();
			__result = ((IEnumerable<Faction>)source).FirstOrDefault((Func<Faction, bool>)IsPlayableFactionCompat) ?? source.FirstOrDefault();
			return false;
		}

		private static bool PatchLevelIconLoader(TABSCampaignLevelAsset level, ref Action<Action<Sprite>> __result)
		{
			__result = delegate(Action<Sprite> callback)
			{
				if (callback != null)
				{
					Sprite val = null;
					if ((Object)(object)level != (Object)null && level.Entity != null)
					{
						val = level.Entity.LevelCellSpriteIcon;
					}
					if ((Object)(object)val != (Object)null)
					{
						callback(val);
					}
					else
					{
						Sprite questionSprite = GetQuestionSprite();
						if ((Object)(object)questionSprite != (Object)null)
						{
							callback(questionSprite);
						}
						if (!((Object)(object)level == (Object)null) && level.Entity != null)
						{
							try
							{
								level.Entity.GetSpriteIconAsync((Action<Sprite>)delegate(Sprite sprite)
								{
									if ((Object)(object)sprite != (Object)null)
									{
										callback(sprite);
									}
								});
							}
							catch (Exception ex)
							{
								Debug.LogWarning((object)("[CustomContentRoguelike] Could not load level icon: " + ex.Message));
							}
						}
					}
				}
			};
			return false;
		}

		private static Sprite GetQuestionSprite()
		{
			Type type = AccessTools.TypeByName("RoguelikeMode.Roguelike.UI.GlyphBackdrop");
			if (type == null)
			{
				return null;
			}
			PropertyInfo propertyInfo = AccessTools.Property(type, "QuestionSprite");
			if (propertyInfo == null)
			{
				return null;
			}
			try
			{
				object? value = propertyInfo.GetValue(null, null);
				return (Sprite)((value is Sprite) ? value : null);
			}
			catch
			{
				return null;
			}
		}

		private static void PatchLevelPoolBuildDifficultyIndex(Harmony harmony)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("RoguelikeMode.Roguelike.LevelPool");
			if (type == null)
			{
				throw new Exception("Could not find RoguelikeMode.Roguelike.LevelPool");
			}
			MethodInfo methodInfo = AccessTools.Method(type, "BuildDifficultyIndex", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new Exception("Could not find LevelPool.BuildDifficultyIndex");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "BuildDifficultyIndexPrefix", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void PatchPrefix(Harmony harmony, string typeName, string methodName, string prefixName)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				throw new Exception("Could not find type: " + typeName);
			}
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new Exception("Could not find method: " + typeName + "." + methodName);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), prefixName, (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void Patch(Harmony harmony, string typeName, string methodName, string transpilerName)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				throw new Exception("Could not find type: " + typeName);
			}
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new Exception("Could not find method: " + typeName + "." + methodName);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), transpilerName, (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static IEnumerable<CodeInstruction> PatchGetUnitFromRosters(IEnumerable<CodeInstruction> instructions)
		{
			return ReplaceInstanceCall(instructions, typeof(LandfallContentDatabase), "GetFactions", typeof(ContentDatabase), "GetAllFactions");
		}

		private static bool PatchGetLevel(string id, ref TABSCampaignLevelAsset __result)
		{
			__result = FindCampaignLevelCompat(id);
			return false;
		}

		private static TABSCampaignLevelAsset FindCampaignLevelCompat(string id)
		{
			//IL_001d: 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)
			if (!TryParseDatabaseIdCompat(id, out var result))
			{
				return null;
			}
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return null;
			}
			TABSCampaignLevelAsset val2 = FindLevelIn(val.GetAllLandfallCampaignLevels(), result);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			return FindLevelIn(val.GetUserCampaignLevels(), result);
		}

		private static TABSCampaignLevelAsset FindLevelIn(IEnumerable<TABSCampaignLevelAsset> levels, DatabaseID guid)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (levels == null)
			{
				return null;
			}
			foreach (TABSCampaignLevelAsset level in levels)
			{
				if ((Object)(object)level != (Object)null && level.Entity != null && level.Entity.GUID == guid)
				{
					return level;
				}
			}
			return null;
		}

		private static bool TryParseDatabaseIdCompat(string id, out DatabaseID result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			result = default(DatabaseID);
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			string[] array = id.Split(new char[1] { ':' });
			if (array.Length != 2)
			{
				return false;
			}
			if (!int.TryParse(array[0], out var result2) || !int.TryParse(array[1], out var result3))
			{
				return false;
			}
			result = new DatabaseID(result2, result3);
			return true;
		}

		private static bool PatchEligibleUnits(Faction faction, HashSet<DatabaseID> seen, ref IEnumerable<UnitBlueprint> __result)
		{
			if ((Object)(object)faction != (Object)null && faction.Units != null && faction.Units.Length != 0)
			{
				return true;
			}
			__result = EnumerateFactionUnitsCompat(faction, seen);
			return false;
		}

		private static IEnumerable<UnitBlueprint> EnumerateFactionUnitsCompat(Faction faction, HashSet<DatabaseID> seen)
		{
			if ((Object)(object)faction == (Object)null || faction.Entity == null)
			{
				yield break;
			}
			ContentDatabase db = ContentDatabase.Instance();
			if (db == null)
			{
				yield break;
			}
			DatabaseID factionId = faction.Entity.GUID;
			IEnumerable<UnitBlueprint> allUnitBlueprints = db.GetAllUnitBlueprints();
			if (allUnitBlueprints == null)
			{
				yield break;
			}
			foreach (UnitBlueprint item in allUnitBlueprints)
			{
				if ((Object)(object)item == (Object)null || item.Entity == null)
				{
					continue;
				}
				DatabaseID gUID = item.Entity.GUID;
				if (seen != null && seen.Contains(gUID))
				{
					continue;
				}
				IEnumerable<Faction> factionsByUnit = db.GetFactionsByUnit(gUID);
				if (factionsByUnit == null)
				{
					continue;
				}
				bool flag = false;
				foreach (Faction item2 in factionsByUnit)
				{
					if ((Object)(object)item2 != (Object)null && item2.Entity != null && item2.Entity.GUID == factionId)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					seen?.Add(gUID);
					if (item.GetUnitCost(true) != 0)
					{
						yield return item;
					}
				}
			}
		}

		private static bool BuildDifficultyIndexPrefix()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			Type type = AccessTools.TypeByName("RoguelikeMode.Roguelike.LevelPool");
			if (type == null)
			{
				throw new Exception("Could not find RoguelikeMode.Roguelike.LevelPool");
			}
			ContentDatabase val = ContentDatabase.Instance();
			if (val == null)
			{
				return false;
			}
			List<TABSCampaignLevelAsset> list = new List<TABSCampaignLevelAsset>();
			HashSet<DatabaseID> seen = new HashSet<DatabaseID>();
			AddLevels(val.GetAllLandfallCampaignLevels(), list, seen);
			AddLevels(val.GetUserCampaignLevels(), list, seen);
			Dictionary<DatabaseID, List<DatabaseID>> membership = BuildCampaignMembershipIndex(val);
			List<LevelDifficultyEntry> list2 = new List<LevelDifficultyEntry>();
			int num = 0;
			int num2 = 0;
			foreach (TABSCampaignLevelAsset item in list)
			{
				if (!((Object)(object)item == (Object)null) && item.Entity != null)
				{
					if (!HasEnemyArmy(item))
					{
						num++;
						continue;
					}
					if (IsLevelExcludedByCampaignFilter(item.Entity.GUID, membership))
					{
						num2++;
						continue;
					}
					list2.Add(new LevelDifficultyEntry
					{
						Level = item,
						Budget = item.m_budget,
						ArmyValue = ComputeArmyValueCompat(item)
					});
				}
			}
			float[] array = AverageRanks(list2.Select((LevelDifficultyEntry e) => e.Budget).ToArray());
			float[] array2 = AverageRanks(list2.Select((LevelDifficultyEntry e) => e.ArmyValue).ToArray());
			for (int num3 = 0; num3 < list2.Count; num3++)
			{
				list2[num3].Score = (array[num3] + array2[num3]) / 2f;
			}
			float[] array3 = AverageRanks(list2.Select((LevelDifficultyEntry e) => Mathf.RoundToInt(e.Score * 1000f)).ToArray());
			for (int num4 = 0; num4 < list2.Count; num4++)
			{
				list2[num4].DifficultyPercent = ((list2.Count > 1) ? Mathf.RoundToInt((array3[num4] - 1f) / (float)(list2.Count - 1) * 100f) : 0);
			}
			List<LevelDifficultyEntry> list3 = (from e in list2
				orderby e.Score, e.Level.Entity.Name
				select e).ToList();
			List<List<LevelDifficultyEntry>> list4 = new List<List<LevelDifficultyEntry>>();
			Dictionary<DatabaseID, LevelDifficultyEntry> dictionary = new Dictionary<DatabaseID, LevelDifficultyEntry>();
			List<LevelDifficultyEntry> list5 = null;
			foreach (LevelDifficultyEntry item2 in list3)
			{
				if (list5 == null || Math.Abs(list5[0].Score - item2.Score) > 0.001f)
				{
					list5 = new List<LevelDifficultyEntry>();
					list4.Add(list5);
				}
				item2.Tier = list4.Count - 1;
				list5.Add(item2);
				dictionary[item2.Level.Entity.GUID] = item2;
			}
			AccessTools.Field(type, "rankedLevels")?.SetValue(null, list3);
			AccessTools.Field(type, "difficultyTiers")?.SetValue(null, list4);
			AccessTools.Field(type, "entryByLevel")?.SetValue(null, dictionary);
			string text = "Built Roguelike level index: " + list3.Count + " levels (available content), skipped " + num + " empty levels and " + num2 + " levels from disabled campaigns.";
			if (!string.Equals(lastLevelIndexSummary, text, StringComparison.Ordinal))
			{
				LoggerStatic(text);
				lastLevelIndexSummary = text;
			}
			return false;
		}

		private static Dictionary<DatabaseID, List<DatabaseID>> BuildCampaignMembershipIndex(ContentDatabase db)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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)
			Dictionary<DatabaseID, List<DatabaseID>> dictionary = new Dictionary<DatabaseID, List<DatabaseID>>();
			foreach (CampaignInfo campaignInfo in GetCampaignInfos(db))
			{
				foreach (DatabaseID levelId in campaignInfo.LevelIds)
				{
					if (!dictionary.TryGetValue(levelId, out var value))
					{
						value = (dictionary[levelId] = new List<DatabaseID>());
					}
					if (!value.Contains(campaignInfo.Id))
					{
						value.Add(campaignInfo.Id);
					}
				}
			}
			return dictionary;
		}

		private static bool IsLevelExcludedByCampaignFilter(DatabaseID levelId, Dictionary<DatabaseID, List<DatabaseID>> membership)
		{
			//IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!membership.TryGetValue(levelId, out var value) || value.Count == 0)
			{
				return false;
			}
			foreach (DatabaseID item in value)
			{
				if (!filterState.DisabledCampaignIds.Contains(IdToStringCompat(item)))
				{
					return false;
				}
			}
			return true;
		}

		private static IEnumerable<CampaignInfo> GetCampaignInfos(ContentDatabase db)
		{
			Dictionary<DatabaseID, CampaignInfo> dictionary = new Dictionary<DatabaseID, CampaignInfo>();
			foreach (object item in EnumerateDatabaseMethod(db, "GetAllCampaigns"))
			{
				AddCampaignInfo(dictionary, item);
			}
			foreach (object item2 in EnumerateDatabaseMethod(db, "GetUserCampaigns"))
			{
				AddCampaignInfo(dictionary, item2);
			}
			return dictionary.Values;
		}

		private static IEnumerable<object> EnumerateDatabaseMethod(ContentDatabase db, string methodName)
		{
			MethodInfo methodInfo = AccessTools.Method(((object)db).GetType(), methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				yield break;
			}
			object obj;
			try
			{
				obj = methodInfo.Invoke(db, null);
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[CustomContentRoguelike] Could not read " + methodName + ": " + ex.Message));
				yield break;
			}
			if (!(obj is IEnumerable enumerable))
			{
				yield break;
			}
			foreach (object item in enumerable)
			{
				if (item != null)
				{
					yield return item;
				}
			}
		}

		private static void AddCampaignInfo(Dictionary<DatabaseID, CampaignInfo> result, object campaignObject)
		{
			//IL_0010: 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_0021: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (campaignObject == null || !TryGetDatabaseId(campaignObject, out var id))
			{
				return;
			}
			if (!result.TryGetValue(id, out var value))
			{
				value = new CampaignInfo
				{
					Id = id,
					Name = GetDisplayName(campaignObject),
					RawObject = campaignObject
				};
				result.Add(id, value);
			}
			value.RawObject = campaignObject;
			if (!(GetMemberValue(campaignObject, "LevelsInCampaign") is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item != null && TryGetDatabaseId(item, out var id2) && !value.LevelIds.Contains(id2))
				{
					value.LevelIds.Add(id2);
				}
			}
		}

		private static bool TryGetDatabaseId(object value, out DatabaseID id)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			id = default(DatabaseID);
			if (value == null)
			{
				return false;
			}
			if (GetMemberValue(GetMemberValue(value, "Entity"), "GUID") is DatabaseID val)
			{
				id = val;
				return true;
			}
			return false;
		}

		private static object GetMemberValue(object value, string memberName)
		{
			if (value == null)
			{
				return null;
			}
			Type type = value.GetType();
			PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(value, null);
			}
			FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field != null))
			{
				return null;
			}
			return field.GetValue(value);
		}

		private static string GetDisplayName(object value)
		{
			if (value == null)
			{
				return "<unknown>";
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val != (Object)null && !string.IsNullOrEmpty(val.name))
			{
				return val.name;
			}
			string text = GetMemberValue(GetMemberValue(value, "Entity"), "Name") as string;
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return value.GetType().Name;
		}

		private static string IdToStringCompat(DatabaseID id)
		{
			return id.m_modID + ":" + id.m_ID;
		}

		private static void AddLevels(IEnumerable<TABSCampaignLevelAsset> source, List<TABSCampaignLevelAsset> destination, HashSet<DatabaseID> seen)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (source == null)
			{
				return;
			}
			foreach (TABSCampaignLevelAsset item in source)
			{
				if (!((Object)(object)item == (Object)null) && item.Entity != null && seen.Add(item.Entity.GUID))
				{
					destination.Add(item);
				}
			}
		}

		private static bool HasEnemyArmy(TABSCampaignLevelAsset level)
		{
			if ((Object)(object)level == (Object)null || level.BlueUnits == null)
			{
				return false;
			}
			TABSLayoutUnit[] blueUnits = level.BlueUnits;
			foreach (TABSLayoutUnit val in blueUnits)
			{
				if (val != null && (Object)(object)val.m_unitBlueprint != (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static int ComputeArmyValueCompat(TABSCampaignLevelAsset level)
		{
			return Mathf.Max(0, ArmyCostCompat(level, enemy: true) - ArmyCostCompat(level, enemy: false) / 2);
		}

		private static int ArmyCostCompat(TABSCampaignLevelAsset level, bool enemy)
		{
			TABSLayoutUnit[] array = (enemy ? level.BlueUnits : level.RedUnits);
			if (array == null)
			{
				return 0;
			}
			long num = 0L;
			TABSLayoutUnit[] array2 = array;
			foreach (TABSLayoutUnit val in array2)
			{
				if (val != null && (Object)(object)val.m_unitBlueprint != (Object)null)
				{
					num += val.m_unitBlueprint.GetUnitCost(true);
				}
			}
			return (int)num;
		}

		private static float[] AverageRanks(int[] values)
		{
			int[] array = (from i in Enumerable.Range(0, values.Length)
				orderby values[i]
				select i).ToArray();
			float[] array2 = new float[values.Length];
			int num = 0;
			while (num < array.Length)
			{
				int num2;
				for (num2 = num; num2 + 1 < array.Length && values[array[num2 + 1]] == values[array[num]]; num2++)
				{
				}
				float num3 = (float)(num + num2) / 2f + 1f;
				for (int num4 = num; num4 <= num2; num4++)
				{
					array2[array[num4]] = num3;
				}
				num = num2 + 1;
			}
			return array2;
		}

		private static void LoggerStatic(string message)
		{
			Debug.Log((object)("[CustomContentRoguelike] " + message));
		}

		private static IEnumerable<CodeInstruction> ReplaceInstanceCall(IEnumerable<CodeInstruction> source, Type oldOwner, string oldMethodName, Type newOwner, string newMethodName)
		{
			List<CodeInstruction> list = source.ToList();
			MethodInfo methodInfo = AccessTools.Method(oldOwner, oldMethodName, (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(newOwner, newMethodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new Exception("Old method not found: " + oldOwner.FullName + "." + oldMethodName);
			}
			if (methodInfo2 == null)
			{
				throw new Exception("New method not found: " + newOwner.FullName + "." + newMethodName);
			}
			bool flag = false;
			for (int i = 0; i < list.Count; i++)
			{
				if (!CodeInstructionExtensions.Calls(list[i], methodInfo))
				{
					continue;
				}
				if (i > 0)
				{
					MethodInfo methodInfo3 = list[i - 1].operand as MethodInfo;
					if (methodInfo3 != null && methodInfo3.Name == "get_LandfallContentDatabase" && methodInfo3.DeclaringType == typeof(ContentDatabase))
					{
						list.RemoveAt(i - 1);
						i--;
					}
				}
				list[i].opcode = OpCodes.Call;
				list[i].operand = methodInfo2;
				flag = true;
				break;
			}
			if (!flag)
			{
				throw new Exception("Could not find call " + oldOwner.FullName + "." + oldMethodName + " in target method.");
			}
			return list;
		}
	}
}