Decompiled source of MorePlayers v1.0.0

MorePlayers.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BoplFixedMath;
using HarmonyLib;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace MorePlayers;

internal static class PerPlayerSounds
{
	private static readonly string[] Prefixes = new string[4] { "slimeJump", "slimeWalk", "slimeLand", "beamCharge" };

	public static string Remap(string name)
	{
		if (string.IsNullOrEmpty(name) || (name[0] != 's' && name[0] != 'b'))
		{
			return name;
		}
		for (int i = 0; i < Prefixes.Length; i++)
		{
			string text = Prefixes[i];
			if (name.Length > text.Length && name.StartsWith(text) && int.TryParse(name.Substring(text.Length), out var result) && ExtraPlayers.IsExtraId(result))
			{
				return text + ((result - 7) % 4 + 1);
			}
		}
		return name;
	}
}
[HarmonyPatch(typeof(AudioManager), "Play", new Type[]
{
	typeof(string),
	typeof(float)
})]
internal static class PlaySoundPatch
{
	private static void Prefix(ref string name)
	{
		name = PerPlayerSounds.Remap(name);
	}
}
[HarmonyPatch(typeof(AudioManager), "Play", new Type[]
{
	typeof(string),
	typeof(float),
	typeof(float)
})]
internal static class PlaySoundPitchPatch
{
	private static void Prefix(ref string name)
	{
		name = PerPlayerSounds.Remap(name);
	}
}
[HarmonyPatch(typeof(AudioManager), "PlayInterruptable")]
internal static class PlayInterruptablePatch
{
	private static void Prefix(ref string name)
	{
		name = PerPlayerSounds.Remap(name);
	}
}
[HarmonyPatch(typeof(AudioManager), "TimesSoundsPlayed")]
internal static class TimesSoundsPlayedPatch
{
	private static bool Prefix(InterruptableAudio interruptableAudio, ref int __result)
	{
		if (interruptableAudio.index < 0)
		{
			__result = 0;
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(CharacterSelectHandler), "TryStartGame_inner")]
internal static class DebugBots
{
	private static readonly FieldInfo AllReadyField = AccessTools.Field(typeof(CharacterSelectHandler), "allReadyForMoreThanOneFrame");

	private static readonly FieldInfo PlayerColorsField = AccessTools.Field(typeof(CharacterSelectHandler), "playerColors");

	private static void Prefix(out bool __state)
	{
		__state = CharacterSelectHandler.startButtonAvailable && (bool)AllReadyField.GetValue(null);
	}

	private static void Postfix(CharacterSelectHandler __instance, bool __state)
	{
		if (!__state)
		{
			return;
		}
		ReplayGuard.SetBigGame(MorePlayersPlugin.DebugBots > 0);
		if (MorePlayersPlugin.DebugBots <= 0)
		{
			return;
		}
		Safe.Run("adding debug bots", delegate
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00de: 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)
			List<Player> list = PlayerHandler.Get().PlayerList();
			if (list.Count != 0)
			{
				PlayerColors val = (PlayerColors)PlayerColorsField.GetValue(__instance);
				Player val2 = list[0];
				int val3 = Math.Min(MorePlayersPlugin.DebugBots, MorePlayersPlugin.MaxPlayers - list.Count);
				val3 = Math.Min(val3, 8);
				int num = Math.Max(TeamColorExtender.TeamCount(), 4);
				int i = 0;
				int j = 0;
				int num2 = -1;
				for (int k = 0; k < val3; k++)
				{
					if (num2 < 0 || !MorePlayersPlugin.DebugBotsOneTeam)
					{
						for (; i < num - 1 && TeamTaken(list, i); i++)
						{
						}
						num2 = i++;
					}
					for (; j < val.Length - 1 && ColorTaken(list, val[j].playerMaterial); j++)
					{
					}
					Player val4 = new Player(7 + k, num2);
					val4.Color = val[j++].playerMaterial;
					val4.IsLocalPlayer = false;
					val4.UsesKeyboardAndMouse = false;
					val4.CanUseAbilities = true;
					val4.Abilities = new List<GameObject>(val2.Abilities);
					val4.AbilityIcons = new List<Sprite>(val2.AbilityIcons);
					list.Add(val4);
				}
				MorePlayersPlugin.Log.LogInfo((object)("Added " + val3 + " debug bots to the local game."));
			}
		});
	}

	private static bool TeamTaken(List<Player> list, int team)
	{
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i].Team == team)
			{
				return true;
			}
		}
		return false;
	}

	private static bool ColorTaken(List<Player> list, Material material)
	{
		for (int i = 0; i < list.Count; i++)
		{
			if ((Object)(object)list[i].Color == (Object)(object)material)
			{
				return true;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(CharacterSelectHandler), "LoadPreviousChoices")]
internal static class RemoveDebugBots
{
	private static void Prefix()
	{
		Safe.Run("removing debug bots", delegate
		{
			PlayerHandler.Get().PlayerList().RemoveAll((Player p) => ExtraPlayers.IsExtraId(p.Id));
		});
	}
}
internal class ExtraPlayer
{
	public byte Id;

	public ulong SteamId;

	public byte Color;

	public byte Team;

	public byte Ability1;

	public byte Ability2;

	public byte Ability3;
}
internal static class ExtraPlayers
{
	public const byte FirstId = 7;

	public const int MaxExtras = 8;

	public const int PacketSize = 777;

	private const int HeaderSize = 5;

	private const int EntrySize = 14;

	private static readonly byte[] Magic = new byte[4] { 66, 77, 80, 1 };

	public static List<ExtraPlayer> Current = new List<ExtraPlayer>();

	public static bool IsExtraId(int id)
	{
		if (id >= 7)
		{
			return id < 15;
		}
		return false;
	}

	public static ExtraPlayer FindBySteamId(ulong steamId)
	{
		for (int i = 0; i < Current.Count; i++)
		{
			if (Current[i].SteamId == steamId)
			{
				return Current[i];
			}
		}
		return null;
	}

	public static byte[] Encode(List<ExtraPlayer> extras)
	{
		byte[] array = new byte[777];
		Magic.CopyTo(array, 0);
		int num = Mathf.Min(extras.Count, 8);
		array[4] = (byte)num;
		int num2 = 5;
		for (int i = 0; i < num; i++)
		{
			ExtraPlayer extraPlayer = extras[i];
			array[num2++] = extraPlayer.Id;
			ulong steamId = extraPlayer.SteamId;
			for (int j = 0; j < 8; j++)
			{
				array[num2++] = (byte)(steamId >> 8 * j);
			}
			array[num2++] = extraPlayer.Color;
			array[num2++] = extraPlayer.Team;
			array[num2++] = extraPlayer.Ability1;
			array[num2++] = extraPlayer.Ability2;
			array[num2++] = extraPlayer.Ability3;
		}
		return array;
	}

	public static bool IsExtrasPacket(byte[] data, int size)
	{
		if (size != 777)
		{
			return false;
		}
		for (int i = 0; i < Magic.Length; i++)
		{
			if (data[i] != Magic[i])
			{
				return false;
			}
		}
		return data[4] <= 8;
	}

	public static List<ExtraPlayer> Decode(byte[] data)
	{
		List<ExtraPlayer> list = new List<ExtraPlayer>();
		int num = data[4];
		int num2 = 5;
		for (int i = 0; i < num; i++)
		{
			ExtraPlayer extraPlayer = new ExtraPlayer();
			extraPlayer.Id = data[num2++];
			ulong num3 = 0uL;
			for (int j = 0; j < 8; j++)
			{
				num3 |= (ulong)data[num2++] << 8 * j;
			}
			extraPlayer.SteamId = num3;
			extraPlayer.Color = data[num2++];
			extraPlayer.Team = data[num2++];
			extraPlayer.Ability1 = data[num2++];
			extraPlayer.Ability2 = data[num2++];
			extraPlayer.Ability3 = data[num2++];
			if (IsExtraId(extraPlayer.Id))
			{
				list.Add(extraPlayer);
			}
		}
		return list;
	}

	public static void Broadcast()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		byte[] array = Encode(Current);
		List<SteamConnection> connectedPlayers = SteamManager.instance.connectedPlayers;
		for (int i = 0; i < connectedPlayers.Count; i++)
		{
			((Connection)(ref ((ConnectionManager)connectedPlayers[i]).Connection)).SendMessage(array, (SendType)8);
		}
	}

	public static ExtraPlayer FromConnection(byte id, SteamConnection connection)
	{
		ExtraPlayer extraPlayer = new ExtraPlayer();
		extraPlayer.Id = id;
		extraPlayer.SteamId = connection.id.Value;
		extraPlayer.Color = (byte)connection.lobby_color;
		extraPlayer.Team = connection.lobby_team;
		extraPlayer.Ability1 = connection.lobby_ability1;
		extraPlayer.Ability2 = connection.lobby_ability2;
		extraPlayer.Ability3 = connection.lobby_ability3;
		return extraPlayer;
	}

	public static void ApplyAbilities(Player player, ExtraPlayer extra, int nrOfAbilities)
	{
		//IL_0058: 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)
		NamedSpriteList abilityIcons = SteamManager.instance.abilityIcons;
		player.Abilities.Clear();
		player.AbilityIcons.Clear();
		byte[] array = new byte[3] { extra.Ability1, extra.Ability2, extra.Ability3 };
		for (int i = 0; i < nrOfAbilities && i < array.Length; i++)
		{
			player.Abilities.Add(abilityIcons.sprites[array[i]].associatedGameObject);
			player.AbilityIcons.Add(abilityIcons.sprites[array[i]].sprite);
		}
	}
}
internal static class ExtraInputs
{
	public static readonly Queue<InputPacket[]> Buffer = new Queue<InputPacket[]>();

	private static readonly FieldInfo PreviousQuadField = AccessTools.Field(typeof(Host), "previousInputQuad");

	public static void Store(ref InputPacketQuad quad, ref InputPacket[] extras, int playerId, InputPacket input)
	{
		//IL_001d: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		switch (playerId)
		{
		case 1:
			quad.p1 = input;
			return;
		case 2:
			quad.p2 = input;
			return;
		case 3:
			quad.p3 = input;
			return;
		case 4:
			quad.p4 = input;
			return;
		}
		if (ExtraPlayers.IsExtraId(playerId))
		{
			if (extras == null)
			{
				extras = (InputPacket[])(object)new InputPacket[8];
			}
			extras[playerId - 7] = input;
		}
	}

	public static void ApplyBeforeTick(Host host)
	{
		//IL_0058: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		if (Buffer.Count == 0)
		{
			return;
		}
		InputPacket[] array = Buffer.Dequeue();
		List<Player> list = PlayerHandler.Get().PlayerList();
		for (int i = 0; i < list.Count; i++)
		{
			int id = list[i].Id;
			if (ExtraPlayers.IsExtraId(id))
			{
				list[i].OverrideInputWithNetworkInput((InputPacket)((array == null) ? default(InputPacket) : array[id - 7]));
			}
		}
		if (array != null)
		{
			AddDelayVotes(host, array);
		}
	}

	private static void AddDelayVotes(Host host, InputPacket[] frame)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		byte b = 0;
		for (int i = 0; i < frame.Length; i++)
		{
			if (frame[i].targetDelayBufferSize > b)
			{
				b = frame[i].targetDelayBufferSize;
			}
		}
		InputPacketQuad val = (InputPacketQuad)PreviousQuadField.GetValue(host);
		if (b > val.p1.targetDelayBufferSize)
		{
			val.p1.targetDelayBufferSize = b;
			PreviousQuadField.SetValue(host, val);
		}
	}
}
[HarmonyPatch(typeof(Host), "Init")]
internal static class HostInitPatch
{
	private static void Postfix()
	{
		ExtraInputs.Buffer.Clear();
	}
}
[HarmonyPatch(typeof(Host), "ProcessNetworkPackets")]
internal static class ProcessNetworkPacketsPatch
{
	private static readonly FieldInfo ClientsField = AccessTools.Field(typeof(Host), "clients");

	private static readonly FieldInfo LocalPlayerIdField = AccessTools.Field(typeof(Host), "localPlayerId");

	private static readonly FieldInfo InputHistoryField = AccessTools.Field(typeof(Host), "inputHistory");

	private static readonly FieldInfo AllClientsSyncedField = AccessTools.Field(typeof(Host), "allClientsSynced");

	private static readonly FieldInfo InputBufferField = AccessTools.Field(typeof(Host), "InputBuffer");

	private static readonly FieldInfo DelayBufferSizeField = AccessTools.Field(typeof(Host), "delayBufferSize");

	private static readonly FieldInfo UpdatesPlacedField = AccessTools.Field(typeof(Host), "UpdatesPlacedInDelayBuffer");

	private static readonly FieldInfo SentPacketHistoryField = AccessTools.Field(typeof(Host), "sentPacketHistory");

	private static bool Prefix(Host __instance)
	{
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		List<Client> list = (List<Client>)ClientsField.GetValue(__instance);
		int num = (int)LocalPlayerIdField.GetValue(__instance);
		TimedInputPacket[] array = (TimedInputPacket[])InputHistoryField.GetValue(__instance);
		Queue<InputPacketQuad> queue = (Queue<InputPacketQuad>)InputBufferField.GetValue(__instance);
		if (list.Count == 0)
		{
			MonoBehaviour.print((object)"There are no clients");
		}
		for (int i = 0; i < list.Count; i++)
		{
			if (!((ConnectionManager)list[i].steamConnection).Connected && !((ConnectionManager)list[i].steamConnection).Connecting)
			{
				MonoBehaviour.print((object)" a client is not connected nor connecting");
			}
		}
		bool flag = true;
		for (int j = 0; j < list.Count; j++)
		{
			list[j].ProcessNetworkPackets(Time.unscaledTime, array, __instance.AdaptiveInputDelayBuffer, (byte)num);
			flag &= list[j].HasReceivedSyncAck;
			flag &= list[j].HasSentSyncAck;
		}
		bool flag2 = (bool)AllClientsSyncedField.GetValue(__instance);
		if (flag && !flag2)
		{
			flag2 = true;
			AllClientsSyncedField.SetValue(__instance, true);
			int num2 = (int)DelayBufferSizeField.GetValue(null);
			for (int k = 0; k < num2; k++)
			{
				queue.Enqueue(default(InputPacketQuad));
				ExtraInputs.Buffer.Enqueue(null);
			}
		}
		if (!flag2)
		{
			return false;
		}
		uint num3 = uint.MaxValue;
		for (int l = 0; l < list.Count; l++)
		{
			if (list[l].InputPacketsReceived < num3)
			{
				num3 = list[l].InputPacketsReceived;
			}
		}
		if (__instance.inputPacketsSent < num3)
		{
			num3 = __instance.inputPacketsSent;
		}
		int num4 = (int)UpdatesPlacedField.GetValue(__instance);
		Queue<InputPacket> queue2 = (Queue<InputPacket>)SentPacketHistoryField.GetValue(__instance);
		int num5 = (int)num3 - num4;
		for (int m = 0; m < num5; m++)
		{
			InputPacketQuad quad = default(InputPacketQuad);
			InputPacket[] extras = null;
			for (int n = 0; n < list.Count; n++)
			{
				ExtraInputs.Store(ref quad, ref extras, list[n].PlayerId, list[n].inputHistory.Dequeue());
			}
			ExtraInputs.Store(ref quad, ref extras, num, queue2.Dequeue());
			queue.Enqueue(quad);
			ExtraInputs.Buffer.Enqueue(extras);
			num4++;
		}
		UpdatesPlacedField.SetValue(__instance, num4);
		try
		{
			if (num == 1)
			{
				for (int num6 = 0; num6 < list.Count; num6++)
				{
					list[num6].CheckForDesyncs();
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("Desync occured, ending game " + ex));
			GameSessionHandler.EndGameImmediately();
		}
		return false;
	}
}
[HarmonyPatch(typeof(Host), "Update")]
internal static class HostUpdatePatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Expected O, but got Unknown
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(Updater), "TickSimulation", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(ExtraInputs), "ApplyBeforeTick", (Type[])null, (Type[])null);
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		int num = 0;
		int index = -1;
		for (int i = 0; i < list.Count; i++)
		{
			if ((list[i].opcode == OpCodes.Call || list[i].opcode == OpCodes.Callvirt) && list[i].operand as MethodInfo == methodInfo)
			{
				num++;
				index = i;
			}
		}
		if (num != 1)
		{
			MorePlayersPlugin.Log.LogError((object)("Host.Update looks different than expected (" + num + " ticks found). Players 7+ will not receive input; the game may have updated."));
			return list;
		}
		CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
		val.labels.AddRange(list[index].labels);
		list[index].labels.Clear();
		list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
		{
			val,
			new CodeInstruction(OpCodes.Call, (object)methodInfo2)
		});
		return list;
	}
}
internal static class LobbyMembers
{
	private const string MemberKey = "moreplayers";

	private const float GraceSeconds = 10f;

	public static readonly List<string> Dropped = new List<string>();

	public static string Notice;

	public static float NoticeUntil;

	private static readonly Dictionary<SteamConnection, float> firstSeen = new Dictionary<SteamConnection, float>();

	private static ulong currentLobbyId;

	private static ulong ownerId;

	private static float ownerSince;

	public static void Update()
	{
		//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_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)SteamManager.instance == (Object)null || !SteamClient.IsValid || string.IsNullOrEmpty(Constants.version))
		{
			return;
		}
		Lobby currentLobby = SteamManager.instance.currentLobby;
		ulong value = ((Lobby)(ref currentLobby)).Id.Value;
		if (value == 0)
		{
			return;
		}
		if (value != currentLobbyId)
		{
			currentLobbyId = value;
			firstSeen.Clear();
			Dropped.Clear();
			ownerId = 0uL;
		}
		HashSet<ulong> hashSet = new HashSet<ulong>();
		foreach (Friend member in ((Lobby)(ref currentLobby)).Members)
		{
			hashSet.Add(member.Id.Value);
		}
		if (!hashSet.Contains(SteamClient.SteamId.Value))
		{
			Dropped.Clear();
			return;
		}
		if (((Lobby)(ref currentLobby)).GetMemberData(new Friend(SteamClient.SteamId), "moreplayers") != Constants.version)
		{
			((Lobby)(ref currentLobby)).SetMemberData("moreplayers", Constants.version);
		}
		if (!GameSession.inMenus)
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (LeaveIfOwnerIncompatible(currentLobby, realtimeSinceStartup))
		{
			return;
		}
		List<SteamConnection> connectedPlayers = SteamManager.instance.connectedPlayers;
		for (int num = connectedPlayers.Count - 1; num >= 0; num--)
		{
			SteamConnection val = connectedPlayers[num];
			if (hashSet.Contains(val.id.Value))
			{
				if (!firstSeen.TryGetValue(val, out var value2))
				{
					firstSeen[val] = realtimeSinceStartup;
				}
				else if (!(realtimeSinceStartup - value2 < 10f) && !IsCompatible(currentLobby, val.id))
				{
					MorePlayersPlugin.Log.LogWarning((object)(val.steamName + " is in the lobby without this build of More Players; ignoring them."));
					Dropped.Add(val.steamName);
					firstSeen.Remove(val);
					((ConnectionManager)val).Close();
					connectedPlayers.RemoveAt(num);
				}
			}
		}
		List<SteamConnection> list = new List<SteamConnection>();
		foreach (SteamConnection key in firstSeen.Keys)
		{
			if (!connectedPlayers.Contains(key))
			{
				list.Add(key);
			}
		}
		for (int i = 0; i < list.Count; i++)
		{
			firstSeen.Remove(list[i]);
		}
	}

	private static bool LeaveIfOwnerIncompatible(Lobby lobby, float now)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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)
		if (SteamManager.LocalPlayerIsLobbyOwner)
		{
			return false;
		}
		ulong value = ((Lobby)(ref lobby)).Owner.Id.Value;
		if (value != ownerId)
		{
			ownerId = value;
			ownerSince = now;
			return false;
		}
		if (now - ownerSince < 10f || IsCompatible(lobby, ((Lobby)(ref lobby)).Owner.Id))
		{
			return false;
		}
		MorePlayersPlugin.Log.LogWarning((object)"The lobby owner doesn't have this build of More Players; moving to a new lobby.");
		ShowNotice("The lobby owner doesn't have More Players 1.0.0.\nYou've been moved to a new lobby - invite your friends again.");
		SteamManager.instance.LeaveLobby();
		return true;
	}

	private static bool IsCompatible(Lobby lobby, SteamId id)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		return ((Lobby)(ref lobby)).GetMemberData(new Friend(id), "moreplayers") == Constants.version;
	}

	public static void ShowNotice(string text)
	{
		Notice = text;
		NoticeUntil = Time.realtimeSinceStartup + 20f;
	}

	public static void LeaveIfIncompatible(Lobby lobby)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		Safe.Run("checking a joined lobby", delegate
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (SteamClient.IsValid && !string.IsNullOrEmpty(Constants.version) && !((Lobby)(ref lobby)).IsOwnedBy(SteamClient.SteamId))
			{
				string data = ((Lobby)(ref lobby)).GetData("version");
				if (!string.IsNullOrEmpty(data) && !(data == Constants.version))
				{
					MorePlayersPlugin.Log.LogWarning((object)("Left a lobby running a different version (" + data + ")."));
					((Lobby)(ref lobby)).Leave();
				}
			}
		});
	}
}
[HarmonyPatch(typeof(SteamManager), "HostGame")]
internal static class HostGamePatch
{
	private static void Prefix()
	{
		Safe.Run("sending extra players at game start", delegate
		{
			List<SteamConnection> connectedPlayers = SteamManager.instance.connectedPlayers;
			List<ExtraPlayer> list = new List<ExtraPlayer>();
			for (int i = 3; i < connectedPlayers.Count; i++)
			{
				if (list.Count >= 8)
				{
					break;
				}
				list.Add(ExtraPlayers.FromConnection((byte)(7 + list.Count), connectedPlayers[i]));
			}
			ExtraPlayers.Current = list;
			ReplayGuard.SetBigGame(list.Count > 0);
			ExtraPlayers.Broadcast();
		});
	}
}
[HarmonyPatch(typeof(SteamManager), "HostNextLevel")]
internal static class HostNextLevelPatch
{
	private static void Prefix()
	{
		Safe.Run("sending extra players for the next level", delegate
		{
			List<SteamConnection> connectedPlayers = SteamManager.instance.connectedPlayers;
			for (int i = 0; i < ExtraPlayers.Current.Count; i++)
			{
				ExtraPlayer extraPlayer = ExtraPlayers.Current[i];
				for (int j = 0; j < connectedPlayers.Count; j++)
				{
					if (connectedPlayers[j].id.Value == extraPlayer.SteamId)
					{
						extraPlayer.Ability1 = connectedPlayers[j].lobby_ability1;
						extraPlayer.Ability2 = connectedPlayers[j].lobby_ability2;
						extraPlayer.Ability3 = connectedPlayers[j].lobby_ability3;
						break;
					}
				}
			}
			ExtraPlayers.Broadcast();
			List<Player> list = PlayerHandler.Get().PlayerList();
			for (int k = 0; k < list.Count; k++)
			{
				for (int l = 0; l < ExtraPlayers.Current.Count; l++)
				{
					if (ExtraPlayers.Current[l].Id == list[k].Id)
					{
						ExtraPlayers.ApplyAbilities(list[k], ExtraPlayers.Current[l], SteamManager.startParameters.nrOfAbilites);
					}
				}
			}
		});
	}
}
[HarmonyPatch(typeof(SteamSocket), "OnMessage")]
internal static class ReceiveExtraPlayersPatch
{
	private static bool Prefix(NetIdentity identity, IntPtr data, int size)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		if (size != 777)
		{
			return true;
		}
		byte[] buffer = new byte[size];
		Marshal.Copy(data, buffer, 0, size);
		if (!ExtraPlayers.IsExtrasPacket(buffer, size))
		{
			return true;
		}
		Safe.Run("reading extra players", delegate
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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)
			SteamId steamId = ((NetIdentity)(ref identity)).SteamId;
			if (((SteamId)(ref steamId)).IsValid && ((Lobby)(ref SteamManager.instance.currentLobby)).IsOwnedBy(((NetIdentity)(ref identity)).SteamId))
			{
				ExtraPlayers.Current = ExtraPlayers.Decode(buffer);
				ReplayGuard.SetBigGame(ExtraPlayers.Current.Count > 0);
			}
		});
		return false;
	}
}
[HarmonyPatch(typeof(SteamManager), "InitNetworkClient")]
internal static class InitNetworkClientPatch
{
	private static bool Prefix(SteamManager __instance)
	{
		//IL_0000: 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)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Expected O, but got Unknown
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Expected O, but got Unknown
		StartRequestPacket startParameters = SteamManager.startParameters;
		ulong value = SteamClient.SteamId.Value;
		int num = 0;
		if (startParameters.p1_id == value)
		{
			num = 1;
		}
		else if (startParameters.p2_id == value)
		{
			num = 2;
		}
		else if (startParameters.p3_id == value)
		{
			num = 3;
		}
		else if (startParameters.p4_id == value)
		{
			num = 4;
		}
		else
		{
			ExtraPlayer extraPlayer = ExtraPlayers.FindBySteamId(value);
			if (extraPlayer != null)
			{
				num = extraPlayer.Id;
			}
		}
		List<Client> list = new List<Client>();
		List<SteamConnection> connectedPlayers = __instance.connectedPlayers;
		for (int i = 0; i < connectedPlayers.Count; i++)
		{
			ulong value2 = connectedPlayers[i].id.Value;
			if (value2 == startParameters.p1_id && startParameters.nrOfPlayers >= 1)
			{
				list.Add(new Client(1, connectedPlayers[i]));
				continue;
			}
			if (value2 == startParameters.p2_id && startParameters.nrOfPlayers >= 2)
			{
				list.Add(new Client(2, connectedPlayers[i]));
				continue;
			}
			if (value2 == startParameters.p3_id && startParameters.nrOfPlayers >= 3)
			{
				list.Add(new Client(3, connectedPlayers[i]));
				continue;
			}
			if (value2 == startParameters.p4_id && startParameters.nrOfPlayers >= 4)
			{
				list.Add(new Client(4, connectedPlayers[i]));
				continue;
			}
			ExtraPlayer extraPlayer2 = ExtraPlayers.FindBySteamId(value2);
			if (extraPlayer2 != null)
			{
				list.Add(new Client((int)extraPlayer2.Id, connectedPlayers[i]));
			}
		}
		__instance.networkClient.Init(list, num, startParameters.currentLevel, __instance.startFrameBuffer, __instance.checkForDesyncs);
		SteamManager.networkClientHandle = __instance.networkClient;
		return false;
	}
}
[HarmonyPatch(typeof(CharacterSelectHandler_online), "ForceStartGame")]
internal static class ForceStartGamePatch
{
	private static readonly FieldInfo SelfRef = AccessTools.Field(typeof(CharacterSelectHandler_online), "selfRef");

	private static bool Prefix(PlayerColors pcs)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)pcs == (Object)null)
		{
			pcs = ((CharacterSelectHandler_online)SelfRef.GetValue(null)).playerColors;
		}
		if (GameLobby.isPlayingAReplay)
		{
			ExtraPlayers.Current = new List<ExtraPlayer>();
		}
		ReplayGuard.SetBigGame(ExtraPlayers.Current.Count > 0);
		StartRequestPacket startParameters = SteamManager.startParameters;
		Updater.ReInit();
		List<Player> list = new List<Player>();
		Updater.InitSeed(startParameters.seed);
		int num = 0;
		if (startParameters.p1_ability1 != 0 && startParameters.nrOfPlayers > num)
		{
			list.Add(InitPlayer(1, startParameters.p1_color, startParameters.p1_team, startParameters.p1_ability1, startParameters.p1_ability2, startParameters.p1_ability3, startParameters.nrOfAbilites, pcs));
			num++;
		}
		if (startParameters.p2_ability1 != 0 && startParameters.nrOfPlayers > num)
		{
			list.Add(InitPlayer(2, startParameters.p2_color, startParameters.p2_team, startParameters.p2_ability1, startParameters.p2_ability2, startParameters.p2_ability3, startParameters.nrOfAbilites, pcs));
			num++;
		}
		if (startParameters.p3_ability1 != 0 && startParameters.nrOfPlayers > num)
		{
			list.Add(InitPlayer(3, startParameters.p3_color, startParameters.p3_team, startParameters.p3_ability1, startParameters.p3_ability2, startParameters.p3_ability3, startParameters.nrOfAbilites, pcs));
			num++;
		}
		if (startParameters.p4_ability1 != 0 && startParameters.nrOfPlayers > num)
		{
			list.Add(InitPlayer(4, startParameters.p4_color, startParameters.p4_team, startParameters.p4_ability1, startParameters.p4_ability2, startParameters.p4_ability3, startParameters.nrOfAbilites, pcs));
			num++;
		}
		for (int i = 0; i < ExtraPlayers.Current.Count; i++)
		{
			ExtraPlayer extraPlayer = ExtraPlayers.Current[i];
			Player val = InitPlayer(extraPlayer.Id, extraPlayer.Color, extraPlayer.Team, extraPlayer.Ability1, extraPlayer.Ability2, extraPlayer.Ability3, startParameters.nrOfAbilites, pcs);
			val.steamId = SteamId.op_Implicit(extraPlayer.SteamId);
			list.Add(val);
		}
		for (int j = 0; j < list.Count; j++)
		{
			switch (list[j].Id)
			{
			case 1:
				list[j].steamId = SteamId.op_Implicit(startParameters.p1_id);
				break;
			case 2:
				list[j].steamId = SteamId.op_Implicit(startParameters.p2_id);
				break;
			case 3:
				list[j].steamId = SteamId.op_Implicit(startParameters.p3_id);
				break;
			case 4:
				list[j].steamId = SteamId.op_Implicit(startParameters.p4_id);
				break;
			}
		}
		Player val2 = null;
		if (GameLobby.isPlayingAReplay)
		{
			val2 = list[0];
		}
		else
		{
			ulong value = SteamClient.SteamId.Value;
			for (int k = 0; k < list.Count; k++)
			{
				if (list[k].steamId.Value == value)
				{
					val2 = list[k];
					break;
				}
			}
		}
		if (val2 == null)
		{
			MorePlayersPlugin.Log.LogError((object)"Could not find the local player in the start request, leaving the game.");
			GameSessionHandler.LeaveGame(true, false);
			return false;
		}
		val2.IsLocalPlayer = true;
		val2.inputDevice = CharacterSelectHandler_online.localPlayerInit.inputDevice;
		val2.UsesKeyboardAndMouse = CharacterSelectHandler_online.localPlayerInit.usesKeyboardMouse;
		val2.CustomKeyBinding = CharacterSelectHandler_online.localPlayerInit.keybindOverride;
		CharacterSelectHandler_online.startButtonAvailable = false;
		PlayerHandler.Get().SetPlayerList(list);
		SteamManager.instance.StartHostedGame();
		AudioManager val3 = AudioManager.Get();
		if ((Object)(object)val3 != (Object)null)
		{
			val3.Play("startGame");
		}
		GameSession.Init();
		if (GameLobby.isPlayingAReplay)
		{
			SceneManager.LoadScene(startParameters.currentLevel + 6);
		}
		else
		{
			SceneManager.LoadScene("Level1");
		}
		if (!WinnerTriangleCanvas.HasBeenSpawned)
		{
			SceneManager.LoadScene("winnerTriangle", (LoadSceneMode)1);
		}
		return false;
	}

	private static Player InitPlayer(int id, byte color, byte team, byte ability1, byte ability2, byte ability3, int nrOfAbilities, PlayerColors playerColors)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		Player val = new Player();
		val.Id = id;
		val.Color = playerColors.playerColors[color].playerMaterial;
		val.Team = team;
		ExtraPlayer extraPlayer = new ExtraPlayer();
		extraPlayer.Ability1 = ability1;
		extraPlayer.Ability2 = ability2;
		extraPlayer.Ability3 = ability3;
		ExtraPlayers.ApplyAbilities(val, extraPlayer, nrOfAbilities);
		val.IsLocalPlayer = false;
		return val;
	}
}
[HarmonyPatch(typeof(SteamManager), "ForceLoadNextLevel")]
internal static class ForceLoadNextLevelPatch
{
	private static void Prefix()
	{
		Safe.Run("updating extra players' abilities", delegate
		{
			List<Player> list = PlayerHandler.Get().PlayerList();
			for (int i = 0; i < list.Count; i++)
			{
				if (ExtraPlayers.IsExtraId(list[i].Id))
				{
					for (int j = 0; j < ExtraPlayers.Current.Count; j++)
					{
						if (ExtraPlayers.Current[j].Id == list[i].Id)
						{
							ExtraPlayers.ApplyAbilities(list[i], ExtraPlayers.Current[j], SteamManager.startParameters.nrOfAbilites);
						}
					}
				}
			}
		});
	}
}
[HarmonyPatch(typeof(CharacterSelectHandler_online), "SetTeamColor")]
internal static class SetTeamColorPatch
{
	private static void Prefix(ref int colorId)
	{
		int num = TeamColorExtender.TeamCount();
		if (num > 0 && colorId >= num)
		{
			colorId %= num;
		}
	}
}
[HarmonyPatch(typeof(SteamManager), "ForceBacktoAbilitySelect")]
internal static class ClearClientsAfterMatchPatch
{
	private static void Postfix()
	{
		Safe.Run("clearing last match's players", delegate
		{
			Host networkClientHandle = SteamManager.networkClientHandle;
			if ((Object)(object)networkClientHandle != (Object)null && !networkClientHandle.hasBeenInitialized)
			{
				networkClientHandle.ClearClients();
			}
		});
	}
}
internal static class ReplayGuard
{
	private static bool paused;

	private static bool savedValue;

	public static void SetBigGame(bool big)
	{
		if (big && !paused)
		{
			savedValue = Host.recordReplay;
			Host.recordReplay = false;
			paused = true;
		}
		else if (!big && paused)
		{
			Host.recordReplay = savedValue;
			paused = false;
		}
	}
}
[BepInPlugin("com.boplmods.moreplayers", "More Players", "1.0.0")]
public class MorePlayersPlugin : BaseUnityPlugin
{
	public const string Guid = "com.boplmods.moreplayers";

	public const string Version = "1.0.0";

	public const int HardMaxPlayers = 12;

	public const string VersionTag = " + More Players 1.0.0";

	internal static ManualLogSource Log;

	internal static int MaxPlayers = 12;

	internal static int DebugBots;

	internal static bool DebugBotsOneTeam;

	private static MorePlayersRunner runner;

	private void Awake()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPlayers", 12, new ConfigDescription("Most players allowed in an online lobby. The game has 12 slime colours, so 12 is the limit.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 12), new object[0]));
		ConfigEntry<int> val2 = ((BaseUnityPlugin)this).Config.Bind<int>("Testing", "DebugBots", 0, new ConfigDescription("Adds this many standing-still dummy slimes to LOCAL games so you can preview big matches alone. Leave at 0 for normal play.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 11), new object[0]));
		ConfigEntry<bool> val3 = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "DebugBotsOneTeam", true, "Put all dummy slimes on one team, so a round ends as soon as you lose or beat them.");
		MaxPlayers = Mathf.Clamp(val.Value, 2, 12);
		DebugBots = val2.Value;
		DebugBotsOneTeam = val3.Value;
		if (Constants.MAX_PLAYERS < MaxPlayers)
		{
			Constants.MAX_PLAYERS = MaxPlayers;
		}
		new Harmony("com.boplmods.moreplayers").PatchAll(typeof(MorePlayersPlugin).Assembly);
		SceneManager.sceneLoaded += OnSceneLoaded;
		SteamMatchmaking.OnLobbyEntered += LobbyMembers.LeaveIfIncompatible;
		Log.LogInfo((object)("More Players 1.0.0 loaded: up to " + MaxPlayers + " players per online lobby."));
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		Safe.Run("extending team colours", TeamColorExtender.ExtendAll);
		Spawns.OnSceneLoaded();
		if ((Object)(object)runner == (Object)null)
		{
			GameObject val = new GameObject("MorePlayersRunner");
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			runner = val.AddComponent<MorePlayersRunner>();
		}
	}
}
internal class MorePlayersRunner : MonoBehaviour
{
	private float lobbyCheckTimer;

	private static ulong loggedLobby;

	private static MorePlayersRunner instance;

	private static readonly string ScreenshotFlag = Path.Combine(Paths.BepInExRootPath, "moreplayers-screenshot.flag");

	private void Awake()
	{
		instance = this;
	}

	public static void CaptureMainMenuIfRequested()
	{
		if ((Object)(object)instance != (Object)null && File.Exists(ScreenshotFlag))
		{
			File.Delete(ScreenshotFlag);
			((MonoBehaviour)instance).StartCoroutine(CaptureSoon());
		}
	}

	private static IEnumerator CaptureSoon()
	{
		yield return (object)new WaitForSecondsRealtime(4f);
		ScreenCapture.CaptureScreenshot(Path.Combine(Paths.BepInExRootPath, "moreplayers-mainmenu.png"));
	}

	private void Update()
	{
		lobbyCheckTimer -= Time.unscaledDeltaTime;
		if (!(lobbyCheckTimer > 0f))
		{
			lobbyCheckTimer = 2f;
			Safe.Run("updating lobby size", KeepLobbyBigEnough);
			Safe.Run("checking lobby members", LobbyMembers.Update);
		}
	}

	private void OnGUI()
	{
		Safe.Run("drawing the lobby list", LobbyOverlay.Draw);
	}

	private static void KeepLobbyBigEnough()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)SteamManager.instance == (Object)null) && SteamClient.IsValid && ((Lobby)(ref SteamManager.instance.currentLobby)).Id.Value != 0 && SteamManager.LocalPlayerIsLobbyOwner)
		{
			int maxPlayers = MorePlayersPlugin.MaxPlayers;
			if (((Lobby)(ref SteamManager.instance.currentLobby)).MaxMembers < maxPlayers)
			{
				((Lobby)(ref SteamManager.instance.currentLobby)).MaxMembers = maxPlayers;
			}
			ulong value = ((Lobby)(ref SteamManager.instance.currentLobby)).Id.Value;
			if (value != loggedLobby)
			{
				loggedLobby = value;
				MorePlayersPlugin.Log.LogInfo((object)("Your lobby allows " + ((Lobby)(ref SteamManager.instance.currentLobby)).MaxMembers + " players (version tag: " + Constants.version + ")"));
			}
			if (!string.IsNullOrEmpty(Constants.version) && ((Lobby)(ref SteamManager.instance.currentLobby)).GetData("version") != Constants.version)
			{
				((Lobby)(ref SteamManager.instance.currentLobby)).SetData("version", Constants.version);
			}
		}
	}
}
internal static class Safe
{
	public static void Run(string what, Action action)
	{
		try
		{
			action();
		}
		catch (Exception ex)
		{
			MorePlayersPlugin.Log.LogError((object)("Error while " + what + ": " + ex));
		}
	}
}
[HarmonyPatch(typeof(printText), "Awake")]
internal static class TagGameVersion
{
	private static void Postfix(printText __instance)
	{
		Safe.Run("tagging the game version", delegate
		{
			if (Constants.version != null && !Constants.version.EndsWith(" + More Players 1.0.0"))
			{
				Constants.version += " + More Players 1.0.0";
			}
		});
	}
}
[HarmonyPatch(typeof(printText), "Start")]
internal static class ShowModVersion
{
	private static void Postfix(printText __instance)
	{
		Safe.Run("showing the mod version", delegate
		{
			VersionLabel.Add(__instance);
			MorePlayersRunner.CaptureMainMenuIfRequested();
		});
	}
}
internal static class VersionLabel
{
	private const string ObjectName = "MorePlayersVersion";

	public static void Add(printText owner)
	{
		//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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		TextMeshProUGUI component = ((Component)owner).GetComponent<TextMeshProUGUI>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)((Component)owner).transform.Find("MorePlayersVersion") != (Object)null))
		{
			((TMP_Text)component).ForceMeshUpdate(false, false);
			Bounds textBounds = ((TMP_Text)component).textBounds;
			GameObject val = new GameObject("MorePlayersVersion", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((TMP_Text)component).transform, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = ((TMP_Text)component).font;
			((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)component).fontSharedMaterial;
			((Graphic)val2).color = ((Graphic)component).color;
			((TMP_Text)val2).fontSize = ((TMP_Text)component).fontSize * 0.4f;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)1028;
			((TMP_Text)val2).enableWordWrapping = false;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).text = "More Players";
			RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
			rectTransform.anchorMin = ((TMP_Text)component).rectTransform.pivot;
			rectTransform.anchorMax = ((TMP_Text)component).rectTransform.pivot;
			rectTransform.pivot = new Vector2(1f, 0f);
			rectTransform.sizeDelta = new Vector2(((TMP_Text)val2).preferredWidth + 10f, ((TMP_Text)val2).preferredHeight);
			rectTransform.anchoredPosition = new Vector2(((Bounds)(ref textBounds)).max.x, ((Bounds)(ref textBounds)).max.y + ((TMP_Text)component).fontSize * 0.1f);
		}
	}
}
[HarmonyPatch(typeof(CharacterSelectHandler_online), "CheckForMods")]
internal static class ReportModded
{
	private static void Postfix()
	{
		CharacterSelectHandler_online.hasMods = true;
	}
}
[HarmonyPatch(typeof(SteamMatchmaking), "CreateLobbyAsync")]
internal static class BiggerLobbies
{
	private static void Prefix(ref int maxMembers)
	{
		if (maxMembers < MorePlayersPlugin.MaxPlayers)
		{
			maxMembers = MorePlayersPlugin.MaxPlayers;
		}
	}
}
internal static class TeamColorExtender
{
	private static readonly string[][] ExtraTeams = new string[8][]
	{
		new string[3] { "#D9BE29", "#6B5A0D", "#FFE600" },
		new string[3] { "#2BB8C4", "#0F5B61", "#19EEFF" },
		new string[3] { "#E8891C", "#7A4108", "#FF9F00" },
		new string[3] { "#E57A9A", "#7D2B45", "#FF8FB4" },
		new string[3] { "#8065D6", "#372874", "#9375FF" },
		new string[3] { "#E3E3E3", "#7D7D7D", "#FFFFFF" },
		new string[3] { "#9E9E9E", "#474747", "#C9C9C9" },
		new string[3] { "#4D4D4D", "#1A1A1A", "#787878" }
	};

	private static TeamColors known;

	public static int TeamCount()
	{
		if (!((Object)(object)known != (Object)null))
		{
			return 0;
		}
		return known.Length;
	}

	public static void ExtendAll()
	{
		TeamColors[] array = Resources.FindObjectsOfTypeAll<TeamColors>();
		for (int i = 0; i < array.Length; i++)
		{
			Extend(array[i]);
			known = array[i];
		}
	}

	private static void Extend(TeamColors colors)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		int num = colors.teamColors.Length;
		int num2 = 12;
		if (num != 0 && num < num2)
		{
			TeamColor[] array = (TeamColor[])(object)new TeamColor[num2];
			Array.Copy(colors.teamColors, array, num);
			for (int i = num; i < num2; i++)
			{
				string[] array2 = ExtraTeams[(i - num) % ExtraTeams.Length];
				TeamColor val = new TeamColor
				{
					team = i,
					fill = Parse(array2[0]),
					border = Parse(array2[1]),
					saturated = Parse(array2[2])
				};
				array[i] = val;
			}
			colors.teamColors = array;
			MorePlayersPlugin.Log.LogInfo((object)("Added " + (num2 - num) + " team colours to " + ((Object)colors).name));
		}
	}

	private static Color Parse(string hex)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		Color result = default(Color);
		ColorUtility.TryParseHtmlString(hex, ref result);
		return result;
	}
}
[HarmonyPatch(typeof(GameSessionHandler), "SpawnPlayers")]
internal static class Spawns
{
	private static readonly Dictionary<int, Vec2[]> originalSpawns = new Dictionary<int, Vec2[]>();

	private static Vec2[] plan;

	private static int nextPlayer;

	public static void OnSceneLoaded()
	{
		originalSpawns.Clear();
	}

	private static void Prefix(GameSessionHandler __instance)
	{
		plan = null;
		nextPlayer = 0;
		Safe.Run("planning spawn positions", delegate
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: 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_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			List<Player> list = PlayerHandler.Get().PlayerList();
			if (list.Count > 4)
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!originalSpawns.TryGetValue(instanceID, out var value))
				{
					value = (Vec2[])__instance.teamSpawns.Clone();
					originalSpawns[instanceID] = value;
				}
				if (value.Length != 0)
				{
					List<int> list2 = new List<int>();
					for (int i = 0; i < list.Count; i++)
					{
						if (!list2.Contains(list[i].Team))
						{
							list2.Add(list[i].Team);
						}
					}
					list2.Sort();
					if (__instance.teamSpawns.Length < list2.Count)
					{
						Vec2[] array = (Vec2[])(object)new Vec2[list2.Count];
						for (int j = 0; j < array.Length; j++)
						{
							ref Vec2 reference = ref array[j];
							reference = value[j % value.Length];
						}
						__instance.teamSpawns = array;
					}
					Fix teammateSpawnSpacing = __instance.teammateSpawnSpacing;
					Fix val = (Fix)0.5;
					int[] array2 = new int[value.Length];
					plan = (Vec2[])(object)new Vec2[list.Count];
					Vec2 val4 = default(Vec2);
					for (int k = 0; k < list.Count; k++)
					{
						int num = list2.IndexOf(list[k].Team) % value.Length;
						int num2 = array2[num]++;
						switch (num2)
						{
						case 0:
							((Vec2)(ref val4))..ctor(Fix.Zero, Fix.Zero);
							break;
						case 1:
							((Vec2)(ref val4))..ctor(-teammateSpawnSpacing, -teammateSpawnSpacing * val);
							break;
						case 2:
							((Vec2)(ref val4))..ctor(teammateSpawnSpacing, -teammateSpawnSpacing * val);
							break;
						default:
						{
							int num3 = num2 - 3;
							Fix val2 = (Fix)(long)(num3 % 3 - 1);
							Fix val3 = (Fix)(long)(num3 / 3 + 1);
							((Vec2)(ref val4))..ctor(val2 * teammateSpawnSpacing, val3 * teammateSpawnSpacing * (Fix)1.5);
							break;
						}
						}
						ref Vec2 reference2 = ref plan[k];
						reference2 = value[num] + val4;
					}
				}
			}
		});
	}

	public static Vec2 Adjust(Vec2 original)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		int num = nextPlayer++;
		if (plan == null || num >= plan.Length)
		{
			return original;
		}
		return plan[num];
	}

	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo methodInfo = AccessTools.Method(typeof(Spawns), "Adjust", (Type[])null, (Type[])null);
		bool flag = false;
		bool flag2 = false;
		for (int i = 0; i < list.Count; i++)
		{
			if (!flag && list[i].opcode == OpCodes.Ldc_I4_4 && i + 1 < list.Count && list[i + 1].opcode == OpCodes.Newarr && list[i + 1].operand as Type == typeof(int))
			{
				list[i].opcode = OpCodes.Ldc_I4;
				list[i].operand = 64;
				flag = true;
			}
			MethodInfo methodInfo2 = list[i].operand as MethodInfo;
			if (!flag2 && list[i].opcode == OpCodes.Call && methodInfo2 != null && methodInfo2.Name == "InstantiateFixed" && methodInfo2.DeclaringType == typeof(FixTransform))
			{
				list.Insert(i, new CodeInstruction(OpCodes.Call, (object)methodInfo));
				i++;
				flag2 = true;
			}
		}
		if (!flag || !flag2)
		{
			MorePlayersPlugin.Log.LogError((object)"GameSessionHandler.SpawnPlayers looks different than expected; spawn spreading may not work. The game may have updated.");
		}
		return list;
	}
}
[HarmonyPatch(typeof(CharacterStatsList), "OnEnable")]
internal static class WinnerScreenPatch
{
	private const int TeamPictures = 3;

	private static void Prefix(CharacterStatsList __instance)
	{
		Safe.Run("growing the winner screens", delegate
		{
			int wanted = CountWinners();
			__instance.winnersOfDraw = Grow(__instance.winnersOfDraw, wanted);
			__instance.teams3v1WinnersRef = Grow(__instance.teams3v1WinnersRef, wanted);
		});
	}

	private static void Postfix(CharacterStatsList __instance)
	{
		Safe.Run("filling the team winner screen", delegate
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Image[] teams3v1WinnersRef = __instance.teams3v1WinnersRef;
			if (teams3v1WinnersRef != null && teams3v1WinnersRef.Length > 3)
			{
				List<Player> list = new List<Player>(PlayerHandler.Get().PlayerList());
				list.Sort((IComparer<Player>?)new PlayerSorter());
				int num = CountWinners();
				bool flag = num > 3 && !WinnersOnDifferentTeams();
				for (int i = 3; i < teams3v1WinnersRef.Length; i++)
				{
					bool flag2 = flag && i < num && i < list.Count;
					((Component)teams3v1WinnersRef[i]).gameObject.SetActive(flag2);
					if (flag2)
					{
						((Graphic)teams3v1WinnersRef[i]).material = list[i].Color;
					}
				}
			}
		});
	}

	private static int CountWinners()
	{
		int num = 0;
		List<Player> list = PlayerHandler.Get().PlayerList();
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i].IsMostRecentWinner)
			{
				num++;
			}
		}
		return num;
	}

	private static bool WinnersOnDifferentTeams()
	{
		List<Player> list = PlayerHandler.Get().PlayerList();
		for (int i = 0; i < list.Count; i++)
		{
			for (int j = i + 1; j < list.Count; j++)
			{
				if (list[i].IsMostRecentWinner && list[j].IsMostRecentWinner && list[i].Team != list[j].Team)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static Image[] Grow(Image[] images, int wanted)
	{
		//IL_0053: 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_0033: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		if (images == null || images.Length == 0 || wanted <= images.Length)
		{
			return images;
		}
		Image[] array = (Image[])(object)new Image[wanted];
		images.CopyTo(array, 0);
		Image val = images[^1];
		? val2;
		if (images.Length <= 1)
		{
			Rect rect = ((Graphic)val).rectTransform.rect;
			val2 = new Vector2(((Rect)(ref rect)).width, 0f);
		}
		else
		{
			val2 = ((Graphic)val).rectTransform.anchoredPosition - ((Graphic)images[^2]).rectTransform.anchoredPosition;
		}
		Vector2 val3 = (Vector2)val2;
		for (int i = images.Length; i < wanted; i++)
		{
			Image val4 = Object.Instantiate<Image>(val, ((Component)val).transform.parent);
			((Graphic)val4).rectTransform.anchoredPosition = ((Graphic)val).rectTransform.anchoredPosition + val3 * (float)(i - images.Length + 1);
			array[i] = val4;
		}
		return array;
	}
}
[HarmonyPatch(typeof(HandleAbilitySelectUI), "Init")]
internal static class AbilitySelectLayoutPatch
{
	private static readonly FieldInfo SelectorsField = AccessTools.Field(typeof(HandleAbilitySelectUI), "Selectors");

	private static readonly FieldInfo SeparationField = AccessTools.Field(typeof(HandleAbilitySelectUI), "Separation");

	private static readonly FieldInfo OriginalPositionField = AccessTools.Field(typeof(AbilitySelectCircle), "originalPosition");

	private static readonly FieldInfo TargetPositionField = AccessTools.Field(typeof(AbilitySelectCircle), "targetPosition");

	private static void Postfix(HandleAbilitySelectUI __instance)
	{
		Safe.Run("laying out the ability select screen", delegate
		{
			//IL_00cf: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			AbilitySelectCircle[] array = (AbilitySelectCircle[])SelectorsField.GetValue(__instance);
			if (array != null && array.Length > 4)
			{
				float num = (float)SeparationField.GetValue(__instance);
				int num2 = array.Length;
				int num3 = ((num2 <= 6) ? num2 : ((num2 + 1) / 2));
				int num4 = (num2 + num3 - 1) / num3;
				float num5 = Mathf.Min(1f, 3f / (float)(num3 - 1));
				if (num4 > 1)
				{
					num5 *= 0.8f;
				}
				float num6 = -1.5f * num;
				for (int i = 0; i < num2; i++)
				{
					AbilitySelectCircle val = array[i];
					int num7 = i / num3;
					int num8 = i % num3;
					int num9 = Mathf.Min(num3, num2 - num7 * num3);
					float num10 = num * num5 * (float)(num9 - 1);
					float num11 = num6 - num10 / 2f + (float)num8 * num * num5;
					Rect rect = val.trans.rect;
					float num12 = Mathf.Clamp(((Rect)(ref rect)).height * num5 * 1.05f, num * num5 * 0.8f, num * num5 * 1.6f);
					float num13 = ((num4 > 1) ? ((num7 == 0) ? (num12 / 2f) : ((0f - num12) / 2f)) : 0f);
					val.trans.anchoredPosition = new Vector2(num11, val.trans.anchoredPosition.y);
					((Transform)val.trans).localScale = new Vector3(num5, num5, 1f);
					Vector2 val2 = (Vector2)OriginalPositionField.GetValue(val);
					OriginalPositionField.SetValue(val, (object)new Vector2(num11, val2.y));
					Vector2 val3 = (Vector2)TargetPositionField.GetValue(val);
					TargetPositionField.SetValue(val, (object)new Vector2(val3.x, val3.y + num13));
				}
			}
		});
	}
}
[HarmonyPatch(typeof(SteamFrame), "Awake")]
internal static class SteamFramePatch
{
	private static readonly FieldInfo SelfRefField = AccessTools.Field(typeof(SteamFrame), "selfRef");

	private static readonly FieldInfo SquareColorsField = AccessTools.Field(typeof(SteamFrame), "currentSquareColors");

	private static void Postfix(SteamFrame __instance)
	{
		Safe.Run("adding avatar slots", delegate
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: 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)
			if (!((Object)(SteamFrame)SelfRefField.GetValue(null) != (Object)(object)__instance))
			{
				int num = 11;
				List<SteamFrameButton> squares = __instance.squares;
				int count = squares.Count;
				Image[] lookingForPlayersCircles = __instance.lookingForPlayersCircles;
				if (count >= 2 && count < num && lookingForPlayersCircles != null && lookingForPlayersCircles.Length == count)
				{
					RectTransform component = ((Component)squares[count - 1]).GetComponent<RectTransform>();
					Vector2 val = component.anchoredPosition - ((Component)squares[count - 2]).GetComponent<RectTransform>().anchoredPosition;
					for (int i = count; i < num; i++)
					{
						SteamFrameButton val2 = Object.Instantiate<SteamFrameButton>(squares[count - 1], ((Component)squares[count - 1]).transform.parent);
						((Component)val2).GetComponent<RectTransform>().anchoredPosition = component.anchoredPosition + val * (float)(i - count + 1);
						((Graphic)val2.image).material = new Material(((Graphic)squares[count - 1].image).material);
						((Graphic)val2.image).materialForRendering.SetColor("_Blue", Color.white);
						UnityEvent onClick = (UnityEvent)(object)val2.button.onClick;
						for (int j = 0; j < ((UnityEventBase)onClick).GetPersistentEventCount(); j++)
						{
							((UnityEventBase)onClick).SetPersistentListenerState(j, (UnityEventCallState)0);
						}
						int slot = i;
						SteamFrame frame = __instance;
						onClick.AddListener((UnityAction)delegate
						{
							frame.ClickKickPlayer(slot);
						});
						((Component)val2).gameObject.SetActive(false);
						squares.Add(val2);
					}
					Image[] array = (Image[])(object)new Image[num];
					lookingForPlayersCircles.CopyTo(array, 0);
					Image val3 = lookingForPlayersCircles[count - 1];
					Vector2 val4 = ((Graphic)val3).rectTransform.anchoredPosition - ((Graphic)lookingForPlayersCircles[count - 2]).rectTransform.anchoredPosition;
					for (int num2 = count; num2 < num; num2++)
					{
						Image val5 = Object.Instantiate<Image>(val3, ((Component)val3).transform.parent);
						((Graphic)val5).rectTransform.anchoredPosition = ((Graphic)val3).rectTransform.anchoredPosition + val4 * (float)(num2 - count + 1);
						((Behaviour)val5).enabled = false;
						array[num2] = val5;
					}
					__instance.lookingForPlayersCircles = array;
					int[] array2 = new int[num];
					for (int num3 = 0; num3 < array2.Length; num3++)
					{
						array2[num3] = -1;
					}
					SquareColorsField.SetValue(__instance, array2);
				}
			}
		});
	}
}
[HarmonyPatch(typeof(SteamFrame), "HideAllAvatars")]
internal static class HideAvatarsPatch
{
	private static Exception Finalizer(Exception __exception)
	{
		if (__exception != null)
		{
			MorePlayersPlugin.Log.LogWarning((object)("HideAllAvatars: " + __exception.Message));
		}
		return null;
	}
}
[HarmonyPatch(typeof(SteamFrame), "ShowAllAvatars")]
internal static class ShowAvatarsPatch
{
	private static Exception Finalizer(Exception __exception)
	{
		if (__exception != null)
		{
			MorePlayersPlugin.Log.LogWarning((object)("ShowAllAvatars: " + __exception.Message));
		}
		return null;
	}
}
internal static class LobbyOverlay
{
	private static readonly FieldInfo SelfRefField = AccessTools.Field(typeof(CharacterSelectHandler_online), "selfRef");

	private static GUIStyle style;

	public static void Draw()
	{
		float num = 10f;
		if (LobbyMembers.Notice != null && Time.realtimeSinceStartup < LobbyMembers.NoticeUntil)
		{
			num += DrawBox(LobbyMembers.Notice, num) + 6f;
		}
		object? value = SelfRefField.GetValue(null);
		CharacterSelectHandler_online val = (CharacterSelectHandler_online)((value is CharacterSelectHandler_online) ? value : null);
		if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled || (Object)(object)SteamManager.instance == (Object)null)
		{
			return;
		}
		List<SteamConnection> connectedPlayers = SteamManager.instance.connectedPlayers;
		List<SteamConnection> list = new List<SteamConnection>();
		for (int i = 0; i < connectedPlayers.Count; i++)
		{
			bool flag = false;
			for (int j = 0; j < val.networkPlayerBoxes.Length; j++)
			{
				if (val.networkPlayerBoxes[j].isVisible && val.networkPlayerBoxes[j].connectedPlayer == connectedPlayers[i])
				{
					flag = true;
				}
			}
			if (!flag && ((ConnectionManager)connectedPlayers[i]).Connected)
			{
				list.Add(connectedPlayers[i]);
			}
		}
		if (list.Count == 0 && LobbyMembers.Dropped.Count == 0)
		{
			return;
		}
		string text = "Lobby: " + (connectedPlayers.Count + 1) + " / " + MorePlayersPlugin.MaxPlayers + " players";
		if (list.Count > 0)
		{
			text += "\nAlso here:";
		}
		for (int k = 0; k < list.Count; k++)
		{
			text = text + "\n  " + list[k].steamName + (list[k].lobby_isReady ? "  - READY" : "  - choosing");
		}
		if (LobbyMembers.Dropped.Count > 0)
		{
			text += "\nCan't play here (need More Players 1.0.0):";
			for (int l = 0; l < LobbyMembers.Dropped.Count; l++)
			{
				text = text + "\n  " + LobbyMembers.Dropped[l];
			}
		}
		DrawBox(text, num);
	}

	private static float DrawBox(string text, float y)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_0075: 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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		//IL_0049: 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_0068: Expected O, but got Unknown
		if (style == null)
		{
			style = new GUIStyle(GUI.skin.box);
			style.fontSize = Mathf.Max(14, Screen.height / 45);
			style.alignment = (TextAnchor)0;
			style.normal.textColor = Color.white;
			style.padding = new RectOffset(12, 12, 8, 8);
		}
		GUIContent val = new GUIContent(text);
		Vector2 val2 = style.CalcSize(val);
		GUI.Box(new Rect(((float)Screen.width - val2.x) / 2f, y, val2.x, val2.y), val, style);
		return val2.y;
	}
}