Decompiled source of LobbyExpansion v1.0.3

GTFO.LobbyExpansion.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AIGraph;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BoosterImplants;
using CellMenu;
using ChainedPuzzles;
using GTFO.LobbyExpansion.Patches.Manual;
using GTFO.LobbyExpansion.Util;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Common;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using PlayerCoverage;
using SNetwork;
using Steamworks;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GTFO.LobbyExpansion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+07fb2bb5be4b94130450530ae7cbb719bdb6e1d8")]
[assembly: AssemblyProduct("GTFO.LobbyExpansion")]
[assembly: AssemblyTitle("GTFO.LobbyExpansion")]
[assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GTFO.LobbyExpansion
{
	public static class HarmonyControlFlow
	{
		public const bool DontExecute = false;

		public const bool Execute = true;
	}
	internal static class L
	{
		private static readonly ManualLogSource Logger;

		static L()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			Logger = new ManualLogSource("GTFO.LobbyExpansion");
			Logger.Sources.Add((ILogSource)(object)Logger);
		}

		internal static void Assert(bool condition, object data)
		{
			if (!condition)
			{
				string text = "ASSERTION FAILED: " + Format(data);
				Fatal(text);
				throw new ApplicationException(text);
			}
		}

		internal static void DebugWarning(object data)
		{
			Warning("-------------------------------------------");
			Warning("-------------- DEBUG WARNING --------------");
			Warning(Format(data));
			Warning("-------------------------------------------");
		}

		internal static void Debug(object data)
		{
			Logger.LogDebug((object)Format(data));
		}

		internal static void Info(object data)
		{
			Logger.LogMessage((object)Format(data));
		}

		internal static void Verbose(object data)
		{
			Logger.LogDebug((object)Format(data));
		}

		internal static void Error(object data)
		{
			Logger.LogError((object)Format(data));
		}

		internal static void Fatal(object data)
		{
			Logger.LogFatal((object)Format(data));
		}

		internal static void Warning(object data)
		{
			Logger.LogWarning((object)Format(data));
		}

		internal static void LogExecutingMethod(string? parameterInfo = "")
		{
			MethodBase method = new StackFrame(1, needFileInfo: false).GetMethod();
			if (method == null)
			{
				Error("COULD NOT LOG EXECUTING METHOD. THIS SHOULD NOT HAPPEN.");
				return;
			}
			string text = method.DeclaringType?.FullName ?? "???";
			string name = method.Name;
			string text2 = (string.IsNullOrWhiteSpace(parameterInfo) ? "" : (" (" + parameterInfo + ")"));
			Verbose(text + "." + name + text2);
		}

		private static string Format(object msg)
		{
			return msg.ToString() ?? "";
		}
	}
	public class PatchingException : Exception
	{
		public PatchingException(string? message)
			: base(message)
		{
		}

		public PatchingException(string? message, Exception? innerException)
			: base(message, innerException)
		{
		}
	}
	[BepInPlugin("GTFO.LobbyExpansion", "GTFO.LobbyExpansion", "1.0.3")]
	public class Plugin : BasePlugin
	{
		private Harmony _harmony = null;

		public override void Load()
		{
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Expected O, but got Unknown
			try
			{
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				L.Warning("-------------- Applying manual patches. --------------");
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				L.Warning("------------------------------------------------------");
				HashSet<Type> hashSet = new HashSet<Type>();
				List<ManualPatch> list = new List<ManualPatch>
				{
					new CM_PageExpeditionSuccessManualPatch(),
					new CM_PageLoadoutManualPatch(),
					new CM_PageMapManualPatch(),
					new CM_PlayerLobbyBarManualPatch(),
					new DiscordManagerManualPatch(),
					new GuiManagerManualPatch(),
					new PLOC_InElevatorManualPatch(),
					new PlayerAgentManualPatch(),
					new PlayerBotAIDataManualPatch(),
					new PlayerCoverageDataSet_NodeManualPatch(),
					new PlayerCoverageDataSet_PortalManualPatch(),
					new PlayerManagerManualPatch(),
					new PlayerSessionStatusManagerManualPatch(),
					new PlayerVoiceManagerManualPatch(),
					new SNet_PlayerSlotManagerManualPatch(),
					new SNet_SyncManagerManualPatch()
				};
				foreach (ManualPatch item in list)
				{
					Type type = item.GetType();
					if (hashSet.Contains(type))
					{
						string text = $"The same patch {type} is being applied twice. Fix this.";
						L.Fatal(text);
						throw new PatchingException(text);
					}
					L.Verbose("Applying manual patch " + item.GetType().Name + ".");
					item.Apply();
					hashSet.Add(type);
				}
			}
			catch (Exception data)
			{
				L.Fatal("An error occurred while applying manual patches:");
				L.Fatal(data);
				return;
			}
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			L.Warning("-------------- Applying Harmony patches. -------------");
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			L.Warning("------------------------------------------------------");
			try
			{
				_harmony = new Harmony("GTFO.LobbyExpansion");
				_harmony.PatchAll();
			}
			catch (Exception data2)
			{
				L.Fatal("An error occurred while applying patches:");
				L.Fatal(data2);
				return;
			}
			L.Info("Loaded plugin GTFO.LobbyExpansion.");
		}
	}
	public static class PluginConfig
	{
		public static readonly byte MaxPlayers = 8;

		public static SlotPermission GetExtraSlotPermission(int slotIndex)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return (SlotPermission)4;
		}

		public static string GetExtraSlotNickname(int characterIndex)
		{
			if (1 == 0)
			{
			}
			string result = characterIndex switch
			{
				4 => "Schaeffer", 
				5 => "North", 
				6 => "Henriksson", 
				7 => "Maddox", 
				_ => $"Prisoner{characterIndex}", 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "GTFO.LobbyExpansion";

		internal const string Name = "GTFO.LobbyExpansion";

		internal const string Version = "1.0.3";
	}
}
namespace GTFO.LobbyExpansion.Util
{
	public abstract class ManualPatch
	{
		protected record Patch
		{
			public string Method { get; init; } = "";


			public string Description { get; init; } = "";


			public string Pattern { get; init; } = "";


			public int Offset { get; init; }

			public byte[] Bytes { get; init; } = Array.Empty<byte>();


			public long? ScanSize { get; init; }

			public Type[]? ParameterTypes { get; init; } = Array.Empty<Type>();

		}

		private static readonly HashSet<IntPtr> PatchedAddresses = new HashSet<IntPtr>();

		protected List<Patch> Patches { get; } = new List<Patch>();


		protected abstract Type TargetType { get; }

		public void Apply()
		{
			SetupPatches();
			foreach (Patch patch in Patches)
			{
				Type[] parameterTypes = patch.ParameterTypes ?? Array.Empty<Type>();
				string method = patch.Method;
				bool flag = ((method == ".ctor" || method == "ctor") ? true : false);
				nint methodPointer = (flag ? Memory.GetIl2CppConstructorAddress(TargetType, parameterTypes) : Memory.GetIl2CppMethodAddress(TargetType, patch.Method, parameterTypes));
				nint num = Memory.FindSignatureInIl2CppMethod(methodPointer, patch.Pattern, patch.ScanSize);
				if (num == 0)
				{
					throw new PatchingException("Could not find pattern for patch \"" + patch.Description + "\".");
				}
				nint num2 = num + patch.Offset;
				if (PatchedAddresses.Contains(num2))
				{
					string text = "Patching the same address " + ((IntPtr)num2).ToString("X") + "! Something is wrong!";
					L.Fatal(text);
					throw new PatchingException(text);
				}
				L.Verbose("Applying \"" + patch.Description + "\" patch at " + ((IntPtr)num2).ToString("X"));
				Memory.PatchMemory(num2, patch.Bytes);
				PatchedAddresses.Add(num2);
			}
		}

		protected abstract void SetupPatches();

		protected static byte[] GenerateNop(int count)
		{
			if (count < 0)
			{
				throw new ArgumentException("Count must be greater than 0.", "count");
			}
			return Enumerable.Repeat((byte)144, count).ToArray();
		}
	}
	public static class Memory
	{
		private record Signature(byte[] Bytes, char[] Mask);

		private const long DefaultBlockScanSize = 3000L;

		public static nint GetIl2CppConstructorAddress(Type type, params Type[] parameterTypes)
		{
			ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, parameterTypes);
			if (constructor == null)
			{
				IEnumerable<string> value = parameterTypes.Select((Type x) => x.FullName?.ToString() ?? "null");
				throw new MissingMethodException($"Could not find constructor for {type.FullName} with {parameterTypes.Length} parameters ({value}).");
			}
			return GetIl2CppMethodAddress(type, constructor);
		}

		public static nint GetIl2CppConstructorAddress<T>(params Type[] parameterTypes) where T : Il2CppObjectBase
		{
			return GetIl2CppConstructorAddress(typeof(T), parameterTypes);
		}

		public static nint GetIl2CppMethodAddress(Type type, string methodName)
		{
			return GetIl2CppMethodAddress(type, methodName, Array.Empty<Type>());
		}

		public static nint GetIl2CppMethodAddress(Type type, string methodName, Type[] parameterTypes)
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
			if (method == null)
			{
				string value = "";
				if (parameterTypes.Length != 0)
				{
					value = $" with {parameterTypes.Length} parameters (${string.Join(", ", parameterTypes.Select((Type x) => x.FullName?.ToString() ?? x.Name))})";
				}
				throw new MissingMethodException($"Could not find method {methodName} in type {type.FullName}{value}.");
			}
			return GetIl2CppMethodAddress(type, method);
		}

		public static nint GetIl2CppMethodAddress<T>(string methodName) where T : Il2CppObjectBase
		{
			return GetIl2CppMethodAddress<T>(methodName, Array.Empty<Type>());
		}

		public static nint GetIl2CppMethodAddress<T>(string methodName, Type[] parameterTypes) where T : Il2CppObjectBase
		{
			return GetIl2CppMethodAddress(typeof(T), methodName, parameterTypes);
		}

		public unsafe static nint GetIl2CppMethodAddress(Type type, MethodBase methodBase)
		{
			FieldInfo il2CppMethodInfoPointerFieldForGeneratedMethod = Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(methodBase);
			if (il2CppMethodInfoPointerFieldForGeneratedMethod == null)
			{
				throw new MissingFieldException($"Could not find IL2CPP method info pointer field for method {methodBase} of {type.FullName ?? type.Name}.");
			}
			object value = il2CppMethodInfoPointerFieldForGeneratedMethod.GetValue(null);
			if (value == null)
			{
				throw new NullReferenceException($"Method info pointer field for method {methodBase} of {type.FullName ?? type.Name} was null.");
			}
			return *(nint*)(void*)(IntPtr)value;
		}

		public static nint GetIl2CppMethodAddress<T>(MethodBase methodBase) where T : Il2CppObjectBase
		{
			return GetIl2CppMethodAddress(typeof(T), methodBase);
		}

		public static nint FindSignatureInIl2CppMethod(nint methodPointer, string signature, long? blockSize)
		{
			Signature signature2 = ConvertAobToSignature(signature);
			if (signature2 == null)
			{
				throw new ArgumentException("signature was an invalid signature.");
			}
			return FindSignatureInBlock(methodPointer, blockSize ?? 3000, signature2.Bytes, signature2.Mask);
		}

		public static nint FindSignatureInIl2CppMethod<T>(string methodName, string signature, long blockSize = 3000L) where T : Il2CppObjectBase
		{
			nint il2CppMethodAddress = GetIl2CppMethodAddress<T>(methodName);
			return FindSignatureInIl2CppMethod(il2CppMethodAddress, signature, blockSize);
		}

		public static void PatchMemory(IntPtr address, byte[] bytes)
		{
			if (address == IntPtr.Zero)
			{
				throw new ArgumentException("address cannot be zero.");
			}
			if (!Win32.VirtualProtect(address, new IntPtr(bytes.Length), Win32.MemoryProtection.ExecuteReadWrite, out var lpflOldProtect))
			{
				throw new Exception($"VirtualProtect failed for address {address}.");
			}
			bool flag = false;
			try
			{
				L.Verbose("Patching " + address.ToString("X") + " with " + string.Join(", ", bytes.Select((byte x) => x.ToString("X"))));
				for (int i = 0; i < bytes.Length; i++)
				{
					Marshal.WriteByte(address, i, bytes[i]);
				}
			}
			catch (Exception value)
			{
				Console.WriteLine(value);
				throw;
			}
			finally
			{
				try
				{
					flag = Win32.VirtualProtect(address, new IntPtr(bytes.Length), lpflOldProtect, out var _);
				}
				catch
				{
					L.Error($"VirtualProtect failed to restore protection for address {address}.");
				}
			}
			if (!flag)
			{
				throw new Exception($"VirtualProtect failed to restore protection for address {address}.");
			}
		}

		private unsafe static nint FindSignatureInBlock(nint block, long blockSize, byte[] pattern, char[] mask)
		{
			for (long num = 0L; num < blockSize; num++)
			{
				bool flag = true;
				for (uint num2 = 0u; num2 < mask.Length; num2++)
				{
					if (*(byte*)(num + block + num2) != pattern[num2] && mask[num2] != '?')
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					return (nint)(num + block);
				}
			}
			return 0;
		}

		private static Signature? ConvertAobToSignature(string signature)
		{
			if (string.IsNullOrWhiteSpace(signature))
			{
				return null;
			}
			string[] array = signature.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
			if (array.Length == 0)
			{
				return null;
			}
			byte[] array2 = new byte[array.Length];
			char[] array3 = new char[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				if ((text == "?" || text == "??") ? true : false)
				{
					array2[i] = 0;
					array3[i] = '?';
				}
				else
				{
					array2[i] = byte.Parse(text, NumberStyles.HexNumber);
					array3[i] = 'x';
				}
			}
			return new Signature(array2, array3);
		}
	}
	public static class Win32
	{
		[Flags]
		public enum MemoryProtection : uint
		{
			NoAccess = 1u,
			ReadOnly = 2u,
			ReadWrite = 4u,
			WriteCopy = 8u,
			Execute = 0x10u,
			ExecuteRead = 0x20u,
			ExecuteReadWrite = 0x40u,
			ExecuteWriteCopy = 0x80u,
			GuardModifierflag = 0x100u,
			NoCacheModifierflag = 0x200u,
			WriteCombineModifierflag = 0x400u
		}

		[DllImport("kernel32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		public static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect);
	}
}
namespace GTFO.LobbyExpansion.Patches.Manual
{
	public class CM_PageExpeditionSuccessManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(CM_PageExpeditionSuccess);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "Setup",
					Description = "Adjust hardcoded m_playerReports size in Setup.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D BE F0 01 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class CM_PageLoadoutManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(CM_PageLoadout);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "Setup",
					Description = $"Adjust CM_PageLoadout Setup m_playerLobbyBars size from 4 -> {PluginConfig.MaxPlayers}.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8B D0 48 89 87 08 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class CM_PageMapManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(CM_PageMap);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[12]
			{
				new Patch
				{
					Method = "TryGetInventoryWithSlotIndex",
					Description = "Remove CM_PageMap::TryGetInventoryWithSlotIndex slotIndex > 3",
					Pattern = "83 FF 03 77 60",
					Offset = 2,
					Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
				},
				new Patch
				{
					Method = "Setup",
					Description = "Adjust CM_PageMap::Setup() m_inventory = new PUI_Inventory[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D B7 38 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() m_syncedPlayers = new CM_MapPlayerGUIItem[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D AF 50 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() m_syncedCursors = new CM_Cursor[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4D 8D B7 58 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() m_drawPixelBufferIndex = new int[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D 8F 80 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() m_drawPixelBuffer = new CM_MapDrawPixel[4][] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8B D0 49 89 87 78 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() m_lastDrawingPos = new Vector2[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 49 8D 8F 68 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "CreatePlayerIcons",
					Description = "Adjust CM_PageMap::CreatePlayerIcons() for (int i = 0; i < 4; i++) to new max players.",
					Pattern = "83 FE 04 0F 8C A9 FC FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "UpdatePlayerData",
					Description = "Adjust CM_PageMap::UpdatePlayerData() for (int i = 0; i < 4; i++) to new max players.",
					Pattern = "83 FB 04 0F 8C 21 FF FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "UpdateSyncedCursorVisibility",
					Description = "Adjust CM_PageMap::UpdateSyncedCursorVisibility() for (int i = 0; i < 4; i++) to new max players.",
					Pattern = "83 FB 04 0F 8C 61 FF FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "SetPageActive",
					Description = "Adjust CM_PageMap::SetPageActive() m_playerIsDrawing = new bool[4] to new max players.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 8B 60 02 00 00",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "OnEnable",
					Description = "Adjust CM_PageMap::OnEnable() for (int i = 0; i < 4; i++) to new max players.",
					Pattern = "83 FE 04 7C 94",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class CM_PlayerLobbyBarManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(CM_PlayerLobbyBar);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "UpdatePlayer",
					Description = "Adjust hardcoded limit of 4 in CM_PlayerLobbyBar::UpdatePlayer to new max players.",
					Pattern = "83 F8 04 0F 8D F0 00 00 00",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class DiscordManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(DiscordManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "GetMaxLobbySize",
					Description = "Adjust DiscordManager::GetMaxLobbySize hardcoded iteration to new max players.",
					Pattern = "BF 04 00 00 00 33 DB",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class GuiManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(GuiManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "Setup",
					Description = "Adjust GuiManager::Setup() m_playerPings = new SyncedNavMarkerWrapper[4] to new max players.",
					Pattern = "BA 04 00 00 00 4C 8B E8",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers },
					ScanSize = 7500L
				}
			}));
		}
	}
	public class PlayerAgentManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerAgent);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
			{
				new Patch
				{
					Method = "Setup",
					Description = "Remove characterID limit in PlayerAgent::Setup",
					Pattern = "0F 87 12 10 00 00",
					Offset = 0,
					Bytes = ManualPatch.GenerateNop(6)
				},
				new Patch
				{
					Method = "Setup",
					Description = "Remove characterID >= m_modelsForSync length in PlayerAgent::Setup since m_modelsForSync isn't used anyway",
					Pattern = "44 3B 70 18 0F 8D F8 0F 00 00",
					Offset = 4,
					Bytes = ManualPatch.GenerateNop(6)
				}
			}));
		}
	}
	public class PlayerCoverageDataSet_NodeManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerCoverageDataSet_Node);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[4]
			{
				new Patch
				{
					Method = ".ctor",
					Description = "Patch PlayerCoverageDataSet_Node constructor and PlayerCoverageDataSet_Portal$$ constructor (#1)",
					Pattern = "FF C6 83 FE 04 7C 8D 48 8B 5C 24 30",
					Offset = 4,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = ".ctor",
					Description = $"Patch PlayerCoverageDataSet_Node constructor m_coverageDatas array size from 4 -> {PluginConfig.MaxPlayers}.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D 73 10 48 8B D0 49 8B CE 49 89 06 E8 ?? ?? ?? ?? 33 D2",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "GetNodeDistanceToClosestPlayer",
					Description = "Adjust GetNodeDistanceToClosestPlayer hardcoded iteration of 4.",
					Pattern = "83 F9 04 7C CC",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "GetNodeDistanceToClosestPlayer_Unblocked",
					Description = "Adjust GetNodeDistanceToClosestPlayer_Unblocked hardcoded iteration of 4.",
					Pattern = "83 FB 04 0F 8C 5B FF FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class PlayerCoverageDataSet_PortalManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerCoverageDataSet_Portal);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
			{
				new Patch
				{
					Method = ".ctor",
					ParameterTypes = new Type[1] { typeof(AIG_CoursePortal) },
					Description = "Patch PlayerCoverageDataSet_Portal constructor (#1) for loop",
					Pattern = "FF C6 83 FE 04 7C 8D 48 8B 5C 24 30",
					Offset = 4,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = ".ctor",
					ParameterTypes = new Type[1] { typeof(AIG_CoursePortal) },
					Description = $"Patch PlayerCoverageDataSet_Portal constructor m_coverageDatas array size from 4 -> {PluginConfig.MaxPlayers}.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 4C 8D 73 10 48 8B D0 49 8B CE 49 89 06 E8 ?? ?? ?? ?? 33 F6",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class PlayerManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[4]
			{
				new Patch
				{
					Method = "SpawnBot",
					Description = "Remove SpawnBot hardcoded limit of 4.",
					Pattern = "83 78 18 04 0F 84 C0 03 00 00",
					Offset = 4,
					Bytes = ManualPatch.GenerateNop(6)
				},
				new Patch
				{
					Method = ".ctor",
					Description = "Set constructor m_botSlot size to new max player limit.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4E 70",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = ".ctor",
					Description = "Patch inlined version of the creation of PositionReservations in PlayerManager constructor.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 20 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF E8",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = ".ctor",
					Description = "Patch inlined version of the creation of ObjectReservations in PlayerManager constructor.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF E8",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class PlayerBotAIDataManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerBotAIData);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[2]
			{
				new Patch
				{
					Method = ".ctor",
					Description = "Set PlayerBotAIData constructor PositionReservations size to new max player limit.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 20 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF 48 8B 5C 24 30",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = ".ctor",
					Description = "Set PlayerBotAIData constructor ObjectReservations size to new max player limit.",
					Pattern = "BA 04 00 00 00 E8 ?? ?? ?? ?? 48 8D 4F 28 48 8B D0 48 89 01 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 30 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 8D 4F 38 48 8B D3 48 89 19 E8 ?? ?? ?? ?? 33 D2 48 8B CF 48 8B 5C 24 30",
					Offset = 1,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class PlayerSessionStatusManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerSessionStatusManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "OnPlayerStateCapture",
					Description = "Adjust PlayerSessionStatusManager::OnPlayerStateCapture() bool flag2 = characterIndex > -1 && characterIndex < 4; to new max players.",
					Pattern = "83 F8 04 0F 9C C3",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class PlayerVoiceManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PlayerVoiceManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "RegisterPlayerVoice",
					Description = "Patch PlayerVoiceManager < 3",
					Pattern = "83 FE 03 76 67",
					Offset = 2,
					Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
				}
			}));
		}
	}
	public class PLOC_InElevatorManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(PLOC_InElevator);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "CommonEnter",
					Description = "PLOC_InElevator::CommonEnter PLOCStateReferenceID > 3",
					Pattern = "83 B8 A0 00 00 00 03",
					Offset = 6,
					Bytes = new byte[1] { (byte)(PluginConfig.MaxPlayers - 1) }
				}
			}));
		}
	}
	public class SNet_PlayerSlotManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(SNet_PlayerSlotManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[7]
			{
				new Patch
				{
					Method = "Internal_ManageSlot",
					Description = "Adjust Internal_ManageSlot hardcoded iteration of 4.",
					Pattern = "83 FF 04 0F 8C D1 FE FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "OnResetSession",
					Description = "Adjust OnResetSession hardcoded iteration of 4.",
					Pattern = "83 FB 04 7C 9E",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "OnValidateMasterData",
					Description = "Adjust OnValidateMasterData hardcoded iteration of 4.",
					Pattern = "83 FF 04 0F 8C 68 FE FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "HasFreeBotSlot",
					Description = "Adjust HasFreeBotSlot hardcoded iteration of 4.",
					Pattern = "83 FB 04 7C 87",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "HasFreeHumanSlot",
					Description = "Adjust HasFreeHumanSlot hardcoded iteration of 4.",
					Pattern = "83 FB 04 0F 8C 38 FF FF FF",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "SetAllPlayerSlotPermissions",
					Description = "Adjust SetAllPlayerSlotPermissions hardcoded iteration of 4.",
					Pattern = "83 FB 04 7C C7",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				},
				new Patch
				{
					Method = "AreSlotPermissionsSet",
					Description = "Adjust AreSlotPermissionsSet hardcoded iteration of 4.",
					Pattern = "83 F8 04 7C EA",
					Offset = 2,
					Bytes = new byte[1] { PluginConfig.MaxPlayers }
				}
			}));
		}
	}
	public class SNet_SyncManagerManualPatch : ManualPatch
	{
		protected override Type TargetType { get; } = typeof(SNet_SyncManager);


		protected override void SetupPatches()
		{
			base.Patches.AddRange(new <>z__ReadOnlyArray<Patch>(new Patch[1]
			{
				new Patch
				{
					Method = "ValidateIndex",
					Description = "Remove SNet_SyncManager::ValidateIndex character index > 3 check, since we're using higher characterIDs.",
					Pattern = "0F 87 C8 06 00 00",
					Offset = 0,
					Bytes = ManualPatch.GenerateNop(6)
				}
			}));
		}
	}
}
namespace GTFO.LobbyExpansion.Patches.Harmony
{
	[HarmonyPatch(typeof(BoosterImplantManager))]
	public static class BoosterImplantManagerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake__Postfix(BoosterImplantManager __instance)
		{
			L.LogExecutingMethod();
			if (((Il2CppArrayBase<PlayerBoosterImplantState>)(object)__instance.m_boosterPlayers).Length < PluginConfig.MaxPlayers)
			{
				L.Verbose("Expanding m_boosterPlayers size.");
				__instance.m_boosterPlayers = new Il2CppReferenceArray<PlayerBoosterImplantState>((long)PluginConfig.MaxPlayers);
			}
		}
	}
	[HarmonyPatch(typeof(CM_PageExpeditionSuccess))]
	public static class CM_PageExpeditionSuccessPatch
	{
		private static bool _pageDownDebounce;

		private static bool _pageUpDebounce;

		private static bool _needPositionUpdate;

		private static DateTime _lastVisibilityUpdate = DateTime.Now;

		public static string buttonLabel = "SWITCH LOBBIES";

		public static Vector3 buttonPosition = new Vector3(350f, -540f, 50f);

		public static Vector3 buttonScale = new Vector3(0.5f, 0.5f, 0f);

		public static CM_Item switchbutton;

		public static int PageIndex { get; set; }

		[HarmonyPatch("OnEnable")]
		[HarmonyPostfix]
		public static void OnEnable__Postfix(CM_PageExpeditionSuccess __instance)
		{
			L.LogExecutingMethod();
			PageIndex = 0;
			_needPositionUpdate = true;
			UpdateVisiblePlayerReports(__instance);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void Update__Postfix(CM_PageExpeditionSuccess __instance)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Invalid comparison between Unknown and I4
			if (_needPositionUpdate)
			{
				L.Verbose("Updating position of extra player reports.");
				for (int i = 4; i < ((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports).Length; i++)
				{
					Transform transform = ((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i % 4]).transform;
					((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i]).transform.position = transform.position;
					((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)__instance.m_playerReports)[i]).transform.parent = transform.parent;
				}
				_needPositionUpdate = false;
			}
			if (DateTime.Now > _lastVisibilityUpdate)
			{
				_lastVisibilityUpdate = DateTime.Now + TimeSpan.FromMilliseconds(50.0);
				UpdateVisiblePlayerReports(__instance);
			}
			bool flag = false;
			int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
			if (PageIndex < num && !_pageDownDebounce && Input.GetKeyDown((KeyCode)281))
			{
				L.Verbose($"Showing next set of players {PageIndex}.");
				PageIndex++;
				_pageDownDebounce = true;
				flag = true;
			}
			if (_pageDownDebounce && Input.GetKeyUp((KeyCode)281))
			{
				L.Verbose("Debounce off for page down.");
				_pageDownDebounce = false;
			}
			if (PageIndex > 0 && !_pageUpDebounce && Input.GetKeyDown((KeyCode)280))
			{
				L.Verbose($"Showing previous set of players {PageIndex}.");
				PageIndex--;
				_pageUpDebounce = true;
				flag = true;
			}
			if (_pageUpDebounce && Input.GetKeyUp((KeyCode)280))
			{
				L.Verbose("Debounce off for page up.");
				_pageUpDebounce = false;
			}
			if (flag)
			{
				L.Verbose("Updating visible player reports.");
				UpdateVisiblePlayerReports(__instance);
			}
			if ((int)GameStateManager.Current.m_nextState != 14)
			{
				((RectTransformComp)switchbutton).SetVisible(false);
			}
			else
			{
				((RectTransformComp)switchbutton).SetVisible(true);
			}
		}

		private static void UpdateVisiblePlayerReports(CM_PageExpeditionSuccess page)
		{
			if (page.m_playerReports == null)
			{
				return;
			}
			Il2CppReferenceArray<SNet_Slot> playerSlots = SNet.Slots.PlayerSlots;
			int num = PageIndex * 4;
			int num2 = Math.Min(num + 4, PluginConfig.MaxPlayers);
			for (int i = 0; i < ((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports).Count; i++)
			{
				if (!((Object)(object)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports)[i] == (Object)null))
				{
					bool active = true;
					if (i < num)
					{
						L.Verbose($"Hiding lobby bar at slot {i} since it is below the minimum visible index {num}.");
						active = false;
					}
					else if (i >= num2)
					{
						L.Verbose($"Hiding lobby bar at slot {i} since it is above the maximum visible index {num2}.");
						active = false;
					}
					else if (i >= ((Il2CppArrayBase<SNet_Slot>)(object)playerSlots).Count || (Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)playerSlots)[i].player == (Object)null)
					{
						L.Verbose($"Hiding extra slot {i} since we don't have a player in that slot.");
						active = false;
					}
					((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports)[i]).gameObject.SetActive(active);
				}
			}
		}

		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(CM_PageExpeditionSuccess __instance, MainMenuGuiLayer guiLayer)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			CM_PageExpeditionSuccess __instance2 = __instance;
			CM_Item val = ((Il2CppObjectBase)((GuiLayer)((CM_PageBase)__instance2).m_guiLayer).AddRectComp(guiLayer.PageLoadout.m_readyButtonPrefab, (GuiAnchor)1, new Vector2(200f, 20f), ((Component)__instance2.m_btnLeaveExpedition).transform)).TryCast<CM_Item>();
			val.SetText(buttonLabel);
			((Component)val).gameObject.transform.position = buttonPosition;
			((Component)val).gameObject.SetActive(true);
			((RectTransformComp)val).SetVisible(true);
			Action<int> action = delegate
			{
				int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
				if (PageIndex == 0)
				{
					PageIndex++;
					UpdateVisiblePlayerReports(__instance2);
				}
				else if (PageIndex == 1)
				{
					PageIndex--;
					UpdateVisiblePlayerReports(__instance2);
				}
			};
			val.OnBtnPressCallback += Action<int>.op_Implicit(action);
			switchbutton = val;
		}
	}
	[HarmonyPatch(typeof(CM_PageLoadout))]
	public static class CM_PageLoadoutPatch
	{
		private static bool _pageDownDebounce;

		private static bool _pageUpDebounce;

		public static string buttonLabel = "SWITCH LOBBIES";

		public static Vector3 buttonPosition = new Vector3(450f, -600f, 50f);

		public static Vector3 buttonScale = new Vector3(0.5f, 0.5f, 0f);

		public static CM_Item switchbutton;

		public static int PageIndex { get; set; }

		[HarmonyPatch("Setup")]
		[HarmonyPrefix]
		public static bool Setup__Prefix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			L.LogExecutingMethod();
			Il2CppReferenceArray<Transform> playerInfoHolders = __instance.m_playerInfoHolders;
			__instance.m_playerInfoHolders = new Il2CppReferenceArray<Transform>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < 4; i++)
			{
				((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i] = ((Il2CppArrayBase<Transform>)(object)playerInfoHolders)[i];
			}
			GameObject val = GameObject.Find("GUI/CellUI_Camera(Clone)/MainMenuLayer/CM_PageLoadout_CellUI(Clone)/PlayerMovement/PlayerPillars");
			L.Assert((Object)(object)val != (Object)null, "playerPillarsGameObj was null!");
			for (int j = 4; j < PluginConfig.MaxPlayers; j++)
			{
				string text = $"Player{j + 1}Root";
				L.Verbose("Creating extra player root (" + text + ").");
				GameObject val2 = new GameObject(text);
				Transform val3 = ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j % 4];
				val2.transform.position = val3.position;
				val2.transform.localPosition = val3.localPosition;
				val2.transform.localScale = val3.localScale;
				val2.transform.SetParent(val.transform);
				val2.layer = LayerMask.NameToLayer("UI");
				val2.SetActive(true);
				((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j] = val2.transform;
			}
			return true;
		}

		[HarmonyPatch("ArrangePlayerPillarSpacing")]
		[HarmonyPostfix]
		public static void ArrangePlayerPillarSpacing__Postfix(CM_PageLoadout __instance)
		{
			//IL_0025: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			L.LogExecutingMethod();
			Vector3[] array = (Vector3[])(object)new Vector3[4]
			{
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[0]).transform.position,
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[1]).transform.position,
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[2]).transform.position,
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[3]).transform.position
			};
			for (int i = 4; i < PluginConfig.MaxPlayers; i++)
			{
				string text = $"Player{i + 1}Root";
				L.Verbose("Updating extra player root position (" + text + ").");
				Transform val = ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i % 4];
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.position = val.position;
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.localPosition = val.localPosition;
				((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[i]).transform.localScale = val.localScale;
			}
			int num = PageIndex * 4;
			int num2 = Math.Min(num + 4, PluginConfig.MaxPlayers);
			for (int j = 0; j < ((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders).Count; j++)
			{
				if (j < num)
				{
					L.Verbose($"Hiding lobby bar at slot {j} since it is below the minimum visible index {num}.");
					((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).gameObject.transform.position = new Vector3(5000f, 5000f, 5000f);
				}
				else if (j >= num2)
				{
					L.Verbose($"Hiding lobby bar at slot {j} since it is above the maximum visible index {num2}.");
					((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).gameObject.transform.position = new Vector3(5000f, 5000f, 5000f);
				}
				else
				{
					((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).transform.position = array[j % array.Length];
				}
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void Update__Postfix(CM_PageLoadout __instance)
		{
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Invalid comparison between Unknown and I4
			bool flag = false;
			int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
			if (PageIndex < num && !_pageDownDebounce && Input.GetKeyDown((KeyCode)281))
			{
				L.Verbose($"Showing next set of players {PageIndex}.");
				PageIndex++;
				_pageDownDebounce = true;
				flag = true;
			}
			if (_pageDownDebounce && Input.GetKeyUp((KeyCode)281))
			{
				L.Verbose("Debounce off for page down.");
				_pageDownDebounce = false;
			}
			if (PageIndex > 0 && !_pageUpDebounce && Input.GetKeyDown((KeyCode)280))
			{
				L.Verbose($"Showing previous set of players {PageIndex}.");
				PageIndex--;
				_pageUpDebounce = true;
				flag = true;
			}
			if (_pageUpDebounce && Input.GetKeyUp((KeyCode)280))
			{
				L.Verbose("Debounce off for page up.");
				_pageUpDebounce = false;
			}
			if (flag)
			{
				L.Verbose("Updating visible pillars.");
				__instance.ArrangePlayerPillarSpacing();
			}
			if (!PlayfabMatchmakingManager.Current.IsMatchmakeInProgress && SNet.IsInLobby)
			{
				if (!GameStateManager.IsReady)
				{
					((RectTransformComp)switchbutton).SetVisible(true);
				}
				else
				{
					((RectTransformComp)switchbutton).SetVisible(false);
				}
			}
			if ((int)GameStateManager.Current.m_nextState == 10)
			{
				((RectTransformComp)switchbutton).SetVisible(true);
			}
		}

		[HarmonyPatch("ApplyPlayerSlotPermissionsFromSettings")]
		[HarmonyPostfix]
		public static void ApplyPlayerSlotPermissionsFromSettings__Postfix(CM_PageLoadout __instance)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			L.LogExecutingMethod();
			bool flag = false;
			for (int i = 4; i < PluginConfig.MaxPlayers; i++)
			{
				SlotPermission extraSlotPermission = PluginConfig.GetExtraSlotPermission(i);
				if ((Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player == (Object)null || !((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player.IsLocal)
				{
					flag = SNet.Slots.SetSlotPermission(i, extraSlotPermission) || flag;
				}
				else if (((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player.IsLocal)
				{
					flag = SNet.Slots.SetSlotPermission(i, (SlotPermission)4) || flag;
				}
			}
			if (!flag)
			{
				L.Verbose("Calling OnSlotsStatusChange.");
				SNet.Core.OnSlotsStatusChanged();
			}
			if (SNet_Events.OnLobbyPermissionsSet != null)
			{
				L.Verbose("Calling OnLobbyPermissionsSet.");
				SNet_Events.OnLobbyPermissionsSet.Invoke();
			}
		}

		[HarmonyPatch("OnDisable")]
		[HarmonyPostfix]
		public static void OnDisable__Postfix()
		{
			L.LogExecutingMethod();
			PageIndex = 0;
		}

		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			CM_PageLoadout __instance2 = __instance;
			if (!((Object)(object)CM_PageLoadout.Current != (Object)null))
			{
				return;
			}
			CM_Item val = ((Il2CppObjectBase)((GuiLayer)((CM_PageBase)__instance2).m_guiLayer).AddRectComp(__instance2.m_readyButtonPrefab, (GuiAnchor)0, new Vector2(200f, 20f), __instance2.m_readyButtonAlign)).TryCast<CM_Item>();
			val.SetText(buttonLabel);
			((Component)val).gameObject.transform.position = buttonPosition;
			((Component)val).gameObject.SetActive(true);
			((RectTransformComp)val).SetVisible(!GameStateManager.IsReady);
			Action<int> action = delegate
			{
				int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
				if (PageIndex == 0)
				{
					PageIndex++;
					__instance2.ArrangePlayerPillarSpacing();
				}
				else if (PageIndex == 1)
				{
					PageIndex--;
					__instance2.ArrangePlayerPillarSpacing();
				}
			};
			val.OnBtnPressCallback += Action<int>.op_Implicit(action);
			switchbutton = val;
		}
	}
	[HarmonyPatch(typeof(CM_PageMap))]
	public static class CM_PageMapPatch
	{
		[HarmonyPatch("UpdatePlayerInventory")]
		[HarmonyPostfix]
		public static void UpdatePlayerInventory__Postfix(CM_PageMap __instance, SNet_Player player, int count)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			PUI_Inventory val = ((Il2CppArrayBase<PUI_Inventory>)(object)__instance.m_inventory)[player.PlayerSlotIndex()];
			Vector2 position = ((RectTransformComp)val).GetPosition();
			Vector2 position2 = default(Vector2);
			((Vector2)(ref position2))..ctor(0f, 0f);
			int num = 0;
			for (int num2 = count; num2 > 3; num2 -= 4)
			{
				num++;
			}
			float num3 = (0f - __instance.m_inventoryOffsetPerPlayer) * 1.3f;
			position2.x = position.x + (float)num * num3;
			position2.y = -150f + (float)(count % 4) * (0f - __instance.m_inventoryOffsetPerPlayer);
			((RectTransformComp)val).SetPosition(position2);
		}
	}
	[HarmonyPatch(typeof(CM_PlayerLobbyBar))]
	public static class CM_PlayerLobbyBarPatch
	{
		[HarmonyPatch("SpawnPlayerModel")]
		[HarmonyPrefix]
		public static bool SpawnPlayerModel__Prefix(CM_PlayerLobbyBar __instance, ref int index)
		{
			L.LogExecutingMethod($"{"index"}: {index}");
			if (index > 3)
			{
				int num = index % 4;
				L.Verbose($"Clamping {"index"} to {num}.");
				index = num;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CP_PlayerScanner))]
	public static class CP_PlayerScannerPatch
	{
		[HarmonyPatch("StartScan")]
		[HarmonyPrefix]
		public static bool StartScan__Prefix(CP_PlayerScanner __instance)
		{
			L.LogExecutingMethod();
			if (((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length < PluginConfig.MaxPlayers)
			{
				L.Verbose($"Expanding {"m_scanSpeeds"} size from {((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length} to {PluginConfig.MaxPlayers} to account for more players being in the scan.");
				Il2CppStructArray<float> scanSpeeds = __instance.m_scanSpeeds;
				__instance.m_scanSpeeds = new Il2CppStructArray<float>((long)PluginConfig.MaxPlayers);
				for (int i = 0; i < PluginConfig.MaxPlayers; i++)
				{
					((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds)[i] = ((Il2CppArrayBase<float>)(object)scanSpeeds)[Math.Min(i, ((Il2CppArrayBase<float>)(object)scanSpeeds).Length - 1)];
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DefaultCharacterLayouts))]
	public class DefaultCharacterLayoutsPatch
	{
		[HarmonyPatch("GetDefaultVanityItems")]
		[HarmonyPrefix]
		public static bool GetDefaultVanityItems__Prefix(ref int characterIndex)
		{
			L.LogExecutingMethod($"{"characterIndex"}: {characterIndex}");
			if (characterIndex > 3)
			{
				characterIndex %= 4;
				L.Verbose($"Clamping {"characterIndex"} to {characterIndex}.");
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DiscordManager))]
	public class DiscordManagerPatch
	{
		[HarmonyPatch("GetCharacterNickname")]
		[HarmonyPostfix]
		public static void GetCharacterNickname__Postfix(ref string __result, int characterIndex)
		{
			L.LogExecutingMethod($"{"characterIndex"}: {characterIndex}, {"__result"}: {__result}");
			if (characterIndex > 3)
			{
				__result = PluginConfig.GetExtraSlotNickname(characterIndex);
				L.Verbose($"Corrected character nickname for index #{characterIndex} to {__result}.");
			}
		}
	}
	[HarmonyPatch(typeof(DramaManager))]
	public static class DramaManagerPatch
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix()
		{
			L.LogExecutingMethod();
			ResetDramaFieldsProperly();
		}

		[HarmonyPatch("OnLevelCleanup")]
		[HarmonyPostfix]
		public static void OnLevelCleanup__Postfix()
		{
			L.LogExecutingMethod();
			ResetDramaFieldsProperly();
		}

		private static void ResetDramaFieldsProperly()
		{
			DramaManager.SyncedPlayerStates = new Il2CppStructArray<DRAMA_State>((long)PluginConfig.MaxPlayers);
			DramaManager.SyncedPlayerTensions = new Il2CppStructArray<float>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < ((Il2CppArrayBase<DRAMA_State>)(object)DramaManager.SyncedPlayerStates).Length; i++)
			{
				((Il2CppArrayBase<DRAMA_State>)(object)DramaManager.SyncedPlayerStates)[i] = (DRAMA_State)0;
			}
		}
	}
	[HarmonyPatch(typeof(ElevatorCage))]
	public static class ElevatorCagePatch
	{
		[HarmonyPatch("SkipPreReleaseSequence")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool SkipPreReleaseSequence__Prefix(ElevatorCage __instance, CellSoundPlayer sound, ref int playerId)
		{
			L.LogExecutingMethod($"{"playerId"}: {playerId}");
			if (((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft).Length < PluginConfig.MaxPlayers)
			{
				L.Verbose($"Expanding {"m_seatsFromShaft"} size from {((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft).Length} to {PluginConfig.MaxPlayers}.");
				Il2CppReferenceArray<ElevatorSeat> seatsFromShaft = __instance.m_seatsFromShaft;
				__instance.m_seatsFromShaft = new Il2CppReferenceArray<ElevatorSeat>((long)PluginConfig.MaxPlayers);
				for (int i = 0; i < ((Il2CppArrayBase<ElevatorSeat>)(object)seatsFromShaft).Length; i++)
				{
					int num = i % 4;
					((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft)[i] = ((Il2CppArrayBase<ElevatorSeat>)(object)seatsFromShaft)[num];
				}
			}
			if (playerId >= ((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft).Length)
			{
				L.Warning($"playerId {playerId} is past seats from shaft length: skipping call.");
				return false;
			}
			if ((Object)(object)((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft)[playerId] == (Object)null)
			{
				L.Warning($"playerId {playerId} has a null seat. Skipping call.");
				return false;
			}
			return true;
		}

		[HarmonyPatch("RegisterSpawnPoints")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool RegisterSpawnPoints__Prefix(ElevatorCage __instance)
		{
			L.LogExecutingMethod();
			__instance.m_spawnPoints = new Il2CppReferenceArray<PlayerSpawnpoint>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < PluginConfig.MaxPlayers; i++)
			{
				int num = i % 4;
				((Il2CppArrayBase<PlayerSpawnpoint>)(object)__instance.m_spawnPoints)[i] = PlayerManager.RegisterSpawnpoint((PlayerspawnpointType)0, i, ((Il2CppArrayBase<ElevatorSeat>)(object)__instance.m_seatsFromShaft)[num]);
			}
			return false;
		}

		[HarmonyPatch("PlaySeatOpenStraps")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool PlaySeatOpenStraps__Prefix(CellSoundPlayer sound, int playerId, bool isLocal)
		{
			if (playerId > 3)
			{
				L.Verbose("Skipping PlaySeatOpenStraps for playerId > 3.");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ElevatorRide))]
	public static class ElevatorRidePatch
	{
		[HarmonyPatch("StartPreReleaseSequence")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool StartPreReleaseSequence__Prefix(Action onDone)
		{
			L.LogExecutingMethod();
			return true;
		}

		[HarmonyPatch("Cleanup")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool Cleanup__Prefix()
		{
			L.LogExecutingMethod();
			return true;
		}

		[HarmonyPatch("Cleanup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		public static void Cleanup__Postfix()
		{
			L.LogExecutingMethod();
			if (ElevatorRide.ElevatorRideInProgress)
			{
				ElevatorRide.ElevatorRideInProgress = false;
				ElevatorRide.Current.m_shaftTop.Cleanup();
			}
		}
	}
	[HarmonyPatch(typeof(GearManager))]
	public static class GearManagerPatch
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Expected O, but got Unknown
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Expected O, but got Unknown
			L.Verbose("GearManager::Setup postfix");
			BotFavoritesData botFavoritesData = GearManager.BotFavoritesData;
			if (((Il2CppArrayBase<string>)(object)botFavoritesData.LastEquipped_Melee).Length < PluginConfig.MaxPlayers)
			{
				Il2CppStringArray lastEquipped_Melee = botFavoritesData.LastEquipped_Melee;
				Il2CppStringArray val = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
				for (int i = 0; i < ((Il2CppArrayBase<string>)(object)val).Length; i++)
				{
					if (i < ((Il2CppArrayBase<string>)(object)lastEquipped_Melee).Length)
					{
						((Il2CppArrayBase<string>)(object)val)[i] = ((Il2CppArrayBase<string>)(object)lastEquipped_Melee)[i];
					}
					else
					{
						((Il2CppArrayBase<string>)(object)val)[i] = "";
					}
				}
				botFavoritesData.LastEquipped_Melee = val;
			}
			if (((Il2CppArrayBase<string>)(object)botFavoritesData.LastEquipped_Standard).Length < PluginConfig.MaxPlayers)
			{
				Il2CppStringArray lastEquipped_Standard = botFavoritesData.LastEquipped_Standard;
				Il2CppStringArray val2 = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
				for (int j = 0; j < ((Il2CppArrayBase<string>)(object)val2).Length; j++)
				{
					if (j < ((Il2CppArrayBase<string>)(object)lastEquipped_Standard).Length)
					{
						((Il2CppArrayBase<string>)(object)val2)[j] = ((Il2CppArrayBase<string>)(object)lastEquipped_Standard)[j];
					}
					else
					{
						((Il2CppArrayBase<string>)(object)val2)[j] = "";
					}
				}
				botFavoritesData.LastEquipped_Standard = val2;
			}
			if (((Il2CppArrayBase<string>)(object)botFavoritesData.LastEquipped_Special).Length < PluginConfig.MaxPlayers)
			{
				Il2CppStringArray lastEquipped_Special = botFavoritesData.LastEquipped_Special;
				Il2CppStringArray val3 = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
				for (int k = 0; k < ((Il2CppArrayBase<string>)(object)val3).Length; k++)
				{
					if (k < ((Il2CppArrayBase<string>)(object)lastEquipped_Special).Length)
					{
						((Il2CppArrayBase<string>)(object)val3)[k] = ((Il2CppArrayBase<string>)(object)lastEquipped_Special)[k];
					}
					else
					{
						((Il2CppArrayBase<string>)(object)val3)[k] = "";
					}
				}
				botFavoritesData.LastEquipped_Special = val3;
			}
			if (((Il2CppArrayBase<string>)(object)botFavoritesData.LastEquipped_Class).Length < PluginConfig.MaxPlayers)
			{
				Il2CppStringArray lastEquipped_Class = botFavoritesData.LastEquipped_Class;
				Il2CppStringArray val4 = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
				for (int l = 0; l < ((Il2CppArrayBase<string>)(object)val4).Length; l++)
				{
					if (l < ((Il2CppArrayBase<string>)(object)lastEquipped_Class).Length)
					{
						((Il2CppArrayBase<string>)(object)val4)[l] = ((Il2CppArrayBase<string>)(object)lastEquipped_Class)[l];
					}
					else
					{
						((Il2CppArrayBase<string>)(object)val4)[l] = "";
					}
				}
				botFavoritesData.LastEquipped_Class = val4;
			}
			if (((Il2CppArrayBase<string>)(object)botFavoritesData.LastEquipped_HackingTool).Length >= PluginConfig.MaxPlayers)
			{
				return;
			}
			Il2CppStringArray lastEquipped_HackingTool = botFavoritesData.LastEquipped_HackingTool;
			Il2CppStringArray val5 = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
			for (int m = 0; m < ((Il2CppArrayBase<string>)(object)val5).Length; m++)
			{
				if (m < ((Il2CppArrayBase<string>)(object)lastEquipped_HackingTool).Length)
				{
					((Il2CppArrayBase<string>)(object)val5)[m] = ((Il2CppArrayBase<string>)(object)lastEquipped_HackingTool)[m];
				}
				else
				{
					((Il2CppArrayBase<string>)(object)val5)[m] = "";
				}
			}
			botFavoritesData.LastEquipped_HackingTool = val5;
		}
	}
	[HarmonyPatch(typeof(PlayerAgent))]
	public static class PlayerAgentPatch
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		public static bool PlayerCharacterFilter__Getter__Prefix(PlayerAgent __instance, ref DialogCharFilter __result)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected I4, but got Unknown
			L.LogExecutingMethod();
			int characterID = __instance.CharacterID;
			if (characterID > 3)
			{
				int num = characterID % 4;
				__result = (DialogCharFilter)(int)((Il2CppArrayBase<DialogCharFilter>)(object)__instance.m_playerCharacters)[num];
				L.Verbose($"Clamping {"CharacterID"} from {characterID} to {num}.");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerCoverageSystem))]
	public static class PlayerCoverageSystemPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake__Postfix()
		{
			L.LogExecutingMethod();
			if (((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys).Length < PluginConfig.MaxPlayers)
			{
				L.Verbose($"Expanding PlayerCoverageSystem::s_coverageKeys size from {((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys).Length} to {PluginConfig.MaxPlayers}.");
				PlayerCoverageSystem.s_coverageKeys = new Il2CppStructArray<int>((long)PluginConfig.MaxPlayers);
			}
		}

		[HarmonyPatch("GetCoverageKey", new Type[] { typeof(int) })]
		[HarmonyPrefix]
		public static bool GetCoverageKey__Prefix(ref int __result, int activeID)
		{
			L.LogExecutingMethod();
			if (activeID < 0)
			{
				return true;
			}
			if (activeID >= ((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys).Length)
			{
				L.Error($"{"activeID"} was greater than the size of s_coverageKeys ({((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys).Length}).");
				return true;
			}
			__result = ((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys)[activeID];
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerCoverageDataSet_Portal))]
	public static class PlayerCoverageDataSet_PortalPatch
	{
		[HarmonyPatch("SetupData")]
		[HarmonyPostfix]
		public static void SetupData__Postfix(PlayerCoverageDataSet_Portal? __instance)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			L.Verbose("PlayerCoverageDataSet_PortalPatch::SetupData__Postfix");
			L.Assert(__instance != null, "instance was null");
			__instance.m_coverageDatas = new Il2CppReferenceArray<PlayerCoverageData>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < ((Il2CppArrayBase<PlayerCoverageData>)(object)__instance.m_coverageDatas).Length; i++)
			{
				L.Verbose($"Instantiating PlayerCoverageData at index #{i} in m_coverageDatas.");
				((Il2CppArrayBase<PlayerCoverageData>)(object)__instance.m_coverageDatas)[i] = new PlayerCoverageData();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDialogManager))]
	public static class PlayerDialogManagerPatch
	{
		[HarmonyPatch("WantToStartDialog")]
		[HarmonyPatch(new Type[]
		{
			typeof(uint),
			typeof(PlayerAgent)
		})]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static bool WantToStartDialog__Prefix(uint dialogID, PlayerAgent source)
		{
			L.LogExecutingMethod();
			if ((Object)(object)source == (Object)null)
			{
				L.Verbose("Source was null.");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerManager))]
	public static class PlayerManagerPatch
	{
		[HarmonyPatch("GetSpawnPoint")]
		[HarmonyPrefix]
		public static bool GetSpawnPoint__Prefix(PlayerspawnpointType type, ref int referenceID)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			L.Verbose($"{"PlayerManagerPatch"}::{"GetSpawnPoint__Prefix"} ({"type"}: {type}, {"referenceID"}: {referenceID})");
			if (referenceID > 3)
			{
				int num = referenceID % 4;
				L.Verbose($"{"GetSpawnPoint__Prefix"} changed referenceID from {referenceID} to {num}.");
				referenceID = num;
			}
			return true;
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake__Postfix(PlayerManager? __instance)
		{
			L.Verbose("PlayerManagerPatch::Awake__Postfix");
			L.Assert((Object)(object)__instance != (Object)null, "__instance was null");
			L.Assert(((Il2CppArrayBase<List<PositionReservation>>)(object)__instance.BotAIData.PositionReservations).Length == PluginConfig.MaxPlayers, $"{"PositionReservations"} was {((Il2CppArrayBase<List<PositionReservation>>)(object)__instance.BotAIData.PositionReservations).Length} when the manual patch should have set it to {PluginConfig.MaxPlayers}.");
			L.Assert(((Il2CppArrayBase<List<ObjectReservation>>)(object)__instance.BotAIData.ObjectReservations).Length == PluginConfig.MaxPlayers, $"{"ObjectReservations"} was {((Il2CppArrayBase<List<ObjectReservation>>)(object)__instance.BotAIData.ObjectReservations).Length} when the manual patch should have set it to {PluginConfig.MaxPlayers}.");
			for (int i = 4; i < PluginConfig.MaxPlayers; i++)
			{
				L.Verbose($"Initializing BotAIData position and object reservation at index #{i}.");
				((Il2CppArrayBase<List<PositionReservation>>)(object)__instance.BotAIData.PositionReservations)[i] = new List<PositionReservation>((int)PluginConfig.MaxPlayers);
				((Il2CppArrayBase<List<ObjectReservation>>)(object)__instance.BotAIData.ObjectReservations)[i] = new List<ObjectReservation>((int)PluginConfig.MaxPlayers);
			}
		}

		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(PlayerManager __instance)
		{
			L.Verbose("PlayerManagerPatch::Setup__Postfix");
			L.Assert((Object)(object)__instance != (Object)null, "__instance was null");
			L.Verbose("Fixing available spawnpoints...");
			FixAvailableSpawnpoints(__instance);
			L.Verbose("Fixing player colors...");
			FixPlayerColors(__instance);
		}

		private static void FixPlayerColors(PlayerManager __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[4]
			{
				ColorExt.Hex("FFA500"),
				Color.yellow,
				Color.magenta,
				Color.white
			};
			Il2CppStructArray<Color> playerColors = __instance.m_playerColors;
			__instance.m_playerColors = new Il2CppStructArray<Color>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < PluginConfig.MaxPlayers; i++)
			{
				Color val = ((i < ((Il2CppArrayBase<Color>)(object)playerColors).Length) ? ((Il2CppArrayBase<Color>)(object)playerColors)[i] : array[i % array.Length]);
				L.Verbose($"Setting new player color at index #{i} to {val}.");
				((Il2CppArrayBase<Color>)(object)__instance.m_playerColors)[i] = val;
			}
			L.Verbose($"m_playerColors now contains {((Il2CppArrayBase<Color>)(object)__instance.m_playerColors).Count} colors.");
		}

		private static void FixAvailableSpawnpoints(PlayerManager playerManager)
		{
			int length = Enum.GetValues(typeof(PlayerspawnpointType)).Length;
			if (length != 5)
			{
				L.Warning($"{"PlayerspawnpointType"} contained {length} types, but {5} were expected. This may or may not work as expected!");
			}
			for (int i = 0; i < length; i++)
			{
				((Il2CppArrayBase<Il2CppReferenceArray<PlayerSpawnpoint>>)(object)playerManager.m_availableSpawnpoints)[i] = new Il2CppReferenceArray<PlayerSpawnpoint>((long)PluginConfig.MaxPlayers);
				L.Verbose($"Set available spawnpoint at index #{i} to new max player size {PluginConfig.MaxPlayers}.");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerVoiceManager))]
	public static class PlayerVoiceManagerPatch
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(PlayerVoiceManager __instance)
		{
			L.Verbose("PlayerVoiceManager::Setup postfix");
			if (((Il2CppArrayBase<PlayerVoice>)(object)__instance.m_playerVoices).Length < PluginConfig.MaxPlayers)
			{
				L.Verbose("Adjusting m_playerVoices size.");
				__instance.m_playerVoices = new Il2CppReferenceArray<PlayerVoice>((long)PluginConfig.MaxPlayers);
			}
		}
	}
	[HarmonyPatch(typeof(PUI_Compass))]
	public static class PUI_CompassPatch
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(PUI_Compass __instance)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			L.LogExecutingMethod();
			__instance.m_playerPingMarkers = new Il2CppReferenceArray<NavMarker>((long)PluginConfig.MaxPlayers);
			__instance.m_playerNameMarkers = new Il2CppReferenceArray<NavMarker>((long)PluginConfig.MaxPlayers);
			__instance.m_playerMarkersWorldPos = new Il2CppStructArray<Vector3>((long)PluginConfig.MaxPlayers);
			__instance.m_playerPingMarkersActive = new Il2CppStructArray<bool>((long)PluginConfig.MaxPlayers);
			__instance.m_playerNameMarkersVisible = new Il2CppStructArray<bool>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < PluginConfig.MaxPlayers; i++)
			{
				L.Verbose($"Setting up compass stuff at index #{i}.");
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerPingMarkers)[i] = __instance.SpawnCompassObj(__instance.m_playerMarkerPrefab, 0f, 0f, false).GetComponent<NavMarker>();
				((Component)((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerPingMarkers)[i]).transform.localEulerAngles = new Vector3(0f, 0f, 180f);
				((Component)((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerPingMarkers)[i]).transform.localScale = new Vector3(__instance.m_navMarkerScale, __instance.m_navMarkerScale, __instance.m_navMarkerScale);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerPingMarkers)[i].SetVisible(false);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerPingMarkers)[i].SetPinEnabled(true);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i] = __instance.SpawnCompassObj(__instance.m_playerMarkerPrefab, 0f, 0f, false).GetComponent<NavMarker>();
				((Component)((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i]).transform.localScale = new Vector3(__instance.m_navMarkerScale, __instance.m_navMarkerScale, __instance.m_navMarkerScale);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i].SetStyle((eNavMarkerStyle)12);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i].SetState((NavMarkerState)1);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i].SetVisible(false);
				((Il2CppArrayBase<NavMarker>)(object)__instance.m_playerNameMarkers)[i].SetPinEnabled(false);
				((Il2CppArrayBase<bool>)(object)__instance.m_playerPingMarkersActive)[i] = false;
			}
		}
	}
	[HarmonyPatch(typeof(SNet_Core))]
	public static class SNet_CorePatch
	{
		[HarmonyPatch("GetBotNickname")]
		[HarmonyPostfix]
		public static void GetBotNickname__Postfix(ref string __result, int characterIndex)
		{
			if (characterIndex > 3)
			{
				__result = PluginConfig.GetExtraSlotNickname(characterIndex);
			}
		}
	}
	[HarmonyPatch(typeof(SNet_LobbyManager))]
	public class SNet_LobbyManagerPatch
	{
		[HarmonyPatch("CreateLobby")]
		[HarmonyPrefix]
		public static bool CreateLobby__Prefix(SNet_LobbySettings settings, bool leaveSessionHub)
		{
			L.LogExecutingMethod();
			if (settings.m_playerLimit < PluginConfig.MaxPlayers)
			{
				settings.m_playerLimit = PluginConfig.MaxPlayers;
				L.Verbose($"Expanding m_playerLimit to {PluginConfig.MaxPlayers}.");
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SNet_PlayerSlotManager))]
	public static class SNet_PlayerSlotManagerPatch
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		public static void Setup__Postfix(SNet_PlayerSlotManager __instance)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			L.LogExecutingMethod();
			__instance.PlayerSlots = new Il2CppReferenceArray<SNet_Slot>((long)PluginConfig.MaxPlayers);
			__instance.CharacterSlots = new Il2CppReferenceArray<SNet_Slot>((long)PluginConfig.MaxPlayers);
			__instance.m_playerSlotPermissions = new Il2CppStructArray<SlotPermission>((long)PluginConfig.MaxPlayers);
			for (int i = 0; i < PluginConfig.MaxPlayers; i++)
			{
				((Il2CppArrayBase<SNet_Slot>)(object)__instance.PlayerSlots)[i] = new SNet_Slot(i);
				((Il2CppArrayBase<SNet_Slot>)(object)__instance.CharacterSlots)[i] = new SNet_Slot(i);
				__instance.InternalSetSlotPermission(i, (SlotPermission)0, true);
				if (i > 3)
				{
					((Il2CppArrayBase<SlotPermission>)(object)__instance.m_playerSlotPermissions)[i] = PluginConfig.GetExtraSlotPermission(i);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SNet_SessionHub))]
	public static class SNet_SessionHubPatch
	{
		[HarmonyPatch("TryAddBotToSession")]
		[HarmonyPostfix]
		public static void TryAddBotToSession__Postfix(SNet_SessionHub __instance, ref bool __result, SNet_Player bot)
		{
			L.LogExecutingMethod($"{"__result"}: {__result}");
			if (!__result && bot.IsBot && SNet.IsMaster)
			{
				if (__instance.PlayersInSession.Count > PluginConfig.MaxPlayers - 1 || __instance.PlayersInSession.Contains(bot))
				{
					L.Verbose("No room to add another bot.");
					return;
				}
				L.Verbose("Adding extra bot.");
				__instance.AddPlayerToSession(bot, true);
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(SteamMatchmaking))]
	public static class SteamMatchmakingPatch
	{
		[HarmonyPatch("CreateLobby")]
		[HarmonyPrefix]
		public static bool CreateLobby__Prefix(ELobbyType eLobbyType, ref int cMaxMembers)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			L.LogExecutingMethod($"{eLobbyType}, {cMaxMembers}");
			if (cMaxMembers < PluginConfig.MaxPlayers)
			{
				cMaxMembers = PluginConfig.MaxPlayers;
				L.Verbose($"Expanding CreateLobby cMaxMembers to {PluginConfig.MaxPlayers}.");
			}
			return true;
		}
	}
}
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		((ICollection<T>)_items).CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}