Decompiled source of LobbyControl Experimental v5.6.0

BepInEx/plugins/LobbyControl.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using LobbyControl.API;
using LobbyControl.Dependency;
using LobbyControl.Networking;
using LobbyControl.Patches;
using LobbyControl.PopUp;
using LobbyControl.TerminalCommands;
using LobbyControl.Utils;
using LobbyControl.Utils.IL;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using Steamworks;
using Steamworks.Data;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.Pool;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("mattymatty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.5.6")]
[assembly: AssemblyInformationalVersion("2.5.6+62ddc06d9bbf6a4d6aceee8e57b1b25d40cb621f")]
[assembly: AssemblyProduct("LobbyControl")]
[assembly: AssemblyTitle("LobbyControl - Plugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.5.6.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]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[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 LobbyControl
{
	[BepInPlugin("mattymatty.LobbyControl", "LobbyControl", "2.5.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class LobbyControl : BaseUnityPlugin
	{
		internal static class PluginConfig
		{
			internal static class SteamLobby
			{
				internal static ConfigEntry<bool> AutoLobby;
			}

			internal static class SaveLimit
			{
				internal static ConfigEntry<bool> Enabled;
			}

			internal static class LogSpam
			{
				internal static ConfigEntry<bool> Enabled;

				internal static ConfigEntry<bool> CalculatePolygonPath;

				internal static ConfigEntry<bool> AudioSpatializer;
			}

			internal static class JoinQueue
			{
				internal static ConfigEntry<bool> Enabled;

				internal static ConfigEntry<int> ConnectionTimeout;

				internal static ConfigEntry<int> ConnectionDelay;

				internal static ConfigEntry<bool> TimeoutPopup;

				internal static ConfigEntry<bool> ConnectionPopup;
			}

			internal static class Networking
			{
				internal static ConfigEntry<bool> Enabled;

				internal static ConfigEntry<bool> SyncRadarNames;

				internal static ConfigEntry<bool> ResetPlayerValues;
			}

			internal static void Init(BaseUnityPlugin plugin)
			{
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e3: Expected O, but got Unknown
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Expected O, but got Unknown
				ConfigFile config = plugin.Config;
				config.SaveOnConfigSet = false;
				SaveLimit.Enabled = config.Bind<bool>("SaveLimit", "enabled", true, "remove the limit to the amount of items that can be saved");
				SteamLobby.AutoLobby = config.Bind<bool>("SteamLobby", "auto_lobby", false, "automatically reopen the lobby as soon as you reach orbit");
				LogSpam.Enabled = config.Bind<bool>("LogSpam", "enabled", true, "prevent some annoying log spam");
				LogSpam.CalculatePolygonPath = config.Bind<bool>("LogSpam", "CalculatePolygonPath", true, "stop pathfinding for dead Enemies");
				LogSpam.AudioSpatializer = config.Bind<bool>("LogSpam", "audio_spatializer", true, "disable audio spatialization as there is not spatialization plugin");
				JoinQueue.Enabled = config.Bind<bool>("JoinQueue", "enabled", true, "handle joining players as a queue instead of at the same time");
				JoinQueue.ConnectionTimeout = config.Bind<int>("JoinQueue", "connection_timeout_ms", 20000, new ConfigDescription("After how much time discard a hanging connection", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10000, int.MaxValue), Array.Empty<object>()));
				JoinQueue.ConnectionDelay = config.Bind<int>("JoinQueue", "connection_delay_ms", 2000, new ConfigDescription("Delay between each successful connection", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, int.MaxValue), Array.Empty<object>()));
				JoinQueue.TimeoutPopup = config.Bind<bool>("JoinQueue", "timeout_notification", true, "show a popup when a client fails to join before the timeout");
				JoinQueue.ConnectionPopup = config.Bind<bool>("JoinQueue", "connection_notification", false, "show a popup when a client tries to join");
				Networking.Enabled = config.Bind<bool>("Networking", "enabled", true, "handle extra actions requested by host");
				Networking.SyncRadarNames = config.Bind<bool>("Networking", "sync_radar_names", false, "allow host to reorder radar names to align clients\nWARNING: all clients need to have the mod installed or desyncs might will happen");
				Networking.ResetPlayerValues = config.Bind<bool>("Networking", "reset_player_values", true, "allow host to force clients to reset most fields of a playerObject ( fix for invisible players )");
				JoinQueue.ConnectionTimeout.SettingChanged += delegate
				{
					NetworkManager singleton = NetworkManager.Singleton;
					if (singleton != null)
					{
						singleton.NetworkConfig.ClientConnectionBufferTimeout = JoinQueue.ConnectionTimeout.Value / 1000 * 4;
					}
				};
				if (LethalConfigProxy.Enabled)
				{
					LethalConfigProxy.AddConfig(SaveLimit.Enabled);
					LethalConfigProxy.AddConfig(SteamLobby.AutoLobby);
					LethalConfigProxy.AddConfig(LogSpam.Enabled);
					LethalConfigProxy.AddConfig(LogSpam.CalculatePolygonPath);
					LethalConfigProxy.AddConfig(LogSpam.AudioSpatializer);
					LethalConfigProxy.AddConfig(JoinQueue.Enabled);
					LethalConfigProxy.AddConfig(JoinQueue.ConnectionTimeout);
					LethalConfigProxy.AddConfig(JoinQueue.ConnectionDelay);
					LethalConfigProxy.AddConfig(JoinQueue.TimeoutPopup);
					LethalConfigProxy.AddConfig(JoinQueue.ConnectionPopup);
					LethalConfigProxy.AddConfig(Networking.Enabled);
					LethalConfigProxy.AddConfig(Networking.SyncRadarNames);
					LethalConfigProxy.AddConfig(Networking.ResetPlayerValues);
				}
				PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
				dictionary.Clear();
				config.Save();
				config.SaveOnConfigSet = true;
			}
		}

		public const string GUID = "mattymatty.LobbyControl";

		public const string NAME = "LobbyControl";

		public const string VERSION = "2.5.6";

		public static LobbyControl Instance;

		internal static ManualLogSource Log;

		internal static readonly Harmony Harmony = new Harmony("mattymatty.LobbyControl");

		public static bool CanModifyLobby = true;

		public static bool CanSave = true;

		public static bool AutoSaveEnabled = true;

		public static readonly List<Hook> Hooks = new List<Hook>();

		private static readonly string[] IncompatibleGUIDs = new string[4] { "com.github.tinyhoot.ShipLobby", "twig.latecompany", "McBowie.VeryLateCompany", "com.potatoepet.AdvancedCompany" };

		internal static readonly List<PluginInfo> FoundIncompatibilities = new List<PluginInfo>();

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			try
			{
				PluginInfo[] array = Chainloader.PluginInfos.Values.Where((PluginInfo p) => IncompatibleGUIDs.Contains(p.Metadata.GUID)).ToArray();
				if (array.Length != 0)
				{
					StringBuilder stringBuilder = new StringBuilder("LOBBY CONTROL was DISABLED!\nIncompatible:");
					FoundIncompatibilities.AddRange(array);
					PluginInfo[] array2 = array;
					foreach (PluginInfo val in array2)
					{
						Log.LogWarning((object)(val.Metadata.Name + " is incompatible!"));
						stringBuilder.Append("\n").Append(val.Metadata.Name);
					}
					Log.LogError((object)$"{array.Length} incompatible mods found! Disabling!");
					PopUpPatch.PopUps.Add(("LC_Incompatibility", stringBuilder.ToString()));
					Harmony.PatchAll(typeof(PopUpPatch));
					return;
				}
				if (LobbyCompatibilityChecker.Enabled)
				{
					LobbyCompatibilityChecker.Init("mattymatty.LobbyControl", Version.Parse("2.5.6"), 1, 2);
				}
				Log.LogInfo((object)"Initializing Configs");
				PluginConfig.Init((BaseUnityPlugin)(object)this);
				CommandManager.Initialize();
				LobbyCommand.Init();
				Log.LogInfo((object)"Patching Methods");
				Harmony.PatchAll(typeof(PopUpPatch));
				Harmony.PatchAll(typeof(JoinQueuePatches));
				JoinQueuePatches.Init();
				Harmony.PatchAll(typeof(LateJoinPatches));
				Harmony.PatchAll(typeof(LimitPatcher));
				Harmony.PatchAll(typeof(LobbyPatcher));
				Harmony.PatchAll(typeof(LogSpamPatches));
				Harmony.PatchAll(typeof(NetworkManagerPatch));
				Harmony.PatchAll(typeof(SavePatches));
				Harmony.PatchAll(typeof(TerminalPatch));
				Log.LogInfo((object)"LobbyControl v2.5.6 Loaded!");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Exception while initializing: \n" + ex));
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mattymatty.LobbyControl";

		public const string PLUGIN_NAME = "LobbyControl";

		public const string PLUGIN_VERSION = "2.5.6";
	}
}
namespace LobbyControl.Utils
{
	public static class HudUtils
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass0_0
		{
			public bool isWarning;

			internal bool <ShowMessageAfterDelay>b__0()
			{
				return HUDManager.Instance.CanTipDisplay(isWarning, false, (string)null);
			}
		}

		[CompilerGenerated]
		private sealed class <ShowMessageAfterDelay>d__0 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public bool isWarning;

			public float delay;

			private <>c__DisplayClass0_0 <>8__1;

			public string title;

			public string text;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ShowMessageAfterDelay>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Expected O, but got Unknown
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass0_0();
					<>8__1.isWarning = isWarning;
					if (delay > 0f)
					{
						<>2__current = (object)new WaitForSeconds(delay);
						<>1__state = 1;
						return true;
					}
					goto IL_006c;
				case 1:
					<>1__state = -1;
					goto IL_006c;
				case 2:
					{
						<>1__state = -1;
						HUDManager.Instance.DisplayTip(title, text, <>8__1.isWarning, false, "LC_Tip1");
						return false;
					}
					IL_006c:
					<>2__current = (object)new WaitUntil((Func<bool>)(() => HUDManager.Instance.CanTipDisplay(<>8__1.isWarning, false, (string)null)));
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <ShowTipAfterDelay>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public string title;

			public string text;

			public string saveKey;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ShowTipAfterDelay>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Expected O, but got Unknown
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (delay > 0f)
					{
						<>2__current = (object)new WaitForSeconds(delay);
						<>1__state = 1;
						return true;
					}
					goto IL_0050;
				case 1:
					<>1__state = -1;
					goto IL_0050;
				case 2:
					{
						<>1__state = -1;
						HUDManager.Instance.DisplayTip(title, text, false, true, saveKey);
						return false;
					}
					IL_0050:
					<>2__current = (object)new WaitUntil((Func<bool>)(() => HUDManager.Instance.CanTipDisplay(false, false, (string)null)));
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[IteratorStateMachine(typeof(<ShowMessageAfterDelay>d__0))]
		internal static IEnumerator ShowMessageAfterDelay(string title, string text, float delay = 0f, bool isWarning = false)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ShowMessageAfterDelay>d__0(0)
			{
				title = title,
				text = text,
				delay = delay,
				isWarning = isWarning
			};
		}

		[IteratorStateMachine(typeof(<ShowTipAfterDelay>d__1))]
		internal static IEnumerator ShowTipAfterDelay(string title, string text, float delay, string saveKey)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ShowTipAfterDelay>d__1(0)
			{
				title = title,
				text = text,
				delay = delay,
				saveKey = saveKey
			};
		}
	}
	public static class RPCUtils
	{
		private static readonly MethodInfo BeginSendClientRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendClientRpc", (Type[])null, (Type[])null);

		private static readonly MethodInfo BeginSendServerRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendServerRpc", (Type[])null, (Type[])null);

		internal static bool TryGetRpcID(MethodInfo methodInfo, out uint rpcID)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//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_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)
			Collection<Instruction> instructions = PatchManager.GetMethodPatcher((MethodBase)methodInfo).CopyOriginal().Definition.Body.Instructions;
			rpcID = 0u;
			for (int i = 0; i < instructions.Count; i++)
			{
				if (instructions[i].OpCode == OpCodes.Ldc_I4 && instructions[i - 1].OpCode == OpCodes.Ldarg_0)
				{
					rpcID = (uint)(int)instructions[i].Operand;
				}
				if (!(instructions[i].OpCode != OpCodes.Call))
				{
					object operand = instructions[i].Operand;
					MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
					if (val != null && (Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendClientRpc) || Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendServerRpc)))
					{
						LobbyControl.Log.LogDebug((object)$"Rpc Id found for {methodInfo.Name}: {rpcID}U");
						return true;
					}
				}
			}
			LobbyControl.Log.LogFatal((object)("Cannot find Rpc ID for " + methodInfo.Name));
			return false;
		}
	}
}
namespace LobbyControl.Utils.IL
{
	internal class ILInjector
	{
		[CompilerGenerated]
		private sealed class <GetRelativeInstructions>d__34 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			public ILInjector <>4__this;

			private int offset;

			public int <>3__offset;

			private int size;

			public int <>3__size;

			private int <i>5__2;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetRelativeInstructions>d__34(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				ILInjector iLInjector = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__2++;
					break;
				}
				if (<i>5__2 < size)
				{
					<>2__current = iLInjector.instructions[iLInjector.index + offset + <i>5__2];
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<GetRelativeInstructions>d__34 <GetRelativeInstructions>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetRelativeInstructions>d__ = this;
				}
				else
				{
					<GetRelativeInstructions>d__ = new <GetRelativeInstructions>d__34(0)
					{
						<>4__this = <>4__this
					};
				}
				<GetRelativeInstructions>d__.offset = <>3__offset;
				<GetRelativeInstructions>d__.size = <>3__size;
				return <GetRelativeInstructions>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private const string INVALID = "Injector is invalid";

		private List<CodeInstruction> instructions = instructions.ToList();

		private ILGenerator generator;

		private int index;

		private int matchEnd;

		public int Index
		{
			get
			{
				return index;
			}
			set
			{
				index = value;
			}
		}

		public bool IsValid
		{
			get
			{
				if (instructions != null)
				{
					return IsIndexValid(index);
				}
				return false;
			}
		}

		public CodeInstruction Instruction
		{
			get
			{
				if (!IsIndexInRange(index))
				{
					return null;
				}
				return instructions[index];
			}
			set
			{
				if (!IsIndexInRange(index))
				{
					throw new InvalidOperationException($"Current index {index} is out of range of instruction count {instructions.Count}");
				}
				instructions[index] = value;
			}
		}

		public CodeInstruction LastMatchedInstruction
		{
			get
			{
				int num = matchEnd - 1;
				if (!IsIndexInRange(num))
				{
					return null;
				}
				return instructions[num];
			}
			set
			{
				int num = matchEnd - 1;
				if (!IsIndexInRange(num))
				{
					throw new InvalidOperationException($"Last matched index {index} is out of range of instruction count {instructions.Count}");
				}
				instructions[num] = value;
			}
		}

		public ICollection<CodeInstruction> Instructions => instructions.AsReadOnly();

		public ILInjector(IEnumerable<CodeInstruction> instructions, ILGenerator generator = null)
		{
			this.generator = generator;
			matchEnd = -1;
			base..ctor();
		}

		public ILInjector GoToStart()
		{
			matchEnd = index;
			index = 0;
			return this;
		}

		public ILInjector GoToEnd()
		{
			matchEnd = index;
			index = instructions.Count;
			return this;
		}

		public ILInjector Forward(int offset)
		{
			if (!IsValid)
			{
				return this;
			}
			matchEnd = index;
			index = Math.Clamp(index + offset, -1, instructions.Count);
			return this;
		}

		public ILInjector Back(int offset)
		{
			return Forward(-offset);
		}

		private void MarkInvalid()
		{
			index = -1;
			matchEnd = -1;
		}

		private void Search(bool forward, ILMatcher[] predicates)
		{
			if (!IsValid)
			{
				return;
			}
			int num = 1;
			if (!forward)
			{
				num = -1;
				index--;
			}
			while (forward ? (index < instructions.Count) : (index >= 0))
			{
				if (forward && index + predicates.Length > instructions.Count)
				{
					index = instructions.Count;
					break;
				}
				int i;
				for (i = 0; i < predicates.Length && predicates[i].Matches(instructions[index + i]); i++)
				{
				}
				if (i == predicates.Length)
				{
					matchEnd = index + i;
					return;
				}
				index += num;
			}
			MarkInvalid();
		}

		public ILInjector Find(params ILMatcher[] predicates)
		{
			Search(forward: true, predicates);
			return this;
		}

		public ILInjector ReverseFind(params ILMatcher[] predicates)
		{
			Search(forward: false, predicates);
			return this;
		}

		public ILInjector GoToPush(int popIndex)
		{
			if (!IsValid)
			{
				return this;
			}
			matchEnd = index;
			index--;
			int num = 0;
			while (index >= 0)
			{
				CodeInstruction instruction = instructions[index];
				num += instruction.PushCount();
				num -= instruction.PopCount();
				if (num >= popIndex)
				{
					return this;
				}
				index--;
			}
			return this;
		}

		public ILInjector SkipBranch()
		{
			if (Instruction == null)
			{
				return this;
			}
			if (!(Instruction.operand is Label label))
			{
				throw new InvalidOperationException($"Current instruction is not a branch: {Instruction}");
			}
			return FindLabel(label);
		}

		public ILInjector FindLabel(Label label)
		{
			if (label == default(Label))
			{
				return this;
			}
			matchEnd = index;
			for (index = 0; index < instructions.Count; index++)
			{
				if (instructions[index].labels.Contains(label))
				{
					return this;
				}
			}
			MarkInvalid();
			return this;
		}

		public ILInjector GoToMatchEnd()
		{
			index = matchEnd;
			return this;
		}

		public ILInjector GoToLastMatchedInstruction()
		{
			if (!IsIndexValid(matchEnd))
			{
				return this;
			}
			index = matchEnd - 1;
			return this;
		}

		private bool IsIndexValid(int index)
		{
			return index != -1;
		}

		private bool IsIndexInRange(int index)
		{
			if (index >= 0)
			{
				return index < instructions.Count;
			}
			return false;
		}

		public CodeInstruction GetRelativeInstruction(int offset)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			int num = index + offset;
			if (!IsIndexInRange(num))
			{
				throw new IndexOutOfRangeException($"Offset {offset} would read out of bounds at index {num}");
			}
			return instructions[num];
		}

		public ILInjector SetRelativeInstruction(int offset, CodeInstruction instruction)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			int num = index + offset;
			if (!IsIndexInRange(num))
			{
				throw new IndexOutOfRangeException($"Offset {offset} would write out of bounds at index {num}");
			}
			instructions[num] = instruction;
			return this;
		}

		[IteratorStateMachine(typeof(<GetRelativeInstructions>d__34))]
		public IEnumerable<CodeInstruction> GetRelativeInstructions(int offset, int size)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetRelativeInstructions>d__34(-2)
			{
				<>4__this = this,
				<>3__offset = offset,
				<>3__size = size
			};
		}

		public IEnumerable<CodeInstruction> GetRelativeInstructions(int size)
		{
			return GetRelativeInstructions(0, size);
		}

		private void GetLastMatchRangeAbsolute(out int start, out int end)
		{
			start = index;
			end = matchEnd;
			if (start > end)
			{
				int num = end;
				int num2 = start;
				start = num;
				end = num2;
			}
		}

		private void GetLastMatchRange(out int start, out int size)
		{
			GetLastMatchRangeAbsolute(out start, out var end);
			if (start < 0 || start >= instructions.Count)
			{
				throw new InvalidOperationException($"Last match range starts at invalid index {start}");
			}
			if (end < 0 || end > instructions.Count)
			{
				throw new InvalidOperationException($"Last match range ends at invalid index {end}");
			}
			size = end - start;
		}

		public List<CodeInstruction> GetLastMatch()
		{
			GetLastMatchRange(out var start, out var size);
			return instructions.GetRange(start, size);
		}

		public ILInjector DefineLabel(out Label label)
		{
			if (generator == null)
			{
				throw new InvalidOperationException("No ILGenerator was provided");
			}
			label = generator.DefineLabel();
			return this;
		}

		public ILInjector AddLabel(out Label label)
		{
			DefineLabel(out label);
			return AddLabel(label);
		}

		public ILInjector AddLabel(Label label)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Instruction = new CodeInstruction(Instruction);
			Instruction.labels.Add(label);
			return this;
		}

		public ILInjector InsertInPlace(params CodeInstruction[] instructions)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			this.instructions.InsertRange(index, instructions);
			if (matchEnd >= index)
			{
				matchEnd += instructions.Length;
			}
			return this;
		}

		public ILInjector Insert(params CodeInstruction[] instructions)
		{
			InsertInPlace(instructions);
			index += instructions.Length;
			return this;
		}

		public ILInjector InsertInPlaceAfterBranch(params CodeInstruction[] instructions)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			List<Label> labels = Instruction.labels;
			Instruction = new CodeInstruction(Instruction);
			Instruction.labels.Clear();
			this.instructions.InsertRange(index, instructions);
			Instruction.labels.AddRange(labels);
			if (matchEnd >= index)
			{
				matchEnd += instructions.Length;
			}
			return this;
		}

		public ILInjector InsertAfterBranch(params CodeInstruction[] instructions)
		{
			InsertInPlaceAfterBranch(instructions);
			index += instructions.Length;
			return this;
		}

		public ILInjector RemoveAllPreviousInstructions()
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			instructions.RemoveRange(0, index);
			matchEnd -= index;
			if (matchEnd < 0)
			{
				matchEnd = 0;
			}
			index = 0;
			return this;
		}

		public ILInjector Remove(int count = 1)
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid");
			}
			instructions.RemoveRange(index, count);
			if (matchEnd > index)
			{
				matchEnd = Math.Max(index, matchEnd - count);
			}
			return this;
		}

		public ILInjector RemoveLastMatch()
		{
			GetLastMatchRange(out var start, out var size);
			List<Label> labels = instructions[start].labels;
			instructions.RemoveRange(start, size);
			index = start;
			matchEnd = start;
			instructions[start].labels.AddRange(labels);
			return this;
		}

		public ILInjector ReplaceLastMatch(params CodeInstruction[] replacementInstructions)
		{
			if (replacementInstructions.Length == 0)
			{
				throw new ArgumentException("Cannot replace a match with an empty array.");
			}
			GetLastMatchRange(out var start, out var size);
			List<Label> labels = instructions[start].labels;
			instructions.RemoveRange(start, size);
			instructions.InsertRange(start, replacementInstructions);
			index = start;
			matchEnd = start + replacementInstructions.Length;
			instructions[start].labels.AddRange(labels);
			return this;
		}

		public List<CodeInstruction> ReleaseInstructions()
		{
			List<CodeInstruction> result = instructions;
			instructions = null;
			return result;
		}

		public ILInjector PrintContext(int context, string header = "")
		{
			if (!IsValid)
			{
				throw new InvalidOperationException("Injector is invalid (" + header + ")");
			}
			StringBuilder stringBuilder = new StringBuilder(header);
			if (header.Length > 0)
			{
				stringBuilder.Append(':');
			}
			stringBuilder.AppendLine();
			GetLastMatchRangeAbsolute(out var start, out var end);
			int num = Math.Min(end + 1 + context, instructions.Count);
			for (int i = Math.Max(start - context, 0); i < num; i++)
			{
				if (end == -1 && i == index)
				{
					stringBuilder.Append("╶> ");
				}
				else
				{
					if (i >= start && i < end)
					{
						stringBuilder.Append("│");
					}
					else
					{
						stringBuilder.Append(" ");
					}
					if (i == index)
					{
						stringBuilder.Append("╶> ");
					}
					else
					{
						stringBuilder.Append("   ");
					}
				}
				stringBuilder.AppendLine($"{i}: {instructions[i]}");
			}
			LobbyControl.Log.LogFatal((object)stringBuilder);
			return this;
		}

		public ILInjector PrintContext(string header = "")
		{
			return PrintContext(4, header);
		}
	}
	internal interface ILMatcher
	{
		bool Matches(CodeInstruction instruction);

		ILMatcher CaptureAs(out CodeInstruction variable)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			variable = new CodeInstruction(OpCodes.Nop, (object)null);
			return new InstructionCapturingMatcher(this, variable);
		}

		unsafe ILMatcher CaptureOperandAs<T>(out T operand) where T : unmanaged
		{
			operand = default(T);
			fixed (T* operand2 = &operand)
			{
				return new OperandCapturingMatcher<T>(this, operand2);
			}
		}

		static ILMatcher Not(ILMatcher matcher)
		{
			return new NotMatcher(matcher);
		}

		static ILMatcher Opcode(OpCode opcode)
		{
			return new OpcodeMatcher(opcode);
		}

		static ILMatcher Opcodes(params OpCode[] opcodes)
		{
			return new OpcodesMatcher(opcodes);
		}

		static ILMatcher OpcodeOperand(OpCode opcode, object operand)
		{
			return new OpcodeOperandMatcher(opcode, operand);
		}

		static ILMatcher Instruction(CodeInstruction instruction)
		{
			return new InstructionMatcher(instruction);
		}

		static ILMatcher Ldarg(int? arg = null)
		{
			return new LdargMatcher(arg);
		}

		static ILMatcher Ldloc(int? loc = null)
		{
			return new LdlocMatcher(loc);
		}

		static ILMatcher Stloc(int? loc = null)
		{
			return new StlocMatcher(loc);
		}

		static ILMatcher Ldc(int? value = null)
		{
			return new LdcI32Matcher(value);
		}

		static ILMatcher Branch()
		{
			return new BranchMatcher();
		}

		static ILMatcher Ldfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Ldfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Ldfld, field);
		}

		static ILMatcher Ldsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Ldsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Ldsfld, field);
		}

		static ILMatcher Stfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Stfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Stfld, field);
		}

		static ILMatcher Stsfld(FieldInfo field, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (field == null)
			{
				LobbyControl.Log.LogWarning((object)$"Field passed to ILMatcher.Stsfld() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return new OpcodeOperandMatcher(OpCodes.Stsfld, field);
		}

		static ILMatcher Callvirt(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (method == null)
			{
				LobbyControl.Log.LogWarning((object)$"Method passed to ILMatcher.Callvirt() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return OpcodeOperand(OpCodes.Callvirt, method);
		}

		static ILMatcher Call(MethodBase method, [CallerMemberName] string callerName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
		{
			if (method == null)
			{
				LobbyControl.Log.LogWarning((object)$"Method passed to ILMatcher.Call() was null at {sourceFilePath}#{sourceLineNumber} ({callerName})");
			}
			return OpcodeOperand(OpCodes.Call, method);
		}

		static ILMatcher Predicate(Func<CodeInstruction, bool> predicate)
		{
			return new PredicateMatcher(predicate);
		}

		static ILMatcher Predicate(Func<FieldInfo, bool> predicate)
		{
			return new PredicateMatcher((CodeInstruction insn) => insn.operand is FieldInfo arg && predicate(arg));
		}
	}
	internal class NotMatcher : ILMatcher
	{
		private readonly ILMatcher matcher;

		public NotMatcher(ILMatcher matcher)
		{
			this.matcher = matcher;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return !matcher.Matches(instruction);
		}
	}
	internal class OpcodeMatcher : ILMatcher
	{
		private readonly OpCode opcode;

		public OpcodeMatcher(OpCode opcode)
		{
			this.opcode = opcode;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return instruction.opcode == opcode;
		}
	}
	internal class OpcodesMatcher : ILMatcher
	{
		private readonly OpCode[] opcodes;

		public OpcodesMatcher(OpCode[] opcodes)
		{
			this.opcodes = opcodes;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return opcodes.Contains(instruction.opcode);
		}
	}
	internal class OpcodeOperandMatcher : ILMatcher
	{
		private readonly OpCode opcode;

		private readonly object operand;

		public OpcodeOperandMatcher(OpCode opcode, object operand)
		{
			this.opcode = opcode;
			this.operand = operand;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.opcode == opcode)
			{
				return instruction.operand == operand;
			}
			return false;
		}
	}
	internal class InstructionMatcher : ILMatcher
	{
		private readonly OpCode opcode = instruction.opcode;

		private readonly object operand = instruction.operand;

		private readonly Label[] labels = instruction.labels.ToArray();

		public InstructionMatcher(CodeInstruction instruction)
		{
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (instruction.opcode != opcode)
			{
				return false;
			}
			if (instruction.operand != operand)
			{
				return false;
			}
			if (instruction.labels.Count != labels.Length)
			{
				return false;
			}
			for (int i = 0; i < labels.Length; i++)
			{
				if (labels[i] != instruction.labels[i])
				{
					return false;
				}
			}
			return true;
		}
	}
	internal class LdargMatcher : ILMatcher
	{
		private readonly int? arg;

		public LdargMatcher(int? arg)
		{
			this.arg = arg;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!arg.HasValue)
			{
				return instruction.GetLdargIndex().HasValue;
			}
			return instruction.GetLdargIndex() == arg;
		}
	}
	internal class LdlocMatcher : ILMatcher
	{
		private readonly int? loc;

		public LdlocMatcher(int? loc)
		{
			this.loc = loc;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!loc.HasValue)
			{
				return instruction.GetLdlocIndex().HasValue;
			}
			return instruction.GetLdlocIndex() == loc;
		}
	}
	internal class StlocMatcher : ILMatcher
	{
		private readonly int? loc;

		public StlocMatcher(int? loc)
		{
			this.loc = loc;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!loc.HasValue)
			{
				return instruction.GetStlocIndex().HasValue;
			}
			return instruction.GetStlocIndex() == loc;
		}
	}
	internal class LdcI32Matcher : ILMatcher
	{
		private readonly int? value;

		public LdcI32Matcher(int? value)
		{
			this.value = value;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			if (!value.HasValue)
			{
				return instruction.GetLdcI32().HasValue;
			}
			return instruction.GetLdcI32() == value;
		}
	}
	internal class BranchMatcher : ILMatcher
	{
		public bool Matches(CodeInstruction instruction)
		{
			Label? label = default(Label?);
			return CodeInstructionExtensions.Branches(instruction, ref label);
		}
	}
	internal class PredicateMatcher : ILMatcher
	{
		private readonly Func<CodeInstruction, bool> predicate;

		public PredicateMatcher(Func<CodeInstruction, bool> predicate)
		{
			this.predicate = predicate;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			return predicate(instruction);
		}
	}
	internal class InstructionCapturingMatcher : ILMatcher
	{
		private readonly ILMatcher matcher;

		private readonly CodeInstruction variable;

		public InstructionCapturingMatcher(ILMatcher matcher, CodeInstruction variable)
		{
			this.matcher = matcher;
			this.variable = variable;
			base..ctor();
		}

		public bool Matches(CodeInstruction instruction)
		{
			bool flag = matcher.Matches(instruction);
			if (flag)
			{
				variable.opcode = instruction.opcode;
				variable.operand = instruction.operand;
				variable.blocks = instruction.blocks.ToList();
				variable.labels = instruction.labels.ToList();
			}
			return flag;
		}
	}
	internal class OperandCapturingMatcher<T> : ILMatcher where T : unmanaged
	{
		private readonly ILMatcher matcher;

		private unsafe readonly T* operand;

		public unsafe OperandCapturingMatcher(ILMatcher matcher, T* operand)
		{
			this.matcher = matcher;
			this.operand = operand;
			base..ctor();
		}

		public unsafe bool Matches(CodeInstruction instruction)
		{
			bool flag = matcher.Matches(instruction);
			if (flag)
			{
				*operand = (T)instruction.operand;
			}
			return flag;
		}
	}
	internal static class InstructionUtilities
	{
		public static CodeInstruction MakeLdarg(int index)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (index < 256)
			{
				return (CodeInstruction)(index switch
				{
					0 => (object)new CodeInstruction(OpCodes.Ldarg_0, (object)null), 
					1 => (object)new CodeInstruction(OpCodes.Ldarg_1, (object)null), 
					2 => (object)new CodeInstruction(OpCodes.Ldarg_2, (object)null), 
					3 => (object)new CodeInstruction(OpCodes.Ldarg_3, (object)null), 
					_ => (object)new CodeInstruction(OpCodes.Ldarg_S, (object)index), 
				});
			}
			return new CodeInstruction(OpCodes.Ldarg, (object)index);
		}

		public static int PopCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
			{
				MethodBase methodBase = (MethodBase)instruction.operand;
				int num = methodBase.GetParameters().Length;
				if (!methodBase.IsStatic)
				{
					num++;
				}
				return num;
			}
			if (instruction.opcode == OpCodes.Ret)
			{
				return 1;
			}
			return instruction.opcode.StackBehaviourPop switch
			{
				StackBehaviour.Pop0 => 0, 
				StackBehaviour.Pop1 => 1, 
				StackBehaviour.Pop1_pop1 => 2, 
				StackBehaviour.Popi => 1, 
				StackBehaviour.Popi_pop1 => 2, 
				StackBehaviour.Popi_popi => 2, 
				StackBehaviour.Popi_popi8 => 2, 
				StackBehaviour.Popi_popi_popi => 3, 
				StackBehaviour.Popi_popr4 => 2, 
				StackBehaviour.Popi_popr8 => 2, 
				StackBehaviour.Popref => 1, 
				StackBehaviour.Popref_pop1 => 2, 
				StackBehaviour.Popref_popi => 2, 
				StackBehaviour.Popref_popi_popi => 3, 
				StackBehaviour.Popref_popi_popi8 => 3, 
				StackBehaviour.Popref_popi_popr4 => 3, 
				StackBehaviour.Popref_popi_popr8 => 3, 
				StackBehaviour.Popref_popi_popref => 3, 
				StackBehaviour.Varpop => throw new NotImplementedException($"Variable pop on non-call instruction '{instruction}'"), 
				StackBehaviour.Popref_popi_pop1 => 3, 
				_ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), 
			};
		}

		public static int PushCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Newobj)
			{
				if (instruction.operand is MethodInfo methodInfo && methodInfo.ReturnType == typeof(void))
				{
					return 0;
				}
				return 1;
			}
			return instruction.opcode.StackBehaviourPush switch
			{
				StackBehaviour.Push0 => 0, 
				StackBehaviour.Push1 => 1, 
				StackBehaviour.Push1_push1 => 2, 
				StackBehaviour.Pushi => 1, 
				StackBehaviour.Pushi8 => 1, 
				StackBehaviour.Pushr4 => 1, 
				StackBehaviour.Pushr8 => 1, 
				StackBehaviour.Pushref => 1, 
				StackBehaviour.Varpush => throw new NotImplementedException($"Variable push on non-call instruction '{instruction}'"), 
				_ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), 
			};
		}

		public static int? GetLdargIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldarg_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldarg_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldarg_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldarg_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldarg || opcode == OpCodes.Ldarg_S)
			{
				return instruction.operand as int?;
			}
			return null;
		}

		public static int? GetLdlocIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
			{
				return (instruction.operand as LocalBuilder)?.LocalIndex;
			}
			return null;
		}

		public static int? GetStlocIndex(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
			{
				return (instruction.operand as LocalBuilder)?.LocalIndex;
			}
			return null;
		}

		public static CodeInstruction LdlocToStloc(this CodeInstruction instruction)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldloc_0)
			{
				return new CodeInstruction(OpCodes.Stloc_0, (object)null);
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				return new CodeInstruction(OpCodes.Stloc_1, (object)null);
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				return new CodeInstruction(OpCodes.Stloc_2, (object)null);
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				return new CodeInstruction(OpCodes.Stloc_3, (object)null);
			}
			if (opcode == OpCodes.Ldloc || opcode == OpCodes.Ldloc_S)
			{
				return new CodeInstruction(OpCodes.Stloc, instruction.operand);
			}
			return null;
		}

		public static CodeInstruction StlocToLdloc(this CodeInstruction instruction)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Stloc_0)
			{
				return new CodeInstruction(OpCodes.Ldloc_0, (object)null);
			}
			if (opcode == OpCodes.Stloc_1)
			{
				return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
			}
			if (opcode == OpCodes.Stloc_2)
			{
				return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
			}
			if (opcode == OpCodes.Stloc_3)
			{
				return new CodeInstruction(OpCodes.Ldloc_3, (object)null);
			}
			if (opcode == OpCodes.Stloc || opcode == OpCodes.Stloc_S)
			{
				return new CodeInstruction(OpCodes.Ldloc, instruction.operand);
			}
			return null;
		}

		public static int? GetLdcI32(this CodeInstruction instruction)
		{
			OpCode opcode = instruction.opcode;
			if (opcode == OpCodes.Ldc_I4_M1)
			{
				return -1;
			}
			if (opcode == OpCodes.Ldc_I4_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldc_I4_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldc_I4_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldc_I4_3)
			{
				return 3;
			}
			if (opcode == OpCodes.Ldc_I4_4)
			{
				return 4;
			}
			if (opcode == OpCodes.Ldc_I4_5)
			{
				return 5;
			}
			if (opcode == OpCodes.Ldc_I4_6)
			{
				return 6;
			}
			if (opcode == OpCodes.Ldc_I4_7)
			{
				return 7;
			}
			if (opcode == OpCodes.Ldc_I4_8)
			{
				return 8;
			}
			if (opcode == OpCodes.Ldc_I4_S)
			{
				return instruction.operand as sbyte?;
			}
			if (opcode == OpCodes.Ldc_I4)
			{
				return instruction.operand as int?;
			}
			return null;
		}
	}
	public static class ReflectionExtensions
	{
		public static MethodInfo GetGenericMethod(this Type type, string name, Type[] parameters, Type[] genericArgs)
		{
			MethodInfo[] methods = type.GetMethods();
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				if (!(methodInfo.Name != name) && methodInfo.IsGenericMethodDefinition)
				{
					return methodInfo.MakeGenericMethod(genericArgs);
				}
			}
			return null;
		}
	}
}
namespace LobbyControl.TerminalCommands
{
	public class Command
	{
		public TerminalNode previousTerminalNode;

		public bool awaitingConfirmation
		{
			get
			{
				return CommandManager.awaitingConfirmationCommand == this;
			}
			set
			{
				CommandManager.awaitingConfirmationCommand = (value ? this : null);
			}
		}

		public virtual bool IsCommand(string[] args)
		{
			return false;
		}

		public virtual TerminalNode Execute(string[] args)
		{
			return TerminalPatch.CreateTerminalNode("Execute override was not found.\n\n");
		}

		public virtual TerminalNode ExecuteConfirmation(string[] args)
		{
			string text = args[0].ToLower();
			if ("confirm".Contains(text) && text.Length > 0)
			{
				return OnConfirm(args);
			}
			if ("deny".Contains(text) && text.Length > 0)
			{
				return OnDeny(args);
			}
			return OnInvalidInput(args);
		}

		protected virtual TerminalNode OnConfirm(string[] args)
		{
			return TerminalPatch.CreateTerminalNode("OnConfirm override was not found.\n\n");
		}

		protected virtual TerminalNode OnDeny(string[] args)
		{
			return TerminalPatch.CreateTerminalNode("OnDeny override was not found.\n\n");
		}

		protected virtual TerminalNode OnInvalidInput(string[] args)
		{
			return previousTerminalNode;
		}
	}
	internal class CommandManager
	{
		private static List<Command> commands = new List<Command>();

		public static Command awaitingConfirmationCommand;

		public static void Initialize()
		{
			commands = new List<Command>
			{
				new LobbyCommand()
			};
			awaitingConfirmationCommand = null;
		}

		public static bool TryExecuteCommand(string[] array, out TerminalNode terminalNode)
		{
			terminalNode = null;
			if (awaitingConfirmationCommand != null)
			{
				Command command = awaitingConfirmationCommand;
				terminalNode = command.ExecuteConfirmation(array);
				command.previousTerminalNode = terminalNode;
				return true;
			}
			Command command2 = GetCommand(array);
			if (command2 == null)
			{
				return false;
			}
			terminalNode = command2.Execute(array);
			command2.previousTerminalNode = terminalNode;
			return true;
		}

		public static void OnLocalDisconnect()
		{
			awaitingConfirmationCommand = null;
		}

		public static void OnTerminalQuit()
		{
			awaitingConfirmationCommand = null;
		}

		private static Command GetCommand(string[] args)
		{
			Command result = null;
			commands.ForEach(delegate(Command command)
			{
				if (result == null && command.IsCommand(args))
				{
					result = command;
				}
			});
			return result;
		}
	}
	public class LobbyCommand : Command
	{
		[CompilerGenerated]
		private sealed class <LoadLobbyCoroutine>d__19 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private StartOfRound <startOfRound>5__2;

			private Terminal <terminal>5__3;

			private bool <mem>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadLobbyCoroutine>d__19(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<startOfRound>5__2 = null;
				<terminal>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fa: Expected O, but got Unknown
				//IL_021b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0225: Expected O, but got Unknown
				//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Expected O, but got Unknown
				//IL_016c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0176: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<startOfRound>5__2 = StartOfRound.Instance;
					<terminal>5__3 = Object.FindObjectOfType<Terminal>();
					<startOfRound>5__2.ResetShip();
					VehicleController[] array = Object.FindObjectsOfType<VehicleController>();
					VehicleController[] array2 = array;
					foreach (VehicleController val in array2)
					{
						if ((Object)(object)((NetworkBehaviour)val).NetworkObject != (Object)null)
						{
							((NetworkBehaviour)val).NetworkObject.Despawn(false);
						}
					}
					<mem>5__4 = GameNetworkManager.Instance.gameHasStarted;
					GameNetworkManager.Instance.gameHasStarted = false;
					foreach (KeyValuePair<int, GameObject> item in StartOfRound.Instance.SpawnedShipUnlockables.ToList())
					{
						UnlockableItem val2 = <startOfRound>5__2.unlockablesList.unlockables[item.Key];
						if (val2.alreadyUnlocked && val2.spawnPrefab && !((Object)(object)item.Value == (Object)null))
						{
							NetworkObject component = item.Value.GetComponent<NetworkObject>();
							if ((Object)(object)component != (Object)null && component.IsSpawned)
							{
								component.Despawn(true);
							}
						}
					}
					<startOfRound>5__2.SpawnedShipUnlockables.Clear();
					<startOfRound>5__2.suitsPlaced = 0;
					GameNetworkManager.Instance.ResetUnlockablesListValues(false);
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					<startOfRound>5__2.SetTimeAndPlanetToSavedSettings();
					<startOfRound>5__2.SetMapScreenInfoToCurrentLevel();
					<terminal>5__3.Start();
					if (<startOfRound>5__2.connectedPlayersAmount >= 1)
					{
						RefreshLobby();
					}
					ReloadUnlockables();
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<startOfRound>5__2.LoadAttachedVehicle();
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<startOfRound>5__2.LoadShipGrabbableItems();
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					if (<startOfRound>5__2.connectedPlayersAmount >= 1)
					{
						<startOfRound>5__2.SyncShipUnlockablesServerRpc();
					}
					GameNetworkManager.Instance.gameHasStarted = <mem>5__4;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const string DefaultText = "- status        : prints the current lobby status\r\n\r\nSteam:\r\n- open          : open the lobby\r\n- close         : close the lobby\r\n- private       : set lobby to Invite Only\r\n- friend        : set lobby to Friends Only\r\n- public        : set lobby to Public\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave      : toggle autosave for the savefile\r\n- save (name)   : save the lobby\r\n- load (name)   : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear         : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall       : drop all items to the ground\r\n";

		private const string DefaultTextLAN = "- status        : prints the current lobby status\r\n\r\nLAN:\r\n- open          : set the lobby to be discoverable\r\n- close         : set the lobby to be non-discoverable\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave      : toggle autosave for the savefile\r\n- save (name)   : save the lobby\r\n- load (name)   : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear         : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall       : drop all items to the ground\r\n";

		private static uint? _returnUnlockableFromStorageServerRpcID;

		private static uint? _onPlayerConnectedClientRpcID;

		public override bool IsCommand(string[] args)
		{
			if (GameNetworkManager.Instance.isHostingGame)
			{
				return args[0].Trim().ToLower() == "lobby";
			}
			return false;
		}

		public override TerminalNode Execute(string[] args)
		{
			TerminalNode node = ScriptableObject.CreateInstance<TerminalNode>();
			try
			{
				if (Utility.IsNullOrWhiteSpace(args[1]))
				{
					return HelpNode();
				}
				switch (args[1])
				{
				case "status":
					StatusCommand(ref node, args);
					break;
				case "open":
				{
					if (PerformOrbitCheck(node, out var errorText10))
					{
						return errorText10;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						OpenCommand(ref node, args);
					}
					break;
				}
				case "close":
				{
					if (PerformOrbitCheck(node, out var errorText7))
					{
						return errorText7;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						CloseCommand(ref node, args);
					}
					break;
				}
				case "private":
				{
					if (PerformOrbitCheck(node, out var errorText3))
					{
						return errorText3;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						PrivateCommand(ref node, args);
					}
					break;
				}
				case "friend":
				{
					if (PerformOrbitCheck(node, out var errorText11))
					{
						return errorText11;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						FriendCommand(ref node, args);
					}
					break;
				}
				case "public":
				{
					if (PerformOrbitCheck(node, out var errorText2))
					{
						return errorText2;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						PublicCommand(ref node, args);
					}
					break;
				}
				case "rename":
				{
					if (PerformOrbitCheck(node, out var errorText6))
					{
						return errorText6;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						RenameCommand(ref node, args);
					}
					break;
				}
				case "autosave":
					AutoSaveCommand(ref node, args);
					break;
				case "save":
				{
					if (PerformOrbitCheck(node, out var errorText8))
					{
						return errorText8;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						SaveCommand(ref node, args);
					}
					break;
				}
				case "load":
				{
					if (PerformOrbitCheck(node, out var errorText4))
					{
						return errorText4;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						LoadCommand(ref node, args);
					}
					break;
				}
				case "switch":
				{
					if (PerformOrbitCheck(node, out var errorText9))
					{
						return errorText9;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						SwitchCommand(ref node, args);
					}
					break;
				}
				case "clear":
				{
					if (PerformOrbitCheck(node, out var errorText5))
					{
						return errorText5;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						ClearCommand(ref node, args);
					}
					break;
				}
				case "dropall":
				{
					if (PerformOrbitCheck(node, out var errorText))
					{
						return errorText;
					}
					if (!LobbyControl.CanModifyLobby)
					{
						node.displayText = "Lobby cannot be changed at the moment\n\n";
					}
					else
					{
						DropAllCommand(ref node, args);
					}
					break;
				}
				case "help":
					node = HelpNode();
					break;
				default:
					node = HelpNode();
					node.displayText = "Invalid Command, options:\n" + node.displayText;
					break;
				}
			}
			catch (Exception ex)
			{
				LobbyControl.Log.LogError((object)("Exception:\n\n" + ex));
				node.displayText = "Exception!\n\n";
			}
			return node;
		}

		private static bool StatusCommand(ref TerminalNode node, string[] args)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			GameNetworkManager instance = GameNetworkManager.Instance;
			bool flag = false;
			string value = instance.steamLobbyName;
			string value2;
			if (instance.disableSteam)
			{
				UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
				value2 = ((component.ConnectionData.ServerListenAddress == "0.0.0.0") ? "Public" : "Private");
			}
			else
			{
				if (!instance.currentLobby.HasValue)
				{
					node.displayText = "Failed to fetch lobby ( was null )\n\n";
					return false;
				}
				Lobby value3 = instance.currentLobby.Value;
				flag = LobbyPatcher.IsOpen(value3);
				LobbyType visibility = LobbyPatcher.GetVisibility(value3);
				value2 = ((object)(LobbyType)(ref visibility)).ToString();
				value = ((Lobby)(ref value3)).GetData("name");
			}
			bool canSave = LobbyControl.CanSave;
			StringBuilder stringBuilder = new StringBuilder("Lobby Status:");
			stringBuilder.Append("\n- File is '").Append(instance.currentSaveFileName).Append("'");
			stringBuilder.Append("\n- Name is '").Append(value).Append("'");
			if (!instance.disableSteam)
			{
				stringBuilder.Append("\n- Status is ").Append(flag ? "Open" : "Closed");
			}
			stringBuilder.Append("\n- Visibility is ").Append(value2);
			stringBuilder.Append("\n- Saving is ").Append(canSave ? "Automatic" : "Manual");
			stringBuilder.Append("\n\n");
			node.displayText = stringBuilder.ToString();
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool OpenCommand(ref TerminalNode node, string[] args)
		{
			LobbyControl.Log.LogDebug((object)"Reopening lobby, setting to joinable.");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (instance.disableSteam)
			{
				UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
				if (component.ConnectionData.ServerListenAddress != "0.0.0.0")
				{
					node.displayText = "Server is limited to local connections\n\n";
					return false;
				}
				instance.lobbyHostSettings.isLobbyPublic = true;
				ES3.Save<bool>("HostSettings_Public", instance.lobbyHostSettings.isLobbyPublic, "LCGeneralSaveData");
			}
			else if (!instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			instance.SetLobbyJoinable(true);
			Object.FindObjectOfType<QuickMenuManager>().inviteFriendsTextAlpha.alpha = 1f;
			string text = "Lobby is now Open";
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool CloseCommand(ref TerminalNode node, string[] args)
		{
			LobbyControl.Log.LogDebug((object)"Closing lobby, setting to not joinable.");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (instance.disableSteam)
			{
				UnityTransport component = ((Component)NetworkManager.Singleton).GetComponent<UnityTransport>();
				if (component.ConnectionData.ServerListenAddress != "0.0.0.0")
				{
					node.displayText = "Server is limited to local connections\n\n";
					return false;
				}
				instance.lobbyHostSettings.isLobbyPublic = false;
				ES3.Save<bool>("HostSettings_Public", instance.lobbyHostSettings.isLobbyPublic, "LCGeneralSaveData");
			}
			else if (!instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			instance.SetLobbyJoinable(false);
			Object.FindObjectOfType<QuickMenuManager>().inviteFriendsTextAlpha.alpha = 0f;
			string text = "Lobby is now Closed";
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool PrivateCommand(ref TerminalNode node, string[] args)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			LobbyControl.Log.LogDebug((object)"Locking lobby, setting to Private.");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			ES3.Save<bool>("HostSettings_Public", false, "LCGeneralSaveData");
			Lobby value = instance.currentLobby.Value;
			((Lobby)(ref value)).SetPrivate();
			string text = "Lobby is now Private";
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool FriendCommand(ref TerminalNode node, string[] args)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			LobbyControl.Log.LogDebug((object)"Locking lobby, setting to Friends Only.");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			ES3.Save<bool>("HostSettings_Public", false, "LCGeneralSaveData");
			Lobby value = instance.currentLobby.Value;
			((Lobby)(ref value)).SetFriendsOnly();
			string text = "Lobby is now Friends Only";
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool PublicCommand(ref TerminalNode node, string[] args)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			LobbyControl.Log.LogDebug((object)"Unlocking lobby, setting to Public.");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			ES3.Save<bool>("HostSettings_Public", true, "LCGeneralSaveData");
			Lobby value = instance.currentLobby.Value;
			((Lobby)(ref value)).SetPublic();
			string text = "Lobby is now Public";
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool RenameCommand(ref TerminalNode node, string[] args)
		{
			//IL_00ac: 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)
			if (Utility.IsNullOrWhiteSpace(args[2]))
			{
				node.displayText = "Lobby name cannot be null\n\n";
				return false;
			}
			string text = args[2];
			if (text.Length > 40)
			{
				text = text.Substring(0, 40);
			}
			LobbyControl.Log.LogDebug((object)("Renaming lobby: \"" + text + "\""));
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!instance.disableSteam && !instance.currentLobby.HasValue)
			{
				node.displayText = "Failed to fetch lobby ( was null )\n\n";
				return false;
			}
			instance.lobbyHostSettings.lobbyName = text;
			instance.steamLobbyName = instance.lobbyHostSettings.lobbyName;
			if (instance.currentLobby.HasValue)
			{
				Lobby value = instance.currentLobby.Value;
				((Lobby)(ref value)).SetData("name", instance.steamLobbyName);
			}
			ES3.Save<string>("HostSettings_Name", instance.steamLobbyName, "LCGeneralSaveData");
			string text2 = "Lobby renamed to \"" + text + "\"";
			LobbyControl.Log.LogInfo((object)text2);
			node.displayText = text2 + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool AutoSaveCommand(ref TerminalNode node, string[] args)
		{
			LobbyControl.Log.LogDebug((object)"Toggling AutoSave");
			LobbyControl.CanSave = (LobbyControl.AutoSaveEnabled = !LobbyControl.AutoSaveEnabled);
			string text = "AutoSaving is now " + (LobbyControl.CanSave ? "On" : "Off");
			LobbyControl.Log.LogInfo((object)text);
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool SaveCommand(ref TerminalNode node, string[] args)
		{
			if (StartOfRound.Instance.isChallengeFile)
			{
				node.displayText = "Cannot Edit Challenge Save\n\n";
				return false;
			}
			LobbyControl.Log.LogDebug((object)"Saving Lobby");
			GameNetworkManager instance = GameNetworkManager.Instance;
			string currentSaveFileName = instance.currentSaveFileName;
			if (!Utility.IsNullOrWhiteSpace(args[2]))
			{
				string text = args[2];
				if (text.Length > 20)
				{
					text = text.Substring(0, 20);
				}
				instance.currentSaveFileName = text;
			}
			if (currentSaveFileName != instance.currentSaveFileName)
			{
				ES3.CopyFile(currentSaveFileName, instance.currentSaveFileName);
			}
			LobbyControl.CanSave = true;
			HUDManager.Instance.saveDataIconAnimatorB.SetTrigger("save");
			instance.SaveGameValues();
			string text2 = "Lobby Saved to " + instance.currentSaveFileName;
			LobbyControl.CanSave = LobbyControl.AutoSaveEnabled;
			instance.currentSaveFileName = currentSaveFileName;
			LobbyControl.Log.LogInfo((object)text2);
			node.displayText = text2 + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool LoadCommand(ref TerminalNode node, string[] args)
		{
			if (StartOfRound.Instance.isChallengeFile)
			{
				node.displayText = "Cannot Edit Challenge Save\n\n";
				return false;
			}
			LobbyControl.Log.LogDebug((object)"Reloading Lobby");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!Utility.IsNullOrWhiteSpace(args[2]))
			{
				string text = args[2];
				if (text.Length > 20)
				{
					text = text.Substring(0, 20);
				}
				instance.currentSaveFileName = text;
			}
			string text2 = "Lobby '" + instance.currentSaveFileName + "' loaded";
			((MonoBehaviour)StartOfRound.Instance).StartCoroutine(LoadLobbyCoroutine());
			LobbyControl.AutoSaveEnabled = (LobbyControl.CanSave = ES3.Load<bool>("LC_SavingMethod", GameNetworkManager.Instance.currentSaveFileName, true));
			LobbyControl.Log.LogInfo((object)text2);
			node.displayText = text2 + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool SwitchCommand(ref TerminalNode node, string[] args)
		{
			if (StartOfRound.Instance.isChallengeFile)
			{
				node.displayText = "Cannot Edit Challenge Save\n\n";
				return false;
			}
			LobbyControl.Log.LogDebug((object)"Switching Lobby");
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (Utility.IsNullOrWhiteSpace(args[2]))
			{
				node.displayText = "You need to specify a destination for the swap!";
				return false;
			}
			string text = args[2];
			if (text.Length > 20)
			{
				text = text.Substring(0, 20);
			}
			instance.currentSaveFileName = text;
			string text2 = "Lobby is now saving to '" + instance.currentSaveFileName + "'";
			node.displayText = text2 + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool ClearCommand(ref TerminalNode node, string[] args)
		{
			if (StartOfRound.Instance.isChallengeFile)
			{
				node.displayText = "Cannot Edit Challenge Save\n\n";
				return false;
			}
			LobbyControl.Log.LogDebug((object)"Clearing Lobby");
			LobbyControl.CanSave = true;
			GameNetworkManager.Instance.ResetSavedGameValues();
			ES3.DeleteFile(GameNetworkManager.Instance.currentSaveFileName);
			LobbyControl.CanSave = LobbyControl.AutoSaveEnabled;
			bool flag = LoadCommand(ref node, new string[3]);
			if (flag)
			{
				node.displayText = "Lobby is now Empty!";
			}
			return flag;
		}

		private static bool DropAllCommand(ref TerminalNode node, string[] args)
		{
			LobbyControl.Log.LogDebug((object)"Dropping all Items");
			string text = "All Items Dropped";
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				val.DropAllHeldItemsAndSync();
			}
			node.displayText = text + "\n\n";
			node.maxCharactersToType = node.displayText.Length + 2;
			return true;
		}

		private static bool PerformOrbitCheck(TerminalNode terminalNode, out TerminalNode errorText)
		{
			if (!StartOfRound.Instance.inShipPhase)
			{
				terminalNode.displayText = "Can only be used while in Orbit\n\n";
				errorText = terminalNode;
				return true;
			}
			errorText = null;
			return false;
		}

		private static TerminalNode HelpNode()
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = (GameNetworkManager.Instance.disableSteam ? "- status        : prints the current lobby status\r\n\r\nLAN:\r\n- open          : set the lobby to be discoverable\r\n- close         : set the lobby to be non-discoverable\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave      : toggle autosave for the savefile\r\n- save (name)   : save the lobby\r\n- load (name)   : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear         : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall       : drop all items to the ground\r\n" : "- status        : prints the current lobby status\r\n\r\nSteam:\r\n- open          : open the lobby\r\n- close         : close the lobby\r\n- private       : set lobby to Invite Only\r\n- friend        : set lobby to Friends Only\r\n- public        : set lobby to Public\r\n- rename [name] : change the name of the lobby\r\n\r\nSaving:\r\n- autosave      : toggle autosave for the savefile\r\n- save (name)   : save the lobby\r\n- load (name)   : load a savefile\r\n- switch (name) : swap savefile without loading it\r\n- clear         : reset the current lobby to empty\r\n\r\nExtra:\r\n- dropall       : drop all items to the ground\r\n");
			val.clearPreviousText = true;
			val.maxCharactersToType = val.displayText.Length + 2;
			return val;
		}

		[IteratorStateMachine(typeof(<LoadLobbyCoroutine>d__19))]
		private static IEnumerator LoadLobbyCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadLobbyCoroutine>d__19(0);
		}

		private static void ReloadUnlockables()
		{
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_01c9: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: 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)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00de: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			instance.LoadUnlockables();
			try
			{
				for (int i = 0; i < instance.unlockablesList.unlockables.Count; i++)
				{
					UnlockableItem val = instance.unlockablesList.unlockables[i];
					if (val.unlockableType == 0 || !val.alreadyUnlocked)
					{
						continue;
					}
					LobbyControl.Log.LogDebug((object)(val.unlockableName + " starting"));
					if (!instance.SpawnedShipUnlockables.ContainsKey(i))
					{
						instance.SpawnUnlockable(i);
					}
					PlaceableShipObject val2 = instance.SpawnedShipUnlockables[i].GetComponent<PlaceableShipObject>();
					if (val2 == null)
					{
						val2 = instance.SpawnedShipUnlockables[i].GetComponentInChildren<PlaceableShipObject>();
					}
					if (val2 != null)
					{
						LobbyControl.Log.LogDebug((object)(val.unlockableName + " continuing"));
						Quaternion val4;
						if (Object.op_Implicit((Object)(object)val2.parentObjectSecondary))
						{
							Quaternion rotation = ((Component)val2.parentObjectSecondary).transform.rotation;
							Quaternion rotation2 = ((Component)val2.parentObjectSecondary).transform.rotation;
							Quaternion rotation3 = ((Component)val2.mainMesh).transform.rotation;
							Quaternion val3 = rotation * Quaternion.Inverse(rotation2);
							val4 = val3 * rotation3;
							val.placedRotation = ((Quaternion)(ref val4)).eulerAngles;
							Vector3 position = val2.parentObjectSecondary.position;
							Vector3 val5 = ((Component)val2.parentObjectSecondary).transform.position - ((Component)val2.mainMesh).transform.position;
							Vector3 val6 = ((Component)val2.mainMesh).transform.position - ((Component)val2.placeObjectCollider).transform.position;
							val.placedPosition = position - val5 - val6;
						}
						else
						{
							Quaternion val7 = Quaternion.Euler(val2.parentObject.rotationOffset);
							Quaternion rotation4 = ((Component)val2.parentObject).transform.rotation;
							Quaternion rotation5 = ((Component)val2.mainMesh).transform.rotation;
							Quaternion val8 = val7 * Quaternion.Inverse(rotation4);
							val4 = val8 * rotation5;
							val.placedRotation = ((Quaternion)(ref val4)).eulerAngles;
							Vector3 val9 = ((Component)val2.parentObject).transform.position - ((Component)val2.mainMesh).transform.position;
							Vector3 val10 = ((Component)val2.mainMesh).transform.position - ((Component)val2.placeObjectCollider).transform.position;
							val.placedPosition = StartOfRound.Instance.elevatorTransform.TransformPoint(val2.parentObject.positionOffset) - val9 - val10;
						}
					}
				}
				if (instance.connectedPlayersAmount < 1)
				{
					return;
				}
				List<ulong> targetClientIds = instance.ClientPlayerList.Keys.ToList();
				ClientRpcParams val11 = default(ClientRpcParams);
				val11.Send = new ClientRpcSendParams
				{
					TargetClientIds = targetClientIds
				};
				ClientRpcParams val12 = val11;
				for (int j = 0; j < instance.unlockablesList.unlockables.Count; j++)
				{
					UnlockableItem val13 = instance.unlockablesList.unlockables[j];
					if (val13.alreadyUnlocked && !val13.inStorage && _returnUnlockableFromStorageServerRpcID.HasValue)
					{
						uint value = _returnUnlockableFromStorageServerRpcID.Value;
						FastBufferWriter val14 = ((NetworkBehaviour)instance).__beginSendClientRpc(value, val12, (RpcDelivery)0);
						BytePacker.WriteValueBitPacked(val14, j);
						((NetworkBehaviour)instance).__endSendClientRpc(ref val14, value, val12, (RpcDelivery)0);
					}
				}
				instance.SyncShipUnlockablesServerRpc();
			}
			catch (Exception ex)
			{
				LobbyControl.Log.LogError((object)ex);
			}
		}

		private static void RefreshLobby()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			List<ulong> list = new List<ulong>();
			List<ulong> list2 = new List<ulong>();
			for (int i = 0; i < instance.allPlayerObjects.Length; i++)
			{
				NetworkObject component = instance.allPlayerObjects[i].GetComponent<NetworkObject>();
				if (!component.IsOwnedByServer)
				{
					list.Add(component.OwnerClientId);
					list2.Add(component.OwnerClientId);
				}
				else if (i == 0)
				{
					list.Add(NetworkManager.Singleton.LocalClientId);
				}
				else
				{
					list.Add(999uL);
				}
			}
			ClientRpcParams val = default(ClientRpcParams);
			val.Send = new ClientRpcSendParams
			{
				TargetClientIds = list2
			};
			ClientRpcParams val2 = val;
			int groupCredits = Object.FindObjectOfType<Terminal>().groupCredits;
			int profitQuota = TimeOfDay.Instance.profitQuota;
			int quotaFulfilled = TimeOfDay.Instance.quotaFulfilled;
			int num = (int)TimeOfDay.Instance.timeUntilDeadline;
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			if (_onPlayerConnectedClientRpcID.HasValue)
			{
				uint value = _onPlayerConnectedClientRpcID.Value;
				FastBufferWriter val3 = ((NetworkBehaviour)instance).__beginSendClientRpc(value, val2, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val3, localPlayerController.actualClientId);
				BytePacker.WriteValueBitPacked(val3, instance.connectedPlayersAmount - 1);
				bool flag = true;
				((FastBufferWriter)(ref val3)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				((FastBufferWriter)(ref val3)).WriteValueSafe<ulong>(list.ToArray(), default(ForPrimitives));
				BytePacker.WriteValueBitPacked(val3, instance.ClientPlayerList[localPlayerController.actualClientId]);
				BytePacker.WriteValueBitPacked(val3, groupCredits);
				BytePacker.WriteValueBitPacked(val3, instance.currentLevelID);
				BytePacker.WriteValueBitPacked(val3, profitQuota);
				BytePacker.WriteValueBitPacked(val3, num);
				BytePacker.WriteValueBitPacked(val3, quotaFulfilled);
				BytePacker.WriteValueBitPacked(val3, instance.randomMapSeed);
				((FastBufferWriter)(ref val3)).WriteValueSafe<bool>(ref instance.isChallengeFile, default(ForPrimitives));
				((NetworkBehaviour)instance).__endSendClientRpc(ref val3, value, val2, (RpcDelivery)0);
			}
		}

		internal static void Init()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "ReturnUnlockableFromStorageClientRpc", (Type[])null, (Type[])null);
			if (RPCUtils.TryGetRpcID(methodInfo, out var rpcID))
			{
				_returnUnlockableFromStorageServerRpcID = rpcID;
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(StartOfRound), "OnPlayerConnectedClientRpc", (Type[])null, (Type[])null);
			if (RPCUtils.TryGetRpcID(methodInfo2, out var rpcID2))
			{
				_onPlayerConnectedClientRpcID = rpcID2;
			}
		}
	}
}
namespace LobbyControl.PopUp
{
	[HarmonyPatch]
	public class PopUpPatch
	{
		public static readonly List<(string objectName, string text)> PopUps = new List<(string, string)>();

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MenuManager), "Awake")]
		private static void AddPopups(MenuManager __instance)
		{
			foreach (var (objectName, text) in PopUps)
			{
				AppendPopup(objectName, text);
			}
		}

		private static void AppendPopup(string objectName, string text)
		{
			GameObject val = GameObject.Find("/Canvas/MenuContainer/");
			GameObject val2 = GameObject.Find("Canvas/MenuContainer/LANWarning/");
			if (!((Object)(object)val2 == (Object)null))
			{
				GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
				((Object)val3).name = objectName;
				val3.SetActive(true);
				Transform val4 = val3.transform.Find("Panel/NotificationText");
				TextMeshProUGUI component = ((Component)val4).GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).text = text;
			}
		}
	}
}
namespace LobbyControl.Patches
{
	[HarmonyPatch]
	internal class JoinQueuePatches
	{
		private static bool _allowNewConnection;

		private static bool _checkpointsInitialized;

		private static ConnectionCheckpoint _syncAlreadyHeldObjectsCheckpoint;

		private static ConnectionCheckpoint _sendNewPlayerValuesCheckpoint;

		private static ConnectionCheckpoint _syncAllPlayerLevelsCheckpoint;

		private static readonly ConcurrentQueue<(ConnectionApprovalRequest request, ConnectionApprovalResponse response, ulong? steamId)> ConnectionQueue = new ConcurrentQueue<(ConnectionApprovalRequest, ConnectionApprovalResponse, ulong?)>();

		private static readonly Timer ConnectionTimer = new Timer
		{
			AutoReset = false
		};

		private static readonly Stopwatch ConnectionStopwatch = new Stopwatch();

		private static bool _testValue = false;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameNetworkManager), "Awake")]
		private static void OnStartup(GameNetworkManager __instance)
		{
			if (!_checkpointsInitialized)
			{
				_checkpointsInitialized = true;
				_syncAlreadyHeldObjectsCheckpoint = ConnectionCheckpoint.RegisterCheckpoint((BaseUnityPlugin)(object)LobbyControl.Instance, "SyncAlreadyHeldObjects");
				_syncAllPlayerLevelsCheckpoint = ConnectionCheckpoint.RegisterCheckpoint((BaseUnityPlugin)(object)LobbyControl.Instance, "SyncAllPlayerLevels");
				if (!__instance.disableSteam)
				{
					_sendNewPlayerValuesCheckpoint = ConnectionCheckpoint.RegisterCheckpoint((BaseUnityPlugin)(object)LobbyControl.Instance, "SendNewPlayerValues");
				}
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		private static IEnumerable<CodeInstruction> FixConnectionApprovalPrefix(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			Label operand;
			ILInjector iLInjector = new ILInjector(list).Find(ILMatcher.Call(typeof(GameNetworkManager).GetProperty("Instance")?.GetMethod, "FixConnectionApprovalPrefix", "./Plugin/src/Patches/JoinQueuePatches.cs", 74), ILMatcher.Ldfld(typeof(GameNetworkManager).GetField("gameHasStarted", BindingFlags.Instance | BindingFlags.Public), "FixConnectionApprovalPrefix", "./Plugin/src/Patches/JoinQueuePatches.cs", 75), ILMatcher.Opcode(OpCodes.Brfalse).CaptureOperandAs<Label>(out operand));
			if (!iLInjector.IsValid)
			{
				LobbyControl.Log.LogWarning((object)"ConnectionApproval patch failed!!");
				LobbyControl.Log.LogDebug((object)string.Join("\n", iLInjector.ReleaseInstructions()));
				return list;
			}
			return iLInjector.RemoveLastMatch().FindLabel(operand).RemoveLastMatch()
				.ReleaseInstructions();
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		[HarmonyPriority(10)]
		private static Exception ThrottleApprovals(GameNetworkManager __instance, ConnectionApprovalRequest request, ConnectionApprovalResponse response, Exception __exception)
		{
			//IL_0060: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			if (__exception != null)
			{
				return __exception;
			}
			if (!response.Approved)
			{
				return null;
			}
			if (!_allowNewConnection)
			{
				LobbyControl.Log.LogDebug((object)"connection refused ( ship was landed ).");
				response.Reason = "Ship has already landed!";
				response.Approved = false;
				return null;
			}
			if (!__instance.disableSteam && (!__instance.currentLobby.HasValue || !LobbyPatcher.IsOpen(__instance.currentLobby.Value)))
			{
				LobbyControl.Log.LogDebug((object)"connection refused ( lobby was closed ).");
				response.Reason = "Lobby has been closed!";
				response.Approved = false;
				return null;
			}
			if (__instance.gameHasStarted)
			{
				LobbyControl.Log.LogDebug((object)"Incoming late connection.");
			}
			if (!LobbyControl.PluginConfig.JoinQueue.Enabled.Value)
			{
				re