Decompiled source of More Players v0.5.1

plugins/CrackMorePlayers.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CrackMods.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Steamworks;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CrackMorePlayers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CrackMorePlayers")]
[assembly: AssemblyTitle("CrackMorePlayers")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CrackMods.Shared
{
	internal static class ModHandshake
	{
		[HarmonyPatch(typeof(SteamLobby), "OnLobbyCreated")]
		private static class PublishPatch
		{
			private static void Postfix(SteamLobby __instance)
			{
				Publish(__instance);
			}
		}

		[HarmonyPatch(typeof(SteamLobby), "RefreshModdedLobbyData")]
		private static class RefreshPatch
		{
			private static void Postfix(SteamLobby __instance)
			{
				Publish(__instance);
			}
		}

		[HarmonyPatch(typeof(SteamLobby), "HostIsInLobby")]
		private static class JoinCheckPatch
		{
			private static bool Prefix(CSteamID lobby, ref bool __result)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!IsLeader(_ownGuid))
				{
					return true;
				}
				string lobbyData = SteamMatchmaking.GetLobbyData(lobby, "cmods");
				string text = LocalToken();
				if (lobbyData == text)
				{
					return true;
				}
				_pendingReason = Describe(lobbyData, text);
				Debug.LogWarning((object)("[CrackMods] refusing to join: " + _pendingReason));
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(SteamLobby), "FailConnect")]
		private static class FailMessagePatch
		{
			private static void Prefix(ref string messageKey)
			{
				if (_pendingReason != null && !(messageKey != "Error_JoinFailed"))
				{
					messageKey = _pendingReason;
					_pendingReason = null;
				}
			}
		}

		internal const string GuidPrefix = "com.altma.crack.";

		private const string LobbyKey = "cmods";

		private static string _ownGuid;

		private static string _pendingReason;

		internal static string LocalToken()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, PluginInfo> item in Chainloader.PluginInfos.OrderBy((KeyValuePair<string, PluginInfo> k) => k.Key))
			{
				if (item.Key.StartsWith("com.altma.crack."))
				{
					string text = item.Key.Substring("com.altma.crack.".Length) + "=" + item.Value.Metadata.Version;
					object instance = item.Value.Instance;
					PropertyInfo propertyInfo = ((instance != null) ? AccessTools.Property(instance.GetType(), "HandshakeExtra") : null);
					if (propertyInfo != null && propertyInfo.GetGetMethod() != null && propertyInfo.GetGetMethod().IsStatic)
					{
						text = text + "+" + propertyInfo.GetValue(null, null);
					}
					list.Add(text);
				}
			}
			return string.Join(";", list.ToArray());
		}

		private static bool IsLeader(string ownGuid)
		{
			string text = (from k in Chainloader.PluginInfos.Keys
				where k.StartsWith("com.altma.crack.")
				orderby k
				select k).FirstOrDefault();
			if (text != null)
			{
				return text == ownGuid;
			}
			return true;
		}

		internal static void Install(string ownGuid)
		{
			_ownGuid = ownGuid;
		}

		private static void Publish(SteamLobby lobby)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (IsLeader(_ownGuid) && !((Object)(object)lobby == (Object)null) && ((CSteamID)(ref lobby.currentLobbyID)).IsValid())
			{
				string text = LocalToken();
				SteamMatchmaking.SetLobbyData(lobby.currentLobbyID, "cmods", text);
				Debug.Log((object)("[CrackMods] lobby mods: " + text));
			}
		}

		internal static string Describe(string host, string local)
		{
			Dictionary<string, string> dictionary = Parse(host);
			Dictionary<string, string> dictionary2 = Parse(local);
			List<string> list = new List<string>();
			foreach (string item in from k in dictionary.Keys.Union(dictionary2.Keys)
				orderby k
				select k)
			{
				dictionary.TryGetValue(item, out var value);
				dictionary2.TryGetValue(item, out var value2);
				if (!(value == value2))
				{
					list.Add(item + ": host " + (value ?? "doesn't have it") + ", you " + (value2 ?? "don't have it"));
				}
			}
			return "CrackMods don't match the host. " + string.Join(". ", list.ToArray());
			static Dictionary<string, string> Parse(string s)
			{
				return (from p in (s ?? "").Split(new char[1] { ';' })
					where p.Contains("=")
					select p).ToDictionary((string p) => p.Substring(0, p.IndexOf('=')), (string p) => p.Substring(p.IndexOf('=') + 1));
			}
		}
	}
}
namespace CrackMorePlayers
{
	internal class AnnexLighting : MonoBehaviour
	{
		private const uint UsedByLevel = 5u;

		private const float PlayerCheckInterval = 0.25f;

		private float _nextCheck;

		internal static uint Layer { get; private set; } = 2u;

		private static uint PickLayer()
		{
			int lastDefinedRenderingLayerIndex = RenderingLayerMask.GetLastDefinedRenderingLayerIndex();
			for (int i = 1; i <= Mathf.Max(lastDefinedRenderingLayerIndex, 1); i++)
			{
				if ((5 & (1 << i)) == 0)
				{
					return (uint)(1 << i);
				}
			}
			return 2u;
		}

		internal static string Describe()
		{
			return string.Format("annex light layer 0x{0:X} (defined layers: {1}; ", Layer, string.Join(", ", RenderingLayerMask.GetDefinedRenderingLayerNames())) + $"last index {RenderingLayerMask.GetLastDefinedRenderingLayerIndex()})";
		}

		internal static void Setup(GameObject annex)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			Layer = PickLayer();
			Light[] componentsInChildren = annex.GetComponentsInChildren<Light>(true);
			UniversalAdditionalLightData val3 = default(UniversalAdditionalLightData);
			foreach (Light val in componentsInChildren)
			{
				GameObject val2 = new GameObject("CMP_RealtimeTwin");
				val2.transform.SetParent(((Component)val).transform, false);
				Light obj = val2.AddComponent<Light>();
				obj.type = val.type;
				obj.color = val.color;
				obj.intensity = val.intensity;
				obj.range = val.range;
				obj.spotAngle = val.spotAngle;
				obj.innerSpotAngle = val.innerSpotAngle;
				obj.shadows = (LightShadows)0;
				if (!val2.TryGetComponent<UniversalAdditionalLightData>(ref val3))
				{
					val3 = val2.AddComponent<UniversalAdditionalLightData>();
				}
				val3.renderingLayers = RenderingLayerMask.op_Implicit(Layer);
				obj.renderingLayerMask = (int)Layer;
			}
			Renderer[] componentsInChildren2 = annex.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren2)
			{
				if (val4.lightmapIndex < 0 || val4.lightmapIndex >= 65534)
				{
					val4.renderingLayerMask |= Layer;
				}
			}
			annex.AddComponent<AnnexLighting>();
		}

		private void Update()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime < _nextCheck || (Object)(object)GameManager.instance == (Object)null)
			{
				return;
			}
			_nextCheck = Time.unscaledTime + 0.25f;
			foreach (Player allPlayerCharacter in GameManager.instance.GetAllPlayerCharacters())
			{
				if (!((Object)(object)allPlayerCharacter == (Object)null))
				{
					bool flag = QuartersAnnex.Contains(allPlayerCharacter.WorldPosition);
					Renderer[] componentsInChildren = ((Component)allPlayerCharacter).GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val in componentsInChildren)
					{
						val.renderingLayerMask = (flag ? (val.renderingLayerMask | Layer) : (val.renderingLayerMask & ~Layer));
					}
				}
			}
		}
	}
	[BepInPlugin("com.altma.crack.moreplayers", "CRACK More Players", "0.5.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.altma.crack.moreplayers";

		public const string Name = "CRACK More Players";

		public const string Version = "0.5.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> MaxPlayers;

		internal static ConfigEntry<bool> AnnexEnabled;

		public static string HandshakeExtra
		{
			get
			{
				if (AnnexEnabled == null || !AnnexEnabled.Value)
				{
					return "noannex";
				}
				return "annex";
			}
		}

		internal static int RoomCount
		{
			get
			{
				int i;
				for (i = 0; (Object)(object)QuartersRoom.Get(i) != (Object)null; i++)
				{
				}
				return i;
			}
		}

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			MaxPlayers = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPlayers", 8, new ConfigDescription("Maximum crew size. Every player in the lobby must run the mod. Players 5-8 get rooms in the upper quarters; beyond that, players share rooms (player 9 with player 1, 10 with 2, ...).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 32), Array.Empty<object>()));
			AnnexEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Quarters", "AnnexEnabled", true, "Build the upper quarters (4 extra rooms for players 5-8, reached by a ladder through a ceiling hatch). Must be the same for every player in the lobby (joining is refused otherwise).");
			ModHandshake.Install("com.altma.crack.moreplayers");
			new Harmony("com.altma.crack.moreplayers").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)string.Format("{0} {1} loaded, MaxPlayers = {2}", "CRACK More Players", "0.5.1", MaxPlayers.Value));
		}

		[Conditional("DEV")]
		internal static void LogDev(string message)
		{
			Log.LogInfo((object)message);
		}

		internal static int RoomOf(int playerIndex)
		{
			if (playerIndex < 0 || (Object)(object)QuartersRoom.Get(playerIndex) != (Object)null)
			{
				return playerIndex;
			}
			int roomCount = RoomCount;
			if (roomCount <= 0)
			{
				return playerIndex;
			}
			return playerIndex % roomCount;
		}
	}
	[HarmonyPatch(typeof(MyNetworkManager), "Awake")]
	internal static class MaxConnectionsPatch
	{
		private static void Postfix(MyNetworkManager __instance)
		{
			((NetworkManager)__instance).maxConnections = Plugin.MaxPlayers.Value;
		}
	}
	[HarmonyPatch(typeof(GameManager), "GetAvailablePlayerIndex")]
	internal static class AvailablePlayerIndexPatch
	{
		private static bool Prefix(GameManager __instance, ref int __result)
		{
			int value = Plugin.MaxPlayers.Value;
			int i;
			for (i = 0; i < value; i++)
			{
				if (!__instance.players.Any((PlayerController p) => p.index == i))
				{
					__result = i;
					return false;
				}
			}
			__result = -1;
			return false;
		}
	}
	[HarmonyPatch(typeof(GameManager), "GetSpawnPoint")]
	internal static class SpawnPointPatch
	{
		private static bool Prefix(int playerIndex, ref (Vector3 position, Quaternion rotation) __result)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (playerIndex < 0 || (Object)(object)QuartersRoom.Get(playerIndex) != (Object)null)
			{
				return true;
			}
			int roomCount = Plugin.RoomCount;
			if (roomCount == 0)
			{
				return true;
			}
			QuartersRoom val = QuartersRoom.Get(playerIndex % roomCount);
			if ((Object)(object)val == (Object)null || (Object)(object)val.SpawnPoint == (Object)null)
			{
				return true;
			}
			Transform spawnPoint = val.SpawnPoint;
			int num = playerIndex / roomCount;
			__result = (position: spawnPoint.position + spawnPoint.right * (0.75f * (float)num), rotation: spawnPoint.rotation);
			return false;
		}
	}
	[HarmonyPatch(typeof(QuartersDoor), "ReaderHoldsAssignedPlayer")]
	internal static class DoorAuthorizedPatch
	{
		private static bool Prefix(BadgeReader reader, int ____assignedPlayerIndex, ref bool __result)
		{
			__result = BadgeRoom(reader, out var room) && room == ____assignedPlayerIndex;
			return false;
		}

		internal static bool BadgeRoom(BadgeReader reader, out int room)
		{
			room = -1;
			if ((Object)(object)reader == (Object)null || !reader.HasBadgeAuthoritative)
			{
				return false;
			}
			Player signedInPlayer = reader.SignedInPlayer;
			if ((Object)(object)signedInPlayer == (Object)null || (Object)(object)signedInPlayer.playerController == (Object)null)
			{
				return false;
			}
			room = Plugin.RoomOf(signedInPlayer.playerController.index);
			return true;
		}
	}
	[HarmonyPatch(typeof(QuartersDoor), "HasUnauthorizedBadge")]
	internal static class DoorUnauthorizedPatch
	{
		private static bool Prefix(BadgeReader reader, int ____assignedPlayerIndex, ref bool __result)
		{
			__result = DoorAuthorizedPatch.BadgeRoom(reader, out var room) && room != ____assignedPlayerIndex;
			return false;
		}
	}
	[HarmonyPatch(typeof(Bed), "CanInteract")]
	internal static class BedRoommatePatch
	{
		private static void Postfix(Bed __instance, PlayerItemHolder holder, int ____playerIndex, ref bool __result)
		{
			if (__result || ____playerIndex < 0 || (Object)(object)holder == (Object)null)
			{
				return;
			}
			Player player = holder.Player;
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player.playerController == (Object)null))
			{
				int index = player.playerController.index;
				if (index != ____playerIndex && Plugin.RoomOf(index) == ____playerIndex && !((Object)(object)BreakManager.instance == (Object)null) && BreakManager.instance.IsSleepPhase && !player.IsSleepingInBed)
				{
					__result = true;
				}
			}
		}
	}
	internal static class QuartersAnnex
	{
		private sealed class MeshData
		{
			private struct Vert
			{
				public Vector3 P;

				public Vector3 N;

				public Vector4 T;

				public Vector2 Uv0;

				public Vector2 Uv1;

				public static Vert Lerp(Vert a, Vert b, float f)
				{
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_0017: Unknown result type (might be due to invalid IL or missing references)
					//IL_001c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0024: Unknown result type (might be due to invalid IL or missing references)
					//IL_002a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					//IL_0035: Unknown result type (might be due to invalid IL or missing references)
					//IL_003d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0043: Unknown result type (might be due to invalid IL or missing references)
					//IL_0049: Unknown result type (might be due to invalid IL or missing references)
					//IL_004e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0056: Unknown result type (might be due to invalid IL or missing references)
					//IL_005c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0062: Unknown result type (might be due to invalid IL or missing references)
					//IL_0067: Unknown result type (might be due to invalid IL or missing references)
					//IL_006f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0075: Unknown result type (might be due to invalid IL or missing references)
					//IL_007b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0080: Unknown result type (might be due to invalid IL or missing references)
					return new Vert
					{
						P = Vector3.Lerp(a.P, b.P, f),
						N = Vector3.Lerp(a.N, b.N, f),
						T = Vector4.Lerp(a.T, b.T, f),
						Uv0 = Vector2.Lerp(a.Uv0, b.Uv0, f),
						Uv1 = Vector2.Lerp(a.Uv1, b.Uv1, f)
					};
				}
			}

			private Vert[] _verts;

			private int[][] _tris;

			internal Vector3 Centroid
			{
				get
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0020: Unknown result type (might be due to invalid IL or missing references)
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					//IL_003b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0045: Unknown result type (might be due to invalid IL or missing references)
					//IL_0039: Unknown result type (might be due to invalid IL or missing references)
					Vector3 val = Vector3.zero;
					Vert[] verts = _verts;
					for (int i = 0; i < verts.Length; i++)
					{
						Vert vert = verts[i];
						val += vert.P;
					}
					if (_verts.Length == 0)
					{
						return val;
					}
					return val / (float)_verts.Length;
				}
			}

			internal Vector2 NearestUv0(Vector3 world)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				float num2 = float.MaxValue;
				for (int i = 0; i < _verts.Length; i++)
				{
					Vector3 val = _verts[i].P - world;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						num2 = sqrMagnitude;
						num = i;
					}
				}
				if (_verts.Length == 0)
				{
					return Vector2.zero;
				}
				return _verts[num].Uv0;
			}

			internal static MeshData Read(BinaryReader r)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				int num = r.ReadInt32();
				int num2 = r.ReadInt32();
				Vert[] array = new Vert[num];
				for (int i = 0; i < num; i++)
				{
					array[i].P = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
				}
				for (int j = 0; j < num; j++)
				{
					array[j].N = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
				}
				for (int k = 0; k < num; k++)
				{
					array[k].T = new Vector4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
				}
				for (int l = 0; l < num; l++)
				{
					array[l].Uv0 = new Vector2(r.ReadSingle(), r.ReadSingle());
				}
				for (int m = 0; m < num; m++)
				{
					array[m].Uv1 = new Vector2(r.ReadSingle(), r.ReadSingle());
				}
				int[][] array2 = new int[num2][];
				for (int n = 0; n < num2; n++)
				{
					array2[n] = new int[r.ReadInt32()];
					for (int num3 = 0; num3 < array2[n].Length; num3++)
					{
						array2[n][num3] = r.ReadInt32();
					}
				}
				return new MeshData
				{
					_verts = array,
					_tris = array2
				};
			}

			internal Mesh ToLocalMesh(Transform orig, string name, Rect? hole)
			{
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: 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_011d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				//IL_012d: 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_013c: 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_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_015c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0170: Unknown result type (might be due to invalid IL or missing references)
				//IL_0175: Unknown result type (might be due to invalid IL or missing references)
				//IL_0188: Expected O, but got Unknown
				List<Vert> list = new List<Vert>(_verts);
				int[][] array = new int[_tris.Length][];
				for (int i = 0; i < _tris.Length; i++)
				{
					array[i] = (hole.HasValue ? CutHole(_tris[i], hole.Value, list) : _tris[i]);
				}
				Matrix4x4 worldToLocalMatrix = orig.worldToLocalMatrix;
				Matrix4x4 localToWorldMatrix = orig.localToWorldMatrix;
				Matrix4x4 transpose = ((Matrix4x4)(ref localToWorldMatrix)).transpose;
				int count = list.Count;
				Vector3[] array2 = (Vector3[])(object)new Vector3[count];
				Vector3[] array3 = (Vector3[])(object)new Vector3[count];
				Vector4[] array4 = (Vector4[])(object)new Vector4[count];
				Vector2[] array5 = (Vector2[])(object)new Vector2[count];
				Vector2[] array6 = (Vector2[])(object)new Vector2[count];
				for (int j = 0; j < count; j++)
				{
					Vert vert = list[j];
					array2[j] = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(vert.P);
					int num = j;
					Vector3 val = ((Matrix4x4)(ref transpose)).MultiplyVector(vert.N);
					array3[num] = ((Vector3)(ref val)).normalized;
					val = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyVector(Vector4.op_Implicit(vert.T));
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					array4[j] = new Vector4(normalized.x, normalized.y, normalized.z, vert.T.w);
					array5[j] = vert.Uv0;
					array6[j] = vert.Uv1;
				}
				Mesh val2 = new Mesh
				{
					name = name + " (annex)"
				};
				if (count > 65535)
				{
					val2.indexFormat = (IndexFormat)1;
				}
				val2.vertices = array2;
				val2.normals = array3;
				val2.tangents = array4;
				val2.uv = array5;
				val2.uv2 = array6;
				val2.subMeshCount = array.Length;
				for (int k = 0; k < array.Length; k++)
				{
					val2.SetTriangles(array[k], k, false);
				}
				val2.RecalculateBounds();
				return val2;
			}

			private static int[] CutHole(int[] tris, Rect hole, List<Vert> verts)
			{
				List<int> list = new List<int>(tris.Length);
				for (int i = 0; i < tris.Length; i += 3)
				{
					Peel(Peel(Peel(Peel(new List<Vert>
					{
						verts[tris[i]],
						verts[tris[i + 1]],
						verts[tris[i + 2]]
					}, 0, ((Rect)(ref hole)).xMin, -1f, verts, list), 0, ((Rect)(ref hole)).xMax, 1f, verts, list), 2, ((Rect)(ref hole)).yMin, -1f, verts, list), 2, ((Rect)(ref hole)).yMax, 1f, verts, list);
				}
				return list.ToArray();
			}

			private static List<Vert> Peel(List<Vert> poly, int axis, float c, float sign, List<Vert> verts, List<int> result)
			{
				if (poly.Count < 3)
				{
					return poly;
				}
				Emit(Clip(poly, axis, c, sign), verts, result);
				return Clip(poly, axis, c, 0f - sign);
			}

			private static List<Vert> Clip(List<Vert> poly, int axis, float c, float sign)
			{
				List<Vert> list = new List<Vert>(poly.Count + 2);
				for (int i = 0; i < poly.Count; i++)
				{
					Vert vert = poly[i];
					Vert b = poly[(i + 1) % poly.Count];
					float num = sign * (((Vector3)(ref vert.P))[axis] - c);
					float num2 = sign * (((Vector3)(ref b.P))[axis] - c);
					if (num >= 0f)
					{
						list.Add(vert);
					}
					if (num >= 0f != num2 >= 0f)
					{
						list.Add(Vert.Lerp(vert, b, num / (num - num2)));
					}
				}
				return list;
			}

			private static void Emit(List<Vert> poly, List<Vert> verts, List<int> result)
			{
				if (poly.Count >= 3)
				{
					int count = verts.Count;
					verts.AddRange(poly);
					for (int i = 1; i + 1 < poly.Count; i++)
					{
						result.Add(count);
						result.Add(count + i);
						result.Add(count + i + 1);
					}
				}
			}
		}

		internal static readonly Vector3 Offset = new Vector3(-7f, 8.9f, 0f);

		private static readonly Vector3 OrigCenter = new Vector3(-32.62f, 0f, 0f);

		private const float LobbyRadius = 9.6f;

		private static readonly Vector3 HatchCenter = new Vector3(-35.8f, 0f, 0f);

		private const string GatePath = "Walls/PF_Lab_WallSection/SM_LabWall_GarageOpening (1)";

		private static readonly string[] DropGateChildren = new string[2] { "Sound", "Obstacle" };

		private const float HatchSizeX = 1.3f;

		private const float HatchSizeZ = 1.2f;

		private const float CeilingY = 7.55f;

		private const float LadderPieceHeight = 3f;

		private const string LadderPath = "FBX_Scaffolding_01/SM_Scaffolding_Ladder_01";

		private static readonly string[] DropLadderChildren = new string[5] { "Blocker", "Bolt", "Cube", "PF_ImpactParticles", "Placement Ref" };

		private static readonly string[] DropLobbyPrefixes = new string[5] { "Button", "Message", "Waypoint", "PF_SecurityCamera", "PF_Item_" };

		private static readonly string[] DropRoomPrefixes = new string[2] { "PF_Item_", "PF_Whiteboard" };

		private static readonly FieldRef<QuartersRoom, int> RoomIndex = AccessTools.FieldRefAccess<QuartersRoom, int>("_playerIndex");

		private static readonly FieldRef<NetworkIdentity, bool> HasSpawned = AccessTools.FieldRefAccess<NetworkIdentity, bool>("hasSpawned");

		private static GameObject _annex;

		private static Dictionary<string, MeshData> _meshData;

		private static readonly Dictionary<string, Mesh> MeshCache = new Dictionary<string, Mesh>();

		private static Mesh _liningMesh;

		internal static bool Built => (Object)(object)_annex != (Object)null;

		internal static Vector3 AnnexCenter => OrigCenter + Offset;

		internal static bool Contains(Vector3 pos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!Built)
			{
				return false;
			}
			Vector3 annexCenter = AnnexCenter;
			if (pos.y > annexCenter.y - 0.6f && pos.y < annexCenter.y + 8f)
			{
				Vector2 val = new Vector2(pos.x - annexCenter.x, pos.z - annexCenter.z);
				return ((Vector2)(ref val)).sqrMagnitude < 256f;
			}
			return false;
		}

		internal static bool LobbyContains(Vector3 pos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!Built)
			{
				return false;
			}
			Vector3 annexCenter = AnnexCenter;
			if (pos.y > annexCenter.y - 1f && pos.y < annexCenter.y + 8f)
			{
				Vector2 val = new Vector2(pos.x - annexCenter.x, pos.z - annexCenter.z);
				return ((Vector2)(ref val)).sqrMagnitude < 92.16f;
			}
			return false;
		}

		internal static void EnsureBuilt()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.AnnexEnabled.Value || (Object)(object)_annex != (Object)null)
			{
				return;
			}
			QuartersRoom val = QuartersRoom.Get(0);
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform.parent == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)val).transform.parent;
			GameObject val2 = new GameObject("CMP_AnnexHolder");
			val2.SetActive(false);
			SceneManager.MoveGameObjectToScene(val2, ((Component)parent).gameObject.scene);
			try
			{
				_annex = Build(parent, val2.transform);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[Annex] build failed, players 5+ will share rooms instead. Every player must see the same result or they will desync.\n" + ex));
				if ((Object)(object)_annex != (Object)null)
				{
					Object.Destroy((Object)(object)_annex);
				}
				_annex = null;
			}
			finally
			{
				Object.Destroy((Object)(object)val2);
			}
		}

		private static GameObject Build(Transform root, Transform holder)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			int roomCount = Plugin.RoomCount;
			LoadMeshData();
			Transform ladderSource = FindLadderSource(((Component)root).gameObject.scene);
			Transform val = FindGate(((Component)root).gameObject.scene);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)root).gameObject, holder);
			((Object)val2).name = ((Object)root).name + " (Annex)";
			List<(MeshRenderer, MeshRenderer, string)> list = new List<(MeshRenderer, MeshRenderer, string)>();
			List<(NetworkIdentity, NetworkIdentity)> identities = new List<(NetworkIdentity, NetworkIdentity)>();
			Pair(root, val2.transform, root, "", list, identities);
			val2.transform.position = root.position + Offset;
			foreach (Transform item in Children(val2.transform))
			{
				if (((Object)item).name.StartsWith("PF_QuartersRoom"))
				{
					foreach (Transform item2 in Children(item))
					{
						if (StartsWithAny(((Object)item2).name, DropRoomPrefixes))
						{
							Object.DestroyImmediate((Object)(object)((Component)item2).gameObject);
						}
					}
				}
				else if (StartsWithAny(((Object)item).name, DropLobbyPrefixes))
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
				else if (!((Object)item).name.StartsWith("SM_Computer_Monitor") && (Object)(object)((Component)item).GetComponentInChildren<NetworkIdentity>(true) != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
			QuartersRoom[] componentsInChildren = val2.GetComponentsInChildren<QuartersRoom>(true);
			foreach (QuartersRoom val3 in componentsInChildren)
			{
				RoomIndex.Invoke(val3) += roomCount;
			}
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject, val2.transform);
			((Object)val4).name = "CMP_AnnexGate";
			Pair(val, val4.transform, val, "G:", list, null);
			StripGate(val4.transform);
			val4.transform.SetPositionAndRotation(val.position + Offset, val.rotation);
			val4.transform.localScale = val.lossyScale;
			Rect hatch = HatchRect(HatchCenter);
			Transform val5 = val2.transform.Find("SM_QuartersLobby_Floor");
			if ((Object)(object)val5 == (Object)null)
			{
				throw new InvalidOperationException("missing lobby floor");
			}
			int num = 0;
			foreach (var (orig, val6, key) in list)
			{
				if (!((Object)(object)val6 == (Object)null))
				{
					bool flag = (Object)(object)((Component)val6).transform == (Object)(object)val5;
					RebuildVisual(orig, val6, key, flag ? new Rect?(HatchRect(HatchCenter - Offset)) : ((Rect?)null));
					num++;
				}
			}
			CutBoxCollider(((Component)val5).GetComponent<BoxCollider>(), HatchCenter, 1.3f, 1.2f);
			AnnexLighting.Setup(val2);
			AssignSceneIds(identities);
			GameObject obj = BuildHatch(root, ladderSource, holder, hatch);
			val2.transform.SetParent((Transform)null, true);
			obj.transform.SetParent((Transform)null, true);
			return val2;
		}

		private static Rect HatchRect(Vector3 center)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(center.x - 0.65f, center.z - 0.6f, 1.3f, 1.2f);
		}

		private static Transform FindGate(Scene scene)
		{
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if (!(((Object)val).name != "Lab"))
				{
					Transform val2 = val.transform.Find("Walls/PF_Lab_WallSection/SM_LabWall_GarageOpening (1)");
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			throw new InvalidOperationException("quarters gate not found");
		}

		private static void StripGate(Transform gate)
		{
			foreach (Transform item in Children(gate))
			{
				if (StartsWithAny(((Object)item).name, DropGateChildren))
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
			NetworkBehaviour[] componentsInChildren = ((Component)gate).GetComponentsInChildren<NetworkBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			NetworkIdentity[] componentsInChildren2 = ((Component)gate).GetComponentsInChildren<NetworkIdentity>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			((Component)gate).gameObject.SetActive(true);
		}

		private static Transform FindLadderSource(Scene scene)
		{
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if (((Object)val).name.StartsWith("PF_PushScaffold"))
				{
					Transform val2 = val.transform.Find("FBX_Scaffolding_01/SM_Scaffolding_Ladder_01");
					if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).GetComponentInChildren<Ladder>(true) != (Object)null)
					{
						return val2;
					}
				}
			}
			throw new InvalidOperationException("no scaffold ladder found to copy");
		}

		private static GameObject BuildHatch(Transform root, Transform ladderSource, Transform holder, Rect hatch)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: 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)
			GameObject val = new GameObject("CMP_QuartersHatch");
			val.transform.SetParent(holder, false);
			Transform val2 = root.Find("Ceiling");
			if ((Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("missing lobby ceiling");
			}
			MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
			RebuildVisual(component, component, KeyOf(val2, root), hatch);
			CutBoxCollider(((Component)val2).GetComponent<BoxCollider>(), HatchCenter, 1.3f, 1.2f);
			float num = 7.4500003f;
			float num2 = Offset.y + 0.05f - num;
			float num3 = 0.05f;
			Material sharedMaterial = ((Renderer)component).sharedMaterial;
			Vector2 uv = _meshData[KeyOf(val2, root)].NearestUv0(HatchCenter + Vector3.up * 7.55f);
			Vector3 hatchCenter = HatchCenter;
			AddLining(val.transform, sharedMaterial, uv, new Vector3(((Rect)(ref hatch)).xMin - num3 / 2f, num + num2 / 2f, hatchCenter.z), new Vector3(num3, num2, 1.2f + 2f * num3));
			AddLining(val.transform, sharedMaterial, uv, new Vector3(((Rect)(ref hatch)).xMax + num3 / 2f, num + num2 / 2f, hatchCenter.z), new Vector3(num3, num2, 1.2f + 2f * num3));
			AddLining(val.transform, sharedMaterial, uv, new Vector3(hatchCenter.x, num + num2 / 2f, ((Rect)(ref hatch)).yMin - num3 / 2f), new Vector3(1.3f, num2, num3));
			AddLining(val.transform, sharedMaterial, uv, new Vector3(hatchCenter.x, num + num2 / 2f, ((Rect)(ref hatch)).yMax + num3 / 2f), new Vector3(1.3f, num2, num3));
			Quaternion val3 = Quaternion.LookRotation(Vector3.right);
			float num4 = ((Rect)(ref hatch)).xMin - 0.05f;
			float num5 = Offset.y;
			while (num5 - 3f + 0.21f > -0.5f)
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)ladderSource).gameObject, val.transform);
				((Object)obj).name = "CMP_HatchLadder";
				StripBuildSystem(obj.transform);
				obj.transform.SetPositionAndRotation(new Vector3(num4, num5, hatchCenter.z), val3);
				obj.transform.localScale = Vector3.one;
				obj.SetActive(true);
				Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = true;
				}
				num5 -= 3f;
			}
			return val;
		}

		private static void StripBuildSystem(Transform piece)
		{
			foreach (Transform item in Children(piece))
			{
				if (StartsWithAny(((Object)item).name, DropLadderChildren))
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
			MonoBehaviour[] componentsInChildren = ((Component)piece).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!(val is Ladder))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			Collider[] componentsInChildren2 = ((Component)piece).GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if (val2.isTrigger && (Object)(object)((Component)val2).GetComponent<Ladder>() == (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
		}

		private static void AddLining(Transform parent, Material material, Vector2 uv, Vector3 center, Vector3 size)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "CMP_HatchLining";
			val.transform.SetParent(parent, false);
			val.transform.SetPositionAndRotation(center, Quaternion.identity);
			val.transform.localScale = size;
			MeshFilter component = val.GetComponent<MeshFilter>();
			if ((Object)(object)_liningMesh == (Object)null)
			{
				_liningMesh = Object.Instantiate<Mesh>(component.sharedMesh);
				((Object)_liningMesh).name = "CMP_HatchLining";
				Vector2[] array = (Vector2[])(object)new Vector2[_liningMesh.vertexCount];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = uv;
				}
				_liningMesh.uv = array;
			}
			component.sharedMesh = _liningMesh;
			if ((Object)(object)material != (Object)null)
			{
				((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial = material;
			}
		}

		private static void CutBoxCollider(BoxCollider box, Vector3 holeWorld, float sizeX, float sizeZ)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)box == (Object)null)
			{
				throw new InvalidOperationException("hatch surface has no box collider");
			}
			Transform transform = ((Component)box).transform;
			Vector3 val = transform.InverseTransformPoint(holeWorld);
			Vector3 val2 = transform.InverseTransformVector(new Vector3(sizeX / 2f, 0f, 0f));
			Vector3 val3 = transform.InverseTransformVector(new Vector3(0f, 0f, sizeZ / 2f));
			float num = Mathf.Abs(val2.x) + Mathf.Abs(val3.x);
			float num2 = Mathf.Abs(val2.z) + Mathf.Abs(val3.z);
			Vector3 center = box.center;
			Vector3 size = box.size;
			float x = center.x - size.x / 2f;
			float x2 = center.x + size.x / 2f;
			float z = center.z - size.z / 2f;
			float z2 = center.z + size.z / 2f;
			float num3 = val.x - num;
			float num4 = val.x + num;
			float z3 = val.z - num2;
			float z4 = val.z + num2;
			AddBox(box, x, num3, z, z2);
			AddBox(box, num4, x2, z, z2);
			AddBox(box, num3, num4, z, z3);
			AddBox(box, num3, num4, z4, z2);
			((Collider)box).enabled = false;
		}

		private static void AddBox(BoxCollider like, float x0, float x1, float z0, float z1)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!(x1 - x0 < 0.01f) && !(z1 - z0 < 0.01f))
			{
				BoxCollider obj = ((Component)like).gameObject.AddComponent<BoxCollider>();
				obj.center = new Vector3((x0 + x1) / 2f, like.center.y, (z0 + z1) / 2f);
				obj.size = new Vector3(x1 - x0, like.size.y, z1 - z0);
				((Collider)obj).isTrigger = ((Collider)like).isTrigger;
				((Collider)obj).sharedMaterial = ((Collider)like).sharedMaterial;
			}
		}

		private static void Pair(Transform o, Transform c, Transform root, string keyPrefix, List<(MeshRenderer, MeshRenderer, string)> visuals, List<(NetworkIdentity, NetworkIdentity)> identities)
		{
			MeshRenderer component = ((Component)o).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && ((Renderer)component).isPartOfStaticBatch)
			{
				visuals.Add((component, ((Component)c).GetComponent<MeshRenderer>(), keyPrefix + KeyOf(o, root)));
			}
			NetworkIdentity component2 = ((Component)o).GetComponent<NetworkIdentity>();
			if ((Object)(object)component2 != (Object)null)
			{
				identities?.Add((component2, ((Component)c).GetComponent<NetworkIdentity>()));
			}
			for (int i = 0; i < o.childCount; i++)
			{
				Pair(o.GetChild(i), c.GetChild(i), root, keyPrefix, visuals, identities);
			}
		}

		private static void RebuildVisual(MeshRenderer orig, MeshRenderer target, string key, Rect? hole)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_013f: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			string key2 = (hole.HasValue ? (key + "#" + ((object)hole.Value/*cast due to .constrained prefix*/).ToString()) : key);
			if (!MeshCache.TryGetValue(key2, out var value))
			{
				if (!_meshData.TryGetValue(key, out var value2))
				{
					Plugin.Log.LogWarning((object)("[Annex] no extracted mesh for '" + ((Object)orig).name + "' (" + key + "), hiding it"));
					((Renderer)target).enabled = false;
					return;
				}
				Bounds bounds = ((Renderer)orig).bounds;
				((Bounds)(ref bounds)).Expand(0.5f);
				if (!((Bounds)(ref bounds)).Contains(value2.Centroid))
				{
					Plugin.Log.LogWarning((object)("[Annex] extracted mesh for '" + ((Object)orig).name + "' (" + key + ") doesn't match its renderer, hiding it"));
					((Renderer)target).enabled = false;
					return;
				}
				Mesh val = (MeshCache[key2] = value2.ToLocalMesh(((Component)orig).transform, ((Object)orig).name, hole));
				value = val;
			}
			GameObject val3 = new GameObject(((Object)orig).name + " (visual)")
			{
				layer = ((Component)target).gameObject.layer
			};
			val3.transform.SetParent(((Component)target).transform, false);
			val3.AddComponent<MeshFilter>().sharedMesh = value;
			MeshRenderer obj = val3.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterials = ((Renderer)orig).sharedMaterials;
			((Renderer)obj).shadowCastingMode = ((Renderer)orig).shadowCastingMode;
			((Renderer)obj).receiveShadows = ((Renderer)orig).receiveShadows;
			((Renderer)obj).lightProbeUsage = ((Renderer)orig).lightProbeUsage;
			((Renderer)obj).reflectionProbeUsage = ((Renderer)orig).reflectionProbeUsage;
			((Renderer)obj).renderingLayerMask = ((Renderer)orig).renderingLayerMask;
			((Renderer)obj).lightmapIndex = ((Renderer)orig).lightmapIndex;
			((Renderer)obj).lightmapScaleOffset = new Vector4(1f, 1f, 0f, 0f);
			((Renderer)obj).enabled = ((Renderer)orig).enabled;
			((Renderer)target).enabled = false;
		}

		private static void AssignSceneIds(List<(NetworkIdentity orig, NetworkIdentity copy)> identities)
		{
			HashSet<ulong> hashSet = new HashSet<ulong>();
			NetworkIdentity[] array = Resources.FindObjectsOfTypeAll<NetworkIdentity>();
			foreach (NetworkIdentity val in array)
			{
				if (val.sceneId != 0L)
				{
					hashSet.Add(val.sceneId);
				}
			}
			foreach (var (val2, val3) in identities)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					ulong num = val2.sceneId & 0xFFFFFFFF00000000uL;
					uint a = (uint)val2.sceneId;
					uint num2 = 0u;
					ulong num3;
					do
					{
						num3 = num | Fnv(a, 2720923648u + num2++);
					}
					while (hashSet.Contains(num3));
					hashSet.Add(num3);
					val3.sceneId = num3;
					HasSpawned.Invoke(val3) = false;
				}
			}
		}

		private static uint Fnv(uint a, uint b)
		{
			uint num = 2166136261u;
			for (int i = 0; i < 4; i++)
			{
				num ^= (a >> 8 * i) & 0xFF;
				num *= 16777619;
			}
			for (int j = 0; j < 4; j++)
			{
				num ^= (b >> 8 * j) & 0xFF;
				num *= 16777619;
			}
			if (num != 0)
			{
				return num;
			}
			return 1u;
		}

		private static List<Transform> Children(Transform t)
		{
			List<Transform> list = new List<Transform>(t.childCount);
			for (int i = 0; i < t.childCount; i++)
			{
				list.Add(t.GetChild(i));
			}
			return list;
		}

		private static bool StartsWithAny(string s, string[] prefixes)
		{
			foreach (string value in prefixes)
			{
				if (s.StartsWith(value, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static string KeyOf(Transform t, Transform root)
		{
			List<string> list = new List<string>();
			while ((Object)(object)t != (Object)(object)root)
			{
				list.Add(t.GetSiblingIndex().ToString());
				t = t.parent;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private static void LoadMeshData()
		{
			if (_meshData != null)
			{
				return;
			}
			string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "quarters_meshes.bin");
			Dictionary<string, MeshData> dictionary = new Dictionary<string, MeshData>();
			using (FileStream stream = File.OpenRead(text))
			{
				using GZipStream input = new GZipStream(stream, CompressionMode.Decompress);
				using BinaryReader binaryReader = new BinaryReader(input);
				if (new string(binaryReader.ReadChars(4)) != "CMPQ")
				{
					throw new InvalidDataException(text + ": bad header");
				}
				if (binaryReader.ReadInt32() != 1)
				{
					throw new InvalidDataException(text + ": unsupported version");
				}
				int num = binaryReader.ReadInt32();
				for (int i = 0; i < num; i++)
				{
					string key = new string(binaryReader.ReadChars(binaryReader.ReadInt32()));
					dictionary[key] = MeshData.Read(binaryReader);
				}
			}
			_meshData = dictionary;
		}
	}
	[HarmonyPatch(typeof(NetworkServer), "SpawnObjects")]
	internal static class AnnexServerPatch
	{
		private static void Prefix()
		{
			QuartersAnnex.EnsureBuilt();
		}
	}
	[HarmonyPatch(typeof(NetworkClient), "PrepareToSpawnSceneObjects")]
	internal static class AnnexClientPatch
	{
		private static void Prefix()
		{
			QuartersAnnex.EnsureBuilt();
		}
	}
	[HarmonyPatch(typeof(QuartersRoom), "IsInAnyQuarters")]
	internal static class AnnexInQuartersPatch
	{
		private static void Postfix(Vector3 pos, ref bool __result)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!__result)
			{
				__result = QuartersAnnex.LobbyContains(pos);
			}
		}
	}
}