using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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 System.Text.Json;
using AIGraph;
using AK;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using BoosterImplants;
using CellMenu;
using ChainedPuzzles;
using Enemies;
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 TMPro;
using UnityEngine;
using UnityEngine.Events;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GTFO.LobbyExpansion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+3a6479d1f1454e69cb86c099d41e95902d0d59c9")]
[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.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.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 CoolButton
{
private const float ALPHA_OVER = 1f;
private const float ALPHA_OVER_DISABLED = 0.25f;
private const float ALPHA_OUT = 0.66f;
private const float ALPHA_OUT_DISABLED = 0.25f;
private static readonly Color COLOR_OUT = new Color(1f, 1f, 1f, 0.66f);
private static readonly Color COLOR_HOVER = new Color(1f, 1f, 1f, 1f);
private static readonly Color COLOR_DISABLED = new Color(1f, 1f, 1f, 0.25f);
private static GameObject _squareButtonPrefab = null;
public static void SetCoolButtonEnabled(this CM_Item button, bool enabled)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)button == (Object)null))
{
button.m_spriteAlphaOut = (enabled ? 0.66f : 0.25f);
button.m_spriteAlphaOver = (enabled ? 1f : 0.25f);
button.m_spriteColorOut = (enabled ? COLOR_OUT : COLOR_DISABLED);
button.m_spriteColorOver = (enabled ? COLOR_HOVER : COLOR_DISABLED);
button.OnHoverOut();
((Behaviour)button.m_collider).enabled = enabled;
}
}
internal static void Setup(CM_PageLoadout pageLoadout)
{
if (!((Object)(object)_squareButtonPrefab != (Object)null))
{
_squareButtonPrefab = CreateButtonPrefab(pageLoadout);
}
}
public static CM_Item InstantiateSquareButton(Transform parent, Vector3 position, bool hideText = false, bool displayArrow = false, bool flipArrow = false)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Expected O, but got Unknown
GameObject val = Object.Instantiate<GameObject>(_squareButtonPrefab, parent);
val.gameObject.SetActive(true);
val.transform.localPosition = position;
CM_Item component = val.GetComponent<CM_Item>();
if (hideText)
{
((Component)val.transform.Find("MainText")).gameObject.SetActive(false);
}
Transform val2 = val.transform.Find("Arrow");
((Component)val2).gameObject.SetActive(displayArrow);
if (flipArrow)
{
val2.localRotation = Quaternion.Euler(0f, 0f, -90f);
}
component.m_hoverSpriteArray = Il2CppReferenceArray<SpriteRenderer>.op_Implicit(((IEnumerable<SpriteRenderer>)val.gameObject.GetComponentsInChildren<SpriteRenderer>(true)).ToArray());
foreach (SpriteRenderer item in (Il2CppArrayBase<SpriteRenderer>)(object)component.m_hoverSpriteArray)
{
item.color = new Color(1f, 1f, 1f, 0.66f);
}
component.m_spriteAlphaOver = 1f;
component.m_spriteAlphaOut = 0.66f;
component.m_alphaSpriteOnHover = true;
component.m_onBtnPress = new UnityEvent();
((RectTransformComp)component).Setup();
return component;
}
private static GameObject CreateButtonPrefab(CM_PageLoadout pageLoadout)
{
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: 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_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_022d: Unknown result type (might be due to invalid IL or missing references)
CM_Item component = Object.Instantiate<GameObject>(pageLoadout.m_readyButtonPrefab).GetComponent<CM_Item>();
GameObject gameObject = ((Component)component).gameObject;
Transform transform = gameObject.transform;
Object.Destroy((Object)(object)component);
component = gameObject.AddComponent<CM_Item>();
Object.Destroy((Object)(object)((Component)transform.Find("PressAndHold")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("ProgressFillBase")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("ProgressFill")).gameObject);
Object.Destroy((Object)(object)((Component)transform.Find("Progress")).gameObject);
transform.Find("MainText").localPosition = new Vector3(-20f, -18f, 0f);
component.SetText("<color=white>P1</color>");
Transform obj = transform.Find("Arrow");
obj.localPosition = new Vector3(0f, -40f, 0f);
obj.localScale = new Vector3(0.3f, 0.3f, 1f);
Transform val = transform.Find("Box");
val.localPosition = new Vector3(0f, -40f, 0f);
for (int i = 0; i < val.childCount; i++)
{
Transform child = val.GetChild(i);
switch (((Object)child).name)
{
case "StretchLineT":
child.localScale = new Vector3(0.22f, 4f, 1f);
child.localPosition = new Vector3(-45f, 45f, 0f);
break;
case "StretchLineB":
child.localScale = new Vector3(0.22f, 4f, 1f);
child.localPosition = new Vector3(-45f, -45f, 0f);
break;
case "StretchLineR":
child.localPosition = new Vector3(45f, 45f, 0f);
break;
case "StretchLineL":
child.localScale = new Vector3(0.5f, 1f, 1f);
child.localPosition = new Vector3(-45f, 45f, 0f);
break;
}
}
BoxCollider2D component2 = ((Component)component).GetComponent<BoxCollider2D>();
component2.size = new Vector2(80f, 80f);
((Collider2D)component2).offset = new Vector2(0f, -40f);
((Object)component).name = "LobbyExpander_SwitchLobbyButton";
Object.DontDestroyOnLoad((Object)(object)gameObject);
((Object)gameObject).hideFlags = (HideFlags)61;
gameObject.SetActive(false);
return gameObject;
}
}
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);
}
}
[Conditional("DEBUG")]
internal static void DebugWarning(object data)
{
Warning("-------------------------------------------");
Warning("-------------- DEBUG WARNING --------------");
Warning(Format(data));
Warning("-------------------------------------------");
}
[Conditional("DEBUG")]
internal static void Debug(object data)
{
Logger.LogDebug((object)Format(data));
}
internal static void Info(object data)
{
Logger.LogMessage((object)Format(data));
}
[Conditional("DEBUG")]
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));
}
[Conditional("DEBUG")]
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;
}
_ = method.DeclaringType?.FullName;
_ = method.Name;
if (!string.IsNullOrWhiteSpace(parameterInfo))
{
_ = " (" + parameterInfo + ")";
}
}
private static string Format(object msg)
{
return msg.ToString() ?? "";
}
}
public class LobbyExpansionPlayerCount
{
public byte MaxPlayers { get; set; } = 8;
}
public class LobbyExpansionConfig
{
public Dictionary<int, SlotPermission>? SlotPermissions { get; set; } = new Dictionary<int, SlotPermission>();
public List<string>? CustomExtraBotNames { get; set; } = new List<string>();
}
public class Pagination
{
public int PageIndex { get; set; }
public event Action? OnPageChanged;
public bool CanPageUp()
{
int num = (int)Math.Ceiling((double)(int)PluginConfig.MaxPlayers / 4.0) - 1;
return PageIndex < num;
}
public bool PageUp()
{
if (CanPageUp())
{
PageIndex++;
this.OnPageChanged?.Invoke();
return true;
}
return false;
}
public bool CanPageDown()
{
return PageIndex > 0;
}
public bool PageDown()
{
if (CanPageDown())
{
PageIndex--;
this.OnPageChanged?.Invoke();
return true;
}
return false;
}
public static int GetLocalPlayerPageIndexFromPillar()
{
foreach (CM_PlayerLobbyBar item in (Il2CppArrayBase<CM_PlayerLobbyBar>)(object)CM_PageLoadout.Current.m_playerLobbyBars)
{
if (item.m_player.IsLocal)
{
return GetPageFromSlotIndex(item.PlayerSlotIndex);
}
}
return 0;
}
public static int GetLocalPlayerPageFromSlotIndex()
{
return GetPageFromSlotIndex(SNet.LocalPlayer.PlayerSlot.index);
}
public static int GetPageFromSlotIndex(int slotIndex)
{
return (int)Math.Floor((float)slotIndex / 4f);
}
}
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.1.0")]
public class Plugin : BasePlugin
{
private Harmony _harmony;
public override void Load()
{
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Expected O, but got Unknown
try
{
PluginConfig.Load();
}
catch (Exception ex)
{
L.Error("Failed to load plugin config?!");
L.Error(ex.GetType().Name + ": " + ex.Message);
L.Warning("StackTrace:\n" + ex.StackTrace);
}
try
{
HashSet<Type> hashSet = new HashSet<Type>();
foreach (ManualPatch item in 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(),
new CM_PageLoadoutDisplayClassManualPatch()
})
{
Type type = item.GetType();
if (hashSet.Contains(type))
{
string obj = $"The same patch {type} is being applied twice. Fix this.";
L.Fatal(obj);
throw new PatchingException(obj);
}
item.Apply();
hashSet.Add(type);
}
}
catch (Exception data)
{
L.Fatal("An error occurred while applying manual patches:");
L.Fatal(data);
return;
}
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 const byte DEFAULT_MAX_PLAYERS = 8;
private const string CONFIG_FILE_NAME = "LobbyExpansionConfig.json";
private const string USER_CONFIG_FILE_NAME = "LobbyExpansionConfig_UserData.json";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true
};
private static readonly string _configPath = Path.Combine(Paths.ConfigPath, "LobbyExpansionConfig.json");
private static readonly string _configPathUserData = Path.Combine(Paths.ConfigPath, "LobbyExpansionConfig_UserData.json");
internal static byte MaxPlayers = 8;
private static LobbyExpansionPlayerCount _configPlayerCount = new LobbyExpansionPlayerCount();
private static LobbyExpansionConfig _configUserData = new LobbyExpansionConfig();
internal static void Load()
{
LoadCustomPlayerCount();
if (!File.Exists(_configPathUserData))
{
SaveUserData();
}
_configUserData = JsonSerializer.Deserialize<LobbyExpansionConfig>(File.ReadAllText(_configPathUserData), _serializerOptions) ?? new LobbyExpansionConfig();
LobbyExpansionConfig configUserData = _configUserData;
if (configUserData.SlotPermissions == null)
{
Dictionary<int, SlotPermission> dictionary2 = (configUserData.SlotPermissions = new Dictionary<int, SlotPermission>());
}
configUserData = _configUserData;
if (configUserData.CustomExtraBotNames == null)
{
List<string> list2 = (configUserData.CustomExtraBotNames = new List<string>());
}
}
private static void LoadCustomPlayerCount()
{
if (File.Exists(_configPath))
{
_configPlayerCount = JsonSerializer.Deserialize<LobbyExpansionPlayerCount>(File.ReadAllText(_configPath), _serializerOptions) ?? new LobbyExpansionPlayerCount();
if (_configPlayerCount.MaxPlayers < 4)
{
L.Error("ConfigFile: MaxPlayers must be greater or equal to '4'!");
MaxPlayers = 8;
return;
}
L.Info($"Loaded custom player count from config file: {MaxPlayers} (default) -> {_configPlayerCount.MaxPlayers} (config)");
MaxPlayers = _configPlayerCount.MaxPlayers;
}
}
private static void SaveUserData()
{
string contents = JsonSerializer.Serialize(_configUserData, _serializerOptions);
File.WriteAllText(_configPathUserData, contents);
}
public static SlotPermission GetExtraSlotPermission(int slotIndex)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
return _configUserData.SlotPermissions.GetValueOrDefault(slotIndex, (SlotPermission)4);
}
public static void SetExtraLobbySlotPermissions(int slotIndexMinusOne, SlotPermission permission)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
int num = slotIndexMinusOne + 1;
L.Info($"SetExtraLobbySlotPermissions called: slotIndex:{num}, SlotPermission:{permission}");
_configUserData.SlotPermissions[num] = permission;
SaveUserData();
}
public static string GetExtraSlotNickname(int characterIndex)
{
int num = characterIndex - 4;
if (_configUserData.CustomExtraBotNames.Count > 0 && num < _configUserData.CustomExtraBotNames.Count)
{
string text = _configUserData.CustomExtraBotNames[num];
if (!string.IsNullOrWhiteSpace(text))
{
return text;
}
}
return characterIndex switch
{
4 => "Schaeffer",
5 => "North",
6 => "Henriksson",
7 => "Maddox",
_ => $"Prisoner{characterIndex}",
};
}
}
internal static class PluginInfo
{
internal const string Guid = "GTFO.LobbyExpansion";
internal const string Name = "GTFO.LobbyExpansion";
internal const string Version = "1.1.0";
}
}
namespace GTFO.LobbyExpansion.Util
{
public static class CoroutineHelpers
{
public static IEnumerator NextFrame(Action action)
{
yield return null;
action?.Invoke();
}
}
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 const byte NOP = 144;
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 num = Memory.FindSignatureInIl2CppMethod(flag ? Memory.GetIl2CppConstructorAddress(TargetType, parameterTypes) : Memory.GetIl2CppMethodAddress(TargetType, patch.Method, parameterTypes), 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);
}
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}.");
}
return *(nint*)(void*)(IntPtr)(il2CppMethodInfoPointerFieldForGeneratedMethod.GetValue(null) ?? throw new NullReferenceException($"Method info pointer field for method {methodBase} of {type.FullName ?? type.Name} was null."));
}
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.GetValueOrDefault(3000L), signature2.Bytes, signature2.Mask);
}
public static nint FindSignatureInIl2CppMethod<T>(string methodName, string signature, long blockSize = 3000L) where T : Il2CppObjectBase
{
return FindSignatureInIl2CppMethod(GetIl2CppMethodAddress<T>(methodName), 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
{
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__ReadOnlySingleElementList<Patch>(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_PageLoadoutDisplayClassManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(__c__DisplayClass38_1);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(new Patch
{
Method = "_ShowPermissionWindow_b__1",
Description = "NOP out Il2Cpp check and assignment of CellSettingsManager.SettingsData.Player.LobbySlotPermissions[num] = this.permission;",
Pattern = "48 85 C9 74 5C 3B 71 18 73 7D 48 63 C6 89 54 81 20",
Offset = 0,
Bytes = ManualPatch.GenerateNop(17)
}));
}
}
public class CM_PageLoadoutManualPatch : ManualPatch
{
protected override Type TargetType { get; } = typeof(CM_PageLoadout);
protected override void SetupPatches()
{
base.Patches.AddRange(new <>z__ReadOnlySingleElementList<Patch>(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[13]
{
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 = "Update",
Description = "Adjust CM_PageMap::UpdateSyncedCursorVisibility() (Inlined into Update()!) for (int i = 0; i < 4; i++) to new max players.",
Pattern = "83 FB 04 0F 8C 55 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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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__ReadOnlySingleElementList<Patch>(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)
{
if (((Il2CppArrayBase<PlayerBoosterImplantState>)(object)__instance.m_boosterPlayers).Length < PluginConfig.MaxPlayers)
{
__instance.m_boosterPlayers = new Il2CppReferenceArray<PlayerBoosterImplantState>((long)PluginConfig.MaxPlayers);
}
}
}
[HarmonyPatch(typeof(CM_PageExpeditionSuccess))]
public static class CM_PageExpeditionSuccessPatch
{
private static bool _needPositionUpdate;
private static DateTime _lastVisibilityUpdate = DateTime.Now;
private static readonly Pagination _pagination = new Pagination();
private static CM_Item _buttonPageUp = null;
private static CM_Item _buttonPageDown = null;
[HarmonyPatch("OnEnable")]
[HarmonyPostfix]
public static void OnEnable__Postfix(CM_PageExpeditionSuccess __instance)
{
_pagination.PageIndex = 0;
UpdateCustomButtons();
_needPositionUpdate = true;
UpdateVisiblePlayerReports(__instance);
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix(CM_PageExpeditionSuccess __instance)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
if (_needPositionUpdate)
{
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);
}
if (Input.GetKeyDown((KeyCode)281))
{
_pagination.PageDown();
}
if (Input.GetKeyDown((KeyCode)280))
{
_pagination.PageUp();
}
}
private static void UpdateVisiblePlayerReports(CM_PageExpeditionSuccess page)
{
if (page.m_playerReports == null)
{
return;
}
Il2CppReferenceArray<SNet_Slot> playerSlots = SNet.Slots.PlayerSlots;
int num = _pagination.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)
{
active = false;
}
else if (i >= num2)
{
active = false;
}
else if (i >= ((Il2CppArrayBase<SNet_Slot>)(object)playerSlots).Count || (Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)playerSlots)[i].player == (Object)null)
{
active = false;
}
((Component)((Il2CppArrayBase<CM_PageSuccess_PrisonerEvaluation>)(object)page.m_playerReports)[i]).gameObject.SetActive(active);
}
}
}
private static void OnPageChanged()
{
UpdateVisiblePlayerReports(MainMenuGuiLayer.Current.PageExpeditionSuccess);
UpdateCustomButtons();
}
private static void UpdateCustomButtons()
{
bool enabled = _pagination.CanPageDown();
bool enabled2 = _pagination.CanPageUp();
_buttonPageDown.SetCoolButtonEnabled(enabled);
_buttonPageUp.SetCoolButtonEnabled(enabled2);
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageExpeditionSuccess __instance, MainMenuGuiLayer guiLayer)
{
CM_PageExpeditionSuccess __instance2 = __instance;
_pagination.OnPageChanged += OnPageChanged;
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
_buttonPageUp = CoolButton.InstantiateSquareButton(((Component)__instance2.m_btnLeaveExpedition).transform, new Vector3(320f, 42f, 0f), hideText: true, displayArrow: true);
_buttonPageDown = CoolButton.InstantiateSquareButton(((Component)__instance2.m_btnLeaveExpedition).transform, new Vector3(-320f, 42f, 0f), hideText: true, displayArrow: true, flipArrow: true);
UpdateCustomButtons();
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
});
})), (Action)null);
}
}
[HarmonyPatch(typeof(__c__DisplayClass38_1))]
public class CM_PageLoadoutDisplayClassPatch
{
[HarmonyPatch("_ShowPermissionWindow_b__1")]
public static void Prefix(__c__DisplayClass38_1 __instance)
{
//IL_0065: 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)
int num = 0;
for (int i = 0; i < __instance.field_Public___c__DisplayClass38_0_0.playerIndex; i++)
{
SNet_Player player = ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player;
if ((Object)(object)player == (Object)null || !player.IsLocal)
{
num++;
}
}
if (num < 3)
{
((Il2CppArrayBase<SlotPermission>)(object)CellSettingsManager.SettingsData.Player.LobbySlotPermissions)[num] = __instance.permission;
}
else
{
PluginConfig.SetExtraLobbySlotPermissions(num, __instance.permission);
}
}
}
[HarmonyPatch(typeof(CM_PageLoadout))]
public static class CM_PageLoadoutPatch
{
private static CM_Item _centerButton = null;
private static CM_Item _buttonPageDown = null;
private static CM_Item _buttonPageUp = null;
private const string DECOR_TEXT = "//: Lobby Page Switcher";
private static readonly Pagination _pagination = new Pagination();
[HarmonyPatch("Setup")]
[HarmonyPrefix]
public static bool Setup__Prefix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
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++)
{
GameObject val2 = new GameObject($"Player{j + 1}Root");
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_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: 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_0053: 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_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: 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_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
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++)
{
_ = $"Player{i + 1}Root";
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 = _pagination.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)
{
((Component)((Il2CppArrayBase<Transform>)(object)__instance.m_playerInfoHolders)[j]).gameObject.transform.position = new Vector3(5000f, 5000f, 5000f);
}
else if (j >= 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];
}
}
}
public static void UpdatePlayerPillars()
{
CM_PageLoadout.Current.ArrangePlayerPillarSpacing();
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix(CM_PageLoadout __instance)
{
if (Input.GetKeyDown((KeyCode)281) && _pagination.PageDown())
{
UpdateCustomButtons();
}
if (Input.GetKeyDown((KeyCode)280) && _pagination.PageUp())
{
UpdateCustomButtons();
}
}
[HarmonyPatch("ApplyPlayerSlotPermissionsFromSettings")]
[HarmonyPostfix]
public static void ApplyPlayerSlotPermissionsFromSettings__Postfix(CM_PageLoadout __instance)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: 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)
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)
{
SNet.Core.OnSlotsStatusChanged();
}
if (SNet_Events.OnLobbyPermissionsSet != null)
{
SNet_Events.OnLobbyPermissionsSet.Invoke();
}
}
[HarmonyPatch("OnDisable")]
[HarmonyPostfix]
public static void OnDisable__Postfix()
{
}
private static void UpdateCustomButtons()
{
bool enabled = _pagination.CanPageDown();
bool enabled2 = _pagination.CanPageUp();
_buttonPageDown.SetCoolButtonEnabled(enabled);
_buttonPageUp.SetCoolButtonEnabled(enabled2);
_centerButton.SetText($"<color=white>P{_pagination.PageIndex + 1}</color>");
}
private static void OnPageChanged()
{
UpdatePlayerPillars();
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageLoadout __instance, MainMenuGuiLayer guiLayer)
{
CM_PageLoadout __instance2 = __instance;
if ((Object)(object)CM_PageLoadout.Current == (Object)null)
{
return;
}
_pagination.OnPageChanged += OnPageChanged;
CoolButton.Setup(__instance2);
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_0005: 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_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: 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)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
Transform transform = new GameObject("LobbySwitcherHolder").transform;
transform.SetParent(__instance2.m_readyButtonAlign.parent);
transform.localPosition = __instance2.m_readyButtonAlign.localPosition + new Vector3(0f, 1150f, 0f);
transform.localScale = Vector3.one * 0.9f;
Transform obj = Object.Instantiate<Transform>(__instance2.m_readyButtonAlign.Find("DecorText"), transform);
((Component)obj).transform.localPosition = new Vector3(100f, 0f, 0f);
((Component)obj).transform.localScale = Vector3.one;
((Component)obj).gameObject.SetActive(true);
((TMP_Text)((Component)obj).GetComponent<TextMeshPro>()).SetText("//: Lobby Page Switcher", true);
_centerButton = CoolButton.InstantiateSquareButton(transform, Vector3.zero);
_buttonPageDown = CoolButton.InstantiateSquareButton(transform, new Vector3(-110f, 0f, 0f), hideText: true, displayArrow: true, flipArrow: true);
_buttonPageUp = CoolButton.InstantiateSquareButton(transform, new Vector3(110f, 0f, 0f), hideText: true, displayArrow: true);
UpdateCustomButtons();
_centerButton.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
int localPlayerPageIndexFromPillar = Pagination.GetLocalPlayerPageIndexFromPillar();
if (_pagination.PageIndex != localPlayerPageIndexFromPillar)
{
_pagination.PageIndex = localPlayerPageIndexFromPillar;
UpdatePlayerPillars();
}
UpdateCustomButtons();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
UpdateCustomButtons();
});
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
UpdateCustomButtons();
});
})), (Action)null);
}
}
[HarmonyPatch(typeof(CM_PageMap))]
public static class CM_PageMapPatch
{
private static readonly Pagination _pagination = new Pagination();
private static CM_Item _buttonCenter = null;
private static CM_Item _buttonPageUp = null;
private static CM_Item _buttonPageDown = null;
private static void OnPageChanged()
{
UpdateCustomButtons();
UpdateAllPlayerInventories();
}
private static void UpdateCustomButtons()
{
_buttonPageUp.SetCoolButtonEnabled(_pagination.CanPageUp());
_buttonPageDown.SetCoolButtonEnabled(_pagination.CanPageDown());
_buttonCenter.SetText($"<color=white>P{_pagination.PageIndex + 1}</color>");
}
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(CM_PageMap __instance)
{
CM_PageMap __instance2 = __instance;
_pagination.OnPageChanged += OnPageChanged;
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("LobbyExpansion_PageButtonRoot");
val.transform.SetParent(((Component)__instance2.m_btnGotoObjectives).transform);
val.transform.localPosition = new Vector3(40f, -200f, 0f);
val.transform.localScale = Vector3.one * 0.6f;
_buttonCenter = CoolButton.InstantiateSquareButton(val.transform, Vector3.zero);
_buttonPageDown = CoolButton.InstantiateSquareButton(val.transform, new Vector3(-40f, 80f, 0f), hideText: true, displayArrow: true);
((Component)_buttonPageDown).transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
_buttonPageUp = CoolButton.InstantiateSquareButton(val.transform, new Vector3(-40f, -160f, 0f), hideText: true, displayArrow: true, flipArrow: true);
((Component)_buttonPageUp).transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
UpdateCustomButtons();
_buttonCenter.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
int localPlayerPageFromSlotIndex = Pagination.GetLocalPlayerPageFromSlotIndex();
if (_pagination.PageIndex != localPlayerPageFromSlotIndex)
{
_pagination.PageIndex = localPlayerPageFromSlotIndex;
UpdateAllPlayerInventories();
}
UpdateCustomButtons();
});
_buttonPageDown.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageDown();
});
_buttonPageUp.OnBtnPressCallback = Action<int>.op_Implicit((Action<int>)delegate
{
_pagination.PageUp();
});
})), (Action)null);
}
private static void UpdateAllPlayerInventories()
{
CM_PageMap current = CM_PageMap.Current;
int num = 0;
Enumerator<SNet_Player> enumerator = SNet.Slots.SlottedPlayers.GetEnumerator();
while (enumerator.MoveNext())
{
SNet_Player current2 = enumerator.Current;
if (current2.IsInSlot)
{
current.UpdatePlayerInventory(current2, num);
num++;
}
}
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
public static void Update__Postfix()
{
if (Input.GetKeyDown((KeyCode)281))
{
_pagination.PageDown();
}
if (Input.GetKeyDown((KeyCode)280))
{
_pagination.PageUp();
}
}
[HarmonyPatch("UpdatePlayerInventory")]
[HarmonyPostfix]
public static void UpdatePlayerInventory__Postfix(CM_PageMap __instance, SNet_Player player, int count)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: 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(position.x, position.y);
int num = 0;
for (int num2 = count; num2 > 3; num2 -= 4)
{
num++;
}
if (_pagination.PageIndex != num)
{
position2.x = 5000f;
}
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)
{
if (index > 3)
{
int num = index % 4;
index = num;
}
return true;
}
}
[HarmonyPatch(typeof(CP_PlayerScanner))]
public static class CP_PlayerScannerPatch
{
[HarmonyPatch("StartScan")]
[HarmonyPrefix]
public static bool StartScan__Prefix(CP_PlayerScanner __instance)
{
if (((Il2CppArrayBase<float>)(object)__instance.m_scanSpeeds).Length < PluginConfig.MaxPlayers)
{
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)
{
if (characterIndex > 3)
{
characterIndex %= 4;
}
return true;
}
}
[HarmonyPatch(typeof(DiscordManager))]
public class DiscordManagerPatch
{
[HarmonyPatch("GetCharacterNickname")]
[HarmonyPostfix]
public static void GetCharacterNickname__Postfix(ref string __result, int characterIndex)
{
if (characterIndex > 3)
{
__result = PluginConfig.GetExtraSlotNickname(characterIndex);
}
}
}
[HarmonyPatch(typeof(DramaManager))]
public static class DramaManagerPatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix()
{
ResetDramaFieldsProperly();
}
[HarmonyPatch("OnLevelCleanup")]
[HarmonyPostfix]
public static void OnLevelCleanup__Postfix()
{
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)
{
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)
{
__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)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ElevatorRide))]
public static class ElevatorRidePatch
{
[HarmonyPatch("StartPreReleaseSequence")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool StartPreReleaseSequence__Prefix(Action onDone)
{
return true;
}
[HarmonyPatch("Cleanup")]
[HarmonyPrefix]
[HarmonyWrapSafe]
public static bool Cleanup__Prefix()
{
return true;
}
[HarmonyPatch("SpawnShaftSegments")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void SpawnShaftSegments__Postfix(ElevatorRide __instance)
{
ElevatorRide __instance2 = __instance;
ElevatorShaftTop shaftTop = __instance2.m_shaftTop;
Il2CppReferenceArray<ElevatorSeat> elevatorSeats = shaftTop.m_elevatorSeats;
shaftTop.m_elevatorSeats = new Il2CppReferenceArray<ElevatorSeat>((long)PluginConfig.MaxPlayers);
for (int i = 0; i < PluginConfig.MaxPlayers; i++)
{
int num = i % 4;
((Il2CppArrayBase<ElevatorSeat>)(object)shaftTop.m_elevatorSeats)[i] = ((Il2CppArrayBase<ElevatorSeat>)(object)elevatorSeats)[num];
}
Il2CppReferenceArray<Animator> hSULoadingArmAnims = shaftTop.m_HSULoadingArmAnims;
shaftTop.m_HSULoadingArmAnims = new Il2CppReferenceArray<Animator>((long)PluginConfig.MaxPlayers);
for (int j = 0; j < PluginConfig.MaxPlayers; j++)
{
int num2 = j % 4;
((Il2CppArrayBase<Animator>)(object)shaftTop.m_HSULoadingArmAnims)[j] = ((Il2CppArrayBase<Animator>)(object)hSULoadingArmAnims)[num2];
}
((MonoBehaviour)__instance2).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
ElevatorCage elevatorCage = __instance2.m_elevatorCage;
Il2CppReferenceArray<Transform> hSUAligns = elevatorCage.m_HSUAligns;
elevatorCage.m_HSUAligns = new Il2CppReferenceArray<Transform>((long)PluginConfig.MaxPlayers);
for (int k = 0; k < PluginConfig.MaxPlayers; k++)
{
int num3 = k % 4;
((Il2CppArrayBase<Transform>)(object)elevatorCage.m_HSUAligns)[k] = ((Il2CppArrayBase<Transform>)(object)hSUAligns)[num3];
}
})));
}
[HarmonyPatch("Cleanup")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void Cleanup__Postfix()
{
if (ElevatorRide.ElevatorRideInProgress)
{
ElevatorRide.ElevatorRideInProgress = false;
ElevatorRide.Current.m_shaftTop.Cleanup();
}
}
}
[HarmonyPatch(typeof(ElevatorSeat))]
public class ElevatorSeatPatch
{
private static int _frame;
[HarmonyPatch("SkipPreReleaseSequence")]
[HarmonyPostfix]
[HarmonyWrapSafe]
public static void SkipPreReleaseSequence__Postfix(CellSoundPlayer sound)
{
CellSoundPlayer sound2 = sound;
sound2.Stop();
int frameCount = Time.frameCount;
if (_frame != frameCount)
{
CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(CoroutineHelpers.NextFrame(delegate
{
sound2.Post(EVENTS.PLAY_15_ELEVATOR_RELEASE, true);
})), (Action)null);
}
_frame = frameCount;
}
}
[HarmonyPatch(typeof(EnemyAgent))]
public class EnemyAgentArenaDimensionPatch
{
[HarmonyPatch("GetArenaDimension")]
[HarmonyPrefix]
public static void GetArenaDimension__Prefix(ref uint slotIndex)
{
slotIndex %= 4u;
}
}
[HarmonyPatch(typeof(GearManager))]
public static class GearManagerPatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix()
{
BotFavoritesData botFavoritesData = GearManager.BotFavoritesData;
Il2CppStringArray original = botFavoritesData.LastEquipped_Melee;
if (Expand(ref original))
{
botFavoritesData.LastEquipped_Melee = original;
}
Il2CppStringArray original2 = botFavoritesData.LastEquipped_Standard;
if (Expand(ref original2))
{
botFavoritesData.LastEquipped_Standard = original2;
}
Il2CppStringArray original3 = botFavoritesData.LastEquipped_Special;
if (Expand(ref original3))
{
botFavoritesData.LastEquipped_Special = original3;
}
Il2CppStringArray original4 = botFavoritesData.LastEquipped_Class;
if (Expand(ref original4))
{
botFavoritesData.LastEquipped_Class = original4;
}
Il2CppStringArray original5 = botFavoritesData.LastEquipped_HackingTool;
if (Expand(ref original5))
{
botFavoritesData.LastEquipped_HackingTool = original5;
}
}
private static bool Expand(ref Il2CppStringArray original)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
if (((Il2CppArrayBase<string>)(object)original).Length >= PluginConfig.MaxPlayers)
{
return false;
}
Il2CppStringArray val = original;
Il2CppStringArray val2 = new Il2CppStringArray((long)PluginConfig.MaxPlayers);
for (int i = 0; i < ((Il2CppArrayBase<string>)(object)val2).Length; i++)
{
if (i < ((Il2CppArrayBase<string>)(object)val).Length)
{
((Il2CppArrayBase<string>)(object)val2)[i] = ((Il2CppArrayBase<string>)(object)val)[i];
}
else
{
((Il2CppArrayBase<string>)(object)val2)[i] = string.Empty;
}
}
original = val2;
return true;
}
}
[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_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected I4, but got Unknown
int characterID = __instance.CharacterID;
if (characterID > 3)
{
int num = characterID % 4;
__result = (DialogCharFilter)(int)((Il2CppArrayBase<DialogCharFilter>)(object)__instance.m_playerCharacters)[num];
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerCoverageSystem))]
public static class PlayerCoverageSystemPatch
{
[HarmonyPatch("Awake")]
[HarmonyPostfix]
public static void Awake__Postfix()
{
if (((Il2CppArrayBase<int>)(object)PlayerCoverageSystem.s_coverageKeys).Length < 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)
{
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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
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++)
{
((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)
{
if ((Object)(object)source == (Object)null)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(PlayerManager))]
public static class PlayerManagerPatch
{
private static readonly Random _random = new Random(690420);
[HarmonyPatch("GetSpawnPoint")]
[HarmonyPrefix]
public static bool GetSpawnPoint__Prefix(PlayerspawnpointType type, ref int referenceID)
{
if (referenceID > 3)
{
int num = referenceID % 4;
referenceID = num;
}
return true;
}
[HarmonyPatch("Awake")]
[HarmonyPostfix]
public static void Awake__Postfix(PlayerManager? __instance)
{
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++)
{
((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.Assert((Object)(object)__instance != (Object)null, "__instance was null");
FixAvailableSpawnpoints(__instance);
FixPlayerColors(__instance);
}
private static Color GenerateSeededRandomColor(float saturation = 0.8f, float value = 0.8f)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
return Color.HSVToRGB(_random.NextSingle(), saturation, value);
}
private static void FixPlayerColors(PlayerManager __instance)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: 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_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: 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_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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 < 4) ? ((Il2CppArrayBase<Color>)(object)playerColors)[i] : ((i >= 8) ? GenerateSeededRandomColor() : array[i % 4]));
Color val2 = val;
((Il2CppArrayBase<Color>)(object)__instance.m_playerColors)[i] = val2;
}
}
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);
}
}
}
[HarmonyPatch(typeof(PlayerVoiceManager))]
public static class PlayerVoiceManagerPatch
{
[HarmonyPatch("Setup")]
[HarmonyPostfix]
public static void Setup__Postfix(PlayerVoiceManager __instance)
{
if (((Il2CppArrayBase<PlayerVoice>)(object)__instance.m_playerVoices).Length < PluginConfig.MaxPlayers)
{
__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_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
__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++)
{
((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)
{
if (settings.m_playerLimit < PluginConfig.MaxPlayers)
{
settings.m_playerLimit = 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_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
__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)
{
if (!__result && bot.IsBot && SNet.IsMaster && __instance.PlayersInSession.Count <= PluginConfig.MaxPlayers - 1 && !__instance.PlayersInSession.Contains(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)
{
if (cMaxMembers < PluginConfig.MaxPlayers)
{
cMaxMembers = PluginConfig.MaxPlayers;
}
return true;
}
}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
int ICollection.Count => _items.Length;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
object IList.this[int index]
{
get
{
return _items[index];
}
set
{
throw new NotSupportedException();
}
}
bool IList.IsFixedSize => true;
bool IList.IsReadOnly => true;
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();
}
void ICollection.CopyTo(Array array, int index)
{
((ICollection)_items).CopyTo(array, index);
}
int IList.Add(object? value)
{
throw new NotSupportedException();
}
void IList.Clear()
{
throw new NotSupportedException();
}
bool IList.Contains(object? value)
{
return ((IList)_items).Contains(value);
}
int IList.IndexOf(object? value)
{
return ((IList)_items).IndexOf(value);
}
void IList.Insert(int index, object? value)
{
throw new NotSupportedException();
}
void IList.Remove(object? value)
{
throw new NotSupportedException();
}
void IList.RemoveAt(int index)
{
throw new NotSupportedException();
}
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();
}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
{
object IEnumerator.Current => _item;
T IEnumerator<T>.Current => _item;
public Enumerator(T item)
{
_item = item;
}
bool IEnumerator.MoveNext()
{
if (!_moveNextCalled)
{
return _moveNextCalled = true;
}
return false;
}
void IEnumerator.Reset()
{
_moveNextCalled = false;
}
void IDisposable.Dispose()
{
}
}
int ICollection.Count => 1;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
object IList.this[int index]
{
get
{
if (index != 0)
{
throw new IndexOutOfRangeException();
}
return _item;
}
set
{
throw new NotSupportedException();
}
}
bool IList.IsFixedSize => true;
bool IList.IsReadOnly => true;
int IReadOnlyCollection<T>.Count => 1;
T IReadOnlyList<T>.this[int index]
{
get
{
if (index != 0)
{
throw new IndexOutOfRangeException();
}
return _item;
}
}
int ICollection<T>.Count => 1;
bool ICollection<T>.IsReadOnly => true;
T IList<T>.this[int index]
{
get
{
if (index != 0)
{
throw new IndexOutOfRangeException();
}
return _item;
}
set
{
throw new NotSupportedException();
}
}
public <>z__ReadOnlySingleElementList(T item)
{
_item = item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(_item);
}
void ICollection.CopyTo(Array array, int index)
{
array.SetValue(_item, index);
}
int IList.Add(object? value)
{
throw new NotSupportedException();
}
void IList.Clear()
{
throw new NotSupportedException();
}
bool IList.Contains(object? value)
{
return EqualityComparer<T>.Default.Equals(_item, (T)value);
}
int IList.IndexOf(object? value)
{
if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
{
return -1;
}
return 0;
}
void IList.Insert(int index, object? value)
{
throw new NotSupportedException();
}
void IList.Remove(object? value)
{
throw new NotSupportedException();
}
void IList.RemoveAt(int index)
{
throw new NotSupportedException();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(_item);
}
void ICollection<T>.Add(T item)
{
throw new NotSupportedException();
}
void ICollection<T>.Clear()
{
throw new NotSupportedException();
}
bool ICollection<T>.Contains(T item)
{
return EqualityComparer<T>.Default.Equals(_item, item);
}
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
array[arrayIndex] = _item;
}
bool ICollection<T>.Remove(T item)
{
throw new NotSupportedException();
}
int IList<T>.IndexOf(T item)
{
if (!EqualityComparer<T>.Default.Equals(_item, item))
{
return -1;
}
return 0;
}
void IList<T>.Insert(int index, T item)
{
throw new NotSupportedException();
}
void IList<T>.RemoveAt(int index)
{
throw new NotSupportedException();
}
}