Decompiled source of RealmMix v1.0.1

plugins/RealmMix.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("RealmMix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+59942507d246a95a40fc32d9b420ea14320890be")]
[assembly: AssemblyProduct("RealmMix")]
[assembly: AssemblyTitle("RealmMix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 RealmMix
{
	internal static class HostConfig
	{
		private static ConfigFile cfg;

		private static string messageName;

		private static string[] personal;

		private static Dictionary<string, string> whenHostLacksMod;

		private static Func<bool> active;

		private static HandleNamedMessageDelegate handler;

		private static IntPtr registeredOn;

		private static float nextSend;

		private static float joinedAt;

		private static string lastSent;

		private static string lastApplied;

		private static bool overriding;

		private static bool heardFromHost;

		private static bool warnedMissing;

		private static bool savedFlag;

		private static bool savingPersonal;

		private static readonly Dictionary<ConfigEntryBase, string> originals = new Dictionary<ConfigEntryBase, string>();

		internal static bool FromHost
		{
			get
			{
				if (overriding)
				{
					return heardFromHost;
				}
				return false;
			}
		}

		internal static void Init(BasePlugin plugin, string guid, string[] personalKeys, Dictionary<string, string> offWithoutHost, Func<bool> isActive = null)
		{
			cfg = plugin.Config;
			messageName = guid + ".HostConfig";
			personal = personalKeys ?? Array.Empty<string>();
			whenHostLacksMod = offWithoutHost ?? new Dictionary<string, string>();
			active = isActive;
			cfg.SettingChanged += OnSettingChanged;
			plugin.AddComponent<HostConfigRunner>();
		}

		private static void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			try
			{
				if (overriding && !savingPersonal && IsPersonal(e.ChangedSetting.Definition))
				{
					SavePersonal();
				}
			}
			catch
			{
			}
		}

		private static string Id(ConfigDefinition d)
		{
			return d.Section + "." + d.Key;
		}

		private static bool IsPersonal(ConfigDefinition d)
		{
			string[] array = personal;
			foreach (string text in array)
			{
				if (text.EndsWith(".*") ? (d.Section == text.Substring(0, text.Length - 2)) : (Id(d) == text))
				{
					return true;
				}
			}
			return false;
		}

		internal static void Tick()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				bool flag = (Object)(object)singleton != (Object)null && singleton.IsListening;
				if (!flag || singleton.IsServer || (active != null && !active()))
				{
					if (overriding)
					{
						Restore();
					}
					if (flag && singleton.IsServer)
					{
						HostTick(singleton);
					}
					if (!flag)
					{
						registeredOn = IntPtr.Zero;
					}
				}
				else
				{
					ClientTick(singleton);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(15, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Host settings: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val);
			}
		}

		private static void HostTick(NetworkManager nm)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime < nextSend || nm.CustomMessagingManager == null)
			{
				return;
			}
			nextSend = Time.unscaledTime + 1.5f;
			List<string> list = new List<string>();
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in cfg)
			{
				if (!IsPersonal(item.Key))
				{
					list.Add(item.Key.Section + "\u001f" + item.Key.Key + "\u001f" + item.Value.GetSerializedValue());
				}
			}
			string text = string.Join("\u001e", list);
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(text.Length * 2 + 64, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
				nm.CustomMessagingManager.SendNamedMessageToAll(messageName, val, (NetworkDelivery)4);
			}
			finally
			{
				((FastBufferWriter)(ref val)).Dispose();
			}
			if (text != lastSent)
			{
				lastSent = text;
				Plugin.Log.LogInfo((object)"Sending this game's settings to all players.");
			}
		}

		private static void ClientTick(NetworkManager nm)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			CustomMessagingManager customMessagingManager = nm.CustomMessagingManager;
			if (customMessagingManager != null && registeredOn != ((Il2CppObjectBase)customMessagingManager).Pointer)
			{
				if (handler == null)
				{
					handler = DelegateSupport.ConvertDelegate<HandleNamedMessageDelegate>((Delegate)new Action<ulong, FastBufferReader>(OnReceived));
				}
				customMessagingManager.RegisterNamedMessageHandler(messageName, handler);
				registeredOn = ((Il2CppObjectBase)customMessagingManager).Pointer;
			}
			if (!overriding)
			{
				Begin();
				joinedAt = Time.unscaledTime;
				foreach (KeyValuePair<string, string> item in whenHostLacksMod)
				{
					Set(item.Key, item.Value);
				}
			}
			if (!heardFromHost && !warnedMissing && Time.unscaledTime - joinedAt > 15f)
			{
				warnedMissing = true;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(88, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No settings from the host: the host doesn't seem to have ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("RealmMix");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", so it stays off in this game.");
				}
				log.LogWarning(val);
			}
		}

		private static void OnReceived(ulong sender, FastBufferReader reader)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				if (!overriding)
				{
					Begin();
				}
				heardFromHost = true;
				if (text == lastApplied)
				{
					return;
				}
				lastApplied = text;
				int num = 0;
				string[] array = text.Split('\u001e');
				for (int i = 0; i < array.Length; i++)
				{
					string[] array2 = array[i].Split('\u001f');
					if (array2.Length == 3)
					{
						ConfigDefinition d = new ConfigDefinition(array2[0], array2[1]);
						if (!IsPersonal(d) && Set(Id(d), array2[2]))
						{
							num++;
						}
					}
				}
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using the host's settings (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" values).");
				}
				log.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Host settings (receive): ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log2.LogError(val2);
			}
		}

		private static void Begin()
		{
			overriding = true;
			heardFromHost = false;
			warnedMissing = false;
			lastApplied = null;
			savedFlag = cfg.SaveOnConfigSet;
			cfg.SaveOnConfigSet = false;
		}

		private static bool Set(string id, string value)
		{
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in cfg)
			{
				if (!(Id(item.Key) != id))
				{
					ConfigEntryBase value2 = item.Value;
					if (!originals.ContainsKey(value2))
					{
						originals[value2] = value2.GetSerializedValue();
					}
					if (value2.GetSerializedValue() != value)
					{
						value2.SetSerializedValue(value);
					}
					return true;
				}
			}
			return false;
		}

		private static void SavePersonal()
		{
			savingPersonal = true;
			Dictionary<ConfigEntryBase, string> dictionary = new Dictionary<ConfigEntryBase, string>();
			try
			{
				foreach (KeyValuePair<ConfigEntryBase, string> original in originals)
				{
					dictionary[original.Key] = original.Key.GetSerializedValue();
					original.Key.SetSerializedValue(original.Value);
				}
				cfg.Save();
			}
			finally
			{
				foreach (KeyValuePair<ConfigEntryBase, string> item in dictionary)
				{
					try
					{
						item.Key.SetSerializedValue(item.Value);
					}
					catch
					{
					}
				}
				savingPersonal = false;
			}
		}

		private static void Restore()
		{
			foreach (KeyValuePair<ConfigEntryBase, string> original in originals)
			{
				try
				{
					original.Key.SetSerializedValue(original.Value);
				}
				catch
				{
				}
			}
			originals.Clear();
			overriding = false;
			heardFromHost = false;
			lastApplied = null;
			cfg.SaveOnConfigSet = savedFlag;
			try
			{
				cfg.Save();
			}
			catch
			{
			}
			Plugin.Log.LogInfo((object)"Left the game; back to this computer's own settings.");
		}
	}
	public class HostConfigRunner : MonoBehaviour
	{
		public HostConfigRunner(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Update()
		{
			HostConfig.Tick();
		}
	}
	[HarmonyPatch]
	internal static class MixPatches
	{
		private const int Realms = 4;

		private static readonly HashSet<EnemyType> Capped = new HashSet<EnemyType>
		{
			(EnemyType)9,
			(EnemyType)31,
			(EnemyType)35,
			(EnemyType)20,
			(EnemyType)23,
			(EnemyType)21,
			(EnemyType)29,
			(EnemyType)36,
			(EnemyType)10,
			(EnemyType)19
		};

		private static readonly Dictionary<(IntPtr wave, bool variants), List<EnemyProbability>> mixed = new Dictionary<(IntPtr, bool), List<EnemyProbability>>();

		private static readonly HashSet<string> logged = new HashSet<string>();

		private static RunManager run;

		private static bool inElitePick;

		private static float nextErrorLog;

		private static bool Host
		{
			get
			{
				try
				{
					NetworkManager singleton = NetworkManager.Singleton;
					return (Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.IsServer;
				}
				catch
				{
					return true;
				}
			}
		}

		private static RunManager Run
		{
			get
			{
				if (run == null || ((Il2CppObjectBase)run).WasCollected || (Object)(object)run == (Object)null)
				{
					run = Object.FindObjectOfType<RunManager>();
				}
				return run;
			}
		}

		private static RunConfiguration ConfigFor(RunManager rm, int world)
		{
			return (RunConfiguration)(world switch
			{
				0 => rm.verdantMeadowsConfiguration, 
				1 => rm.frozenAncientsConfiguration, 
				2 => rm.pyrestormPitConfiguration, 
				3 => rm.astralPlanesConfiguration, 
				_ => null, 
			});
		}

		private static int WorldOf(RunManager rm, RunConfiguration cfg)
		{
			if ((Object)(object)cfg == (Object)null)
			{
				return -1;
			}
			for (int i = 0; i < 4; i++)
			{
				RunConfiguration val = ConfigFor(rm, i);
				if ((Object)(object)val != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)cfg).Pointer)
				{
					return i;
				}
			}
			return -1;
		}

		private static EnemyType Variant(EnemyType t, int world)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			switch (t - 4)
			{
			case 4:
				if (world != 0)
				{
					break;
				}
				return (EnemyType)32;
			case 0:
				if (world != 1)
				{
					break;
				}
				return (EnemyType)33;
			case 2:
				if (world != 2)
				{
					break;
				}
				return (EnemyType)30;
			case 5:
				if (world != 3)
				{
					break;
				}
				return (EnemyType)31;
			}
			return t;
		}

		[HarmonyPatch(typeof(RunManager), "OnDestroy")]
		[HarmonyPostfix]
		private static void RunEnded()
		{
			mixed.Clear();
			run = null;
		}

		[HarmonyPatch(typeof(RunManager), "StartRun")]
		[HarmonyPrefix]
		private static void RunStarting()
		{
			mixed.Clear();
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void WaveEnemies_Postfix(WaveConfiguration __instance, ref List<EnemyProbability> __result)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float value = Plugin.WaveMix.Value;
				if (!Plugin.Enabled.Value || value <= 0f || __result == null || !Host)
				{
					return;
				}
				bool flag = false;
				try
				{
					flag = new EnemyProbability().ShouldReplaceWithWorldSpecificVariant();
				}
				catch
				{
				}
				(IntPtr, bool) key = (((Il2CppObjectBase)__instance).Pointer, flag);
				if (mixed.TryGetValue(key, out var value2) && value2 != null)
				{
					__result = value2;
					return;
				}
				List<EnemyProbability> val = Build(__instance, __result, Math.Min(value, 1f), flag);
				if (val != null)
				{
					mixed[key] = val;
					__result = val;
				}
			}
			catch (Exception ex)
			{
				if (!(Time.unscaledTime < nextErrorLog))
				{
					nextErrorLog = Time.unscaledTime + 10f;
					ManualLogSource log = Plugin.Log;
					bool flag2 = default(bool);
					BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(15, 1, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Mixing a wave: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
					}
					log.LogError(val2);
				}
			}
		}

		private static List<EnemyProbability> Build(WaveConfiguration wave, List<EnemyProbability> own, float mix, bool variants)
		{
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Expected O, but got Unknown
			RunManager val = Run;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			RunConfiguration configuration = val.Configuration;
			int num = WorldOf(val, configuration);
			if (num < 0 || configuration.Waves == null)
			{
				return null;
			}
			int num2 = -1;
			for (int i = 0; i < configuration.Waves.Count; i++)
			{
				if ((Object)(object)configuration.Waves[i] != (Object)null && ((Il2CppObjectBase)configuration.Waves[i]).Pointer == ((Il2CppObjectBase)wave).Pointer)
				{
					num2 = i;
					break;
				}
			}
			if (num2 < 0)
			{
				return null;
			}
			double num3 = 0.0;
			for (int j = 0; j < own.Count; j++)
			{
				num3 += (double)Math.Max(0f, own[j].Probability);
			}
			if (num3 <= 0.0)
			{
				return null;
			}
			List<(int, List<EnemyProbability>, double)> list = new List<(int, List<EnemyProbability>, double)>();
			for (int k = 0; k < 4; k++)
			{
				if (k == num)
				{
					continue;
				}
				RunConfiguration val2 = ConfigFor(val, k);
				if (((val2 != null) ? val2.Waves : null) == null || val2.Waves.Count == 0)
				{
					continue;
				}
				WaveConfiguration obj = val2.Waves[Math.Min(num2, val2.Waves.Count - 1)];
				List<EnemyProbability> val3 = ((obj != null) ? obj.EnemyProbabilities : null);
				if (val3 != null)
				{
					double num4 = 0.0;
					for (int l = 0; l < val3.Count; l++)
					{
						num4 += (double)Math.Max(0f, val3[l].Probability);
					}
					if (num4 > 0.0)
					{
						list.Add((k, val3, num4));
					}
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			List<EnemyProbability> result = new List<EnemyProbability>();
			Dictionary<EnemyType, double> summary = new Dictionary<EnemyType, double>();
			for (int m = 0; m < own.Count; m++)
			{
				Add(own[m].Type, (double)own[m].Probability * (1.0 - (double)mix));
			}
			foreach (var item in list)
			{
				double num5 = num3 / item.Item3 * (double)mix / (double)list.Count;
				for (int n = 0; n < item.Item2.Count; n++)
				{
					EnemyType t = item.Item2[n].Type;
					if (variants)
					{
						t = Variant(t, item.Item1);
					}
					Add(t, (double)Math.Max(0f, item.Item2[n].Probability) * num5);
				}
			}
			List<EnemyProbability> val4 = new List<EnemyProbability>();
			for (int num6 = 0; num6 < 2; num6++)
			{
				for (int num7 = 0; num7 < result.Count; num7++)
				{
					if (Capped.Contains(result[num7].Type) == (num6 == 1))
					{
						val4.Add(result[num7]);
					}
				}
			}
			result = val4;
			if (Plugin.LogMix.Value && logged.Add($"{num}:{num2}:{variants}"))
			{
				List<string> list2 = new List<string>();
				foreach (KeyValuePair<EnemyType, double> item2 in summary)
				{
					list2.Add($"{item2.Key} {100.0 * item2.Value / num3:0}%");
				}
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(13, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Wave ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(num2 + 1);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" mixed: ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(string.Join(", ", list2));
				}
				log.LogInfo(val5);
			}
			return result;
			void Add(EnemyType val7, double p)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Expected O, but got Unknown
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				if (!(p <= 0.0))
				{
					EnemyProbability val6 = new EnemyProbability();
					val6.Type = val7;
					val6.Probability = (float)p;
					result.Add(val6);
					summary.TryGetValue(val7, out var value);
					summary[val7] = value + p;
				}
			}
		}

		[HarmonyPatch(typeof(EliteEnemyConfiguration), "GetRandomEnemy")]
		[HarmonyPostfix]
		private static void EliteEnemy_Postfix(EliteEnemyConfiguration __instance, ref EnemyType __result)
		{
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected I4, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			if (inElitePick)
			{
				return;
			}
			bool flag = default(bool);
			try
			{
				if (!Plugin.Enabled.Value || !Host || Random.value >= Plugin.EliteMix.Value)
				{
					return;
				}
				RunManager val = Run;
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				RunConfiguration configuration = val.Configuration;
				int num = WorldOf(val, configuration);
				if (num < 0 || configuration.EliteEnemies == null)
				{
					return;
				}
				int num2 = -1;
				for (int i = 0; i < configuration.EliteEnemies.Count; i++)
				{
					if ((Object)(object)configuration.EliteEnemies[i] != (Object)null && ((Il2CppObjectBase)configuration.EliteEnemies[i]).Pointer == ((Il2CppObjectBase)__instance).Pointer)
					{
						num2 = i;
						break;
					}
				}
				if (num2 < 0)
				{
					return;
				}
				List<EliteEnemyConfiguration> list = new List<EliteEnemyConfiguration>();
				for (int j = 0; j < 4; j++)
				{
					if (j == num)
					{
						continue;
					}
					RunConfiguration obj = ConfigFor(val, j);
					List<EliteEnemyConfiguration> val2 = ((obj != null) ? obj.EliteEnemies : null);
					if (val2 != null && val2.Count != 0)
					{
						EliteEnemyConfiguration val3 = val2[Math.Min(num2, val2.Count - 1)];
						if ((Object)(object)val3 != (Object)null)
						{
							list.Add(val3);
						}
					}
				}
				if (list.Count == 0)
				{
					return;
				}
				EliteEnemyConfiguration val4 = list[Random.Range(0, list.Count)];
				inElitePick = true;
				EnemyType randomEnemy;
				try
				{
					randomEnemy = val4.GetRandomEnemy();
				}
				finally
				{
					inElitePick = false;
				}
				if (Plugin.LogMix.Value)
				{
					ManualLogSource log = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(20, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Elite ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(num2 + 1);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<EnemyType>(__result);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" -> ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<EnemyType>(randomEnemy);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" (from ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)val4).name);
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(")");
					}
					log.LogInfo(val5);
				}
				__result = (EnemyType)(int)randomEnemy;
			}
			catch (Exception ex)
			{
				inElitePick = false;
				ManualLogSource log2 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val6 = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Mixing an elite: ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val6);
			}
		}

		[HarmonyPatch(typeof(EndBossObjective), "StartBossSequenceRpc")]
		[HarmonyPrefix]
		private static void BossRpc_Prefix(EndBossObjective __instance, ref BossType bossType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			try
			{
				if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1)
				{
					Boss_Pick(ref bossType);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Picking a boss: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		private static void Boss_Pick(ref BossType __result)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected I4, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			try
			{
				if (!Plugin.Enabled.Value || !Plugin.AnyBoss.Value || !Host)
				{
					return;
				}
				List<BossConfig> val = BossConfigRepository.Get();
				if (val == null || val.Count == 0)
				{
					return;
				}
				List<BossType> list = new List<BossType>();
				for (int i = 0; i < val.Count; i++)
				{
					BossConfig val2 = val[i];
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.BossPrefab != (Object)null && !list.Contains(val2.BossType))
					{
						list.Add(val2.BossType);
					}
				}
				if (list.Count == 0)
				{
					return;
				}
				BossType val3 = list[Random.Range(0, list.Count)];
				if (Plugin.LogMix.Value)
				{
					ManualLogSource log = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Boss: ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<BossType>(__result);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" -> ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<BossType>(val3);
					}
					log.LogInfo(val4);
				}
				__result = (BossType)(int)val3;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Picking a boss: ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val5);
			}
		}
	}
	[BepInPlugin("girthy_mods.RealmMix", "RealmMix", "1.0.1")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "girthy_mods.RealmMix";

		public const string Name = "RealmMix";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> WaveMix;

		internal static ConfigEntry<float> EliteMix;

		internal static ConfigEntry<bool> AnyBoss;

		internal static ConfigEntry<bool> LogMix;

		public override void Load()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			HostConfig.Init((BasePlugin)(object)this, "girthy_mods.RealmMix", new string[1] { "Debug.LogMix" }, new Dictionary<string, string> { ["Mix.Enabled"] = "false" });
			Enabled = ((BasePlugin)this).Config.Bind<bool>("Mix", "Enabled", true, "Mix the realms' enemies into every run (host).");
			WaveMix = ((BasePlugin)this).Config.Bind<float>("Mix", "WaveMix", 0.6f, new ConfigDescription("How much of each wave comes from the other three realms. 0 = only this realm's enemies, 0.75 = all four realms equally, 1 = only the other realms.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			EliteMix = ((BasePlugin)this).Config.Bind<float>("Mix", "EliteMix", 0.6f, new ConfigDescription("Chance that an elite comes from another realm's elite list.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			AnyBoss = ((BasePlugin)this).Config.Bind<bool>("Mix", "AnyBoss", true, "The end boss can be any boss, including ones you haven't unlocked yet (the game normally picks from unlocked bosses).");
			LogMix = ((BasePlugin)this).Config.Bind<bool>("Debug", "LogMix", false, "Write each mixed wave, elite and boss to the BepInEx log.");
			new Harmony("girthy_mods.RealmMix").PatchAll(typeof(MixPatches));
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(8, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("RealmMix");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ready.");
			}
			log.LogInfo(val);
		}
	}
}