Decompiled source of LateLanding v1.0.1

plugins/LateLanding/aj.LateLanding.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LateLanding.Configuration;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("aj.LateLanding")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("LateLanding")]
[assembly: AssemblyTitle("aj.LateLanding")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was created with the assistance of generative AI (code); see the README credits for which assets.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 LateLanding
{
	[HarmonyPatch]
	internal static class JoinGate
	{
		private static ulong? preparing;

		private static float preparingSince;

		private const float PreparingTimeout = 120f;

		private static bool? lobbyOpen;

		private static bool checkedOtherGates;

		internal static ulong? Preparing
		{
			get
			{
				return preparing;
			}
			set
			{
				preparing = value;
				preparingSince = Time.time;
			}
		}

		private static StartOfRound? Round => StartOfRound.Instance;

		internal static bool Landed
		{
			get
			{
				if ((Object)(object)Round != (Object)null && !Round.inShipPhase && Round.shipDoorsEnabled)
				{
					return !Round.shipIsLeaving;
				}
				return false;
			}
		}

		internal static bool CanJoinNow
		{
			get
			{
				StartOfRound round = Round;
				if ((Object)(object)round == (Object)null)
				{
					return true;
				}
				if (round.inShipPhase)
				{
					return !round.newGameIsLoading;
				}
				if (Plugin.BoundConfig.JoinWhileLanded.Value && Landed)
				{
					return !Preparing.HasValue;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		[HarmonyPrefix]
		private static void OpenForApproval(out bool __state)
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			__state = instance.gameHasStarted && CanJoinNow;
			if (__state)
			{
				instance.gameHasStarted = false;
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		[HarmonyPostfix]
		private static void NoteLateJoiner(ConnectionApprovalRequest request, ConnectionApprovalResponse response, bool __state)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (__state && response.Approved && Landed)
			{
				Preparing = request.ClientNetworkId;
				Plugin.Logger.LogInfo((object)$"Late joiner {request.ClientNetworkId} approved while landed.");
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")]
		[HarmonyFinalizer]
		private static void CloseAfterApproval(bool __state)
		{
			if (__state)
			{
				GameNetworkManager.Instance.gameHasStarted = true;
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "LeaveLobbyAtGameStart")]
		[HarmonyPrefix]
		private static bool KeepHostLobby()
		{
			if (!((Object)(object)NetworkManager.Singleton == (Object)null))
			{
				return !NetworkManager.Singleton.IsServer;
			}
			return true;
		}

		[HarmonyPatch(typeof(QuickMenuManager), "DisableInviteFriendsButton")]
		[HarmonyPrefix]
		private static bool KeepInviteButton()
		{
			return false;
		}

		[HarmonyPatch(typeof(QuickMenuManager), "InviteFriendsButton")]
		[HarmonyPrefix]
		private static bool InviteAfterLanding()
		{
			if (!GameNetworkManager.Instance.gameHasStarted)
			{
				return true;
			}
			if (CanJoinNow)
			{
				GameNetworkManager.Instance.InviteFriendsUI();
			}
			return false;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnClientDisconnect")]
		[HarmonyPostfix]
		private static void JoinerLeft(ulong clientId)
		{
			if (Preparing == clientId)
			{
				Preparing = null;
			}
		}

		internal static void UpdateLobby()
		{
			if (preparing.HasValue && Time.time - preparingSince > 120f)
			{
				Plugin.Logger.LogWarning((object)$"Late joiner {preparing} never finished catching up; opening the gate again.");
				Preparing = null;
			}
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (!((Object)(object)instance == (Object)null) && !instance.disableSteam && instance.currentLobby.HasValue && !((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer)
			{
				bool flag = CanJoinNow && instance.connectedPlayers < instance.maxAllowedPlayers;
				if (lobbyOpen != flag)
				{
					lobbyOpen = flag;
					instance.SetLobbyJoinable(flag);
				}
			}
		}

		internal static void Reset()
		{
			preparing = null;
			lobbyOpen = null;
		}

		internal static void WarnAboutOtherGates()
		{
			if (checkedOtherGates)
			{
				return;
			}
			checkedOtherGates = true;
			MethodInfo methodInfo = AccessTools.Method(typeof(GameNetworkManager), "ConnectionApproval", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(GameNetworkManager), "LeaveLobbyAtGameStart", (Type[])null, (Type[])null);
			HashSet<string> hashSet = new HashSet<string>();
			MethodInfo[] array = new MethodInfo[2] { methodInfo, methodInfo2 };
			foreach (MethodInfo methodInfo3 in array)
			{
				Patches val = ((methodInfo3 != null) ? Harmony.GetPatchInfo((MethodBase)methodInfo3) : null);
				if (val != null)
				{
					hashSet.UnionWith(val.Owners);
				}
			}
			hashSet.Remove("aj.LateLanding");
			if (hashSet.Count > 0)
			{
				Plugin.Logger.LogWarning((object)("Other mods also change who may join (" + string.Join(", ", hashSet) + "). If late joins misbehave, try without them; two late-join mods at once will clash."));
			}
		}
	}
	[HarmonyPatch]
	internal static class JoinMessageFix
	{
		internal class Kept
		{
			public float globalTime;

			public int[] weathers;

			public int[] sales;

			public TerminalNode[] decor;
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
		[HarmonyPrefix]
		private static void KeepRound(StartOfRound __instance, ulong clientId, out Kept? __state)
		{
			__state = null;
			if (!((NetworkBehaviour)__instance).IsServer && !__instance.inShipPhase && clientId != NetworkManager.Singleton.LocalClientId)
			{
				Terminal val = Object.FindObjectOfType<Terminal>();
				__state = new Kept
				{
					globalTime = TimeOfDay.Instance.globalTime,
					weathers = __instance.levels.Select((SelectableLevel l) => (int)l.currentWeather).ToArray(),
					sales = (int[])val.itemSalesPercentages.Clone(),
					decor = val.ShipDecorSelection.ToArray()
				};
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
		[HarmonyPostfix]
		private static void RestoreRound(StartOfRound __instance, Kept? __state)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (__state != null)
			{
				TimeOfDay.Instance.globalTime = __state.globalTime;
				for (int i = 0; i < __instance.levels.Length; i++)
				{
					__instance.levels[i].currentWeather = (LevelWeatherType)__state.weathers[i];
				}
				Terminal obj = Object.FindObjectOfType<Terminal>();
				obj.itemSalesPercentages = __state.sales;
				obj.ShipDecorSelection.Clear();
				obj.ShipDecorSelection.AddRange(__state.decor);
				HideSpace(__instance);
				__instance.SwitchMapMonitorPurpose(false);
			}
			if (GameNetworkManager.Instance.gameHasStarted)
			{
				RecountLiving(__instance);
			}
			KnowEveryone(__instance);
		}

		private static void KnowEveryone(StartOfRound round)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			int num = Mathf.Min(round.connectedPlayersAmount + 1, round.allPlayerScripts.Length);
			PumaAI[] array = Object.FindObjectsOfType<PumaAI>();
			foreach (PumaAI val in array)
			{
				if (val.playerKnowledge != null && val.playerKnowledge.Length < num)
				{
					PumaPlayerKnowledge[] playerKnowledge = val.playerKnowledge;
					val.playerKnowledge = (PumaPlayerKnowledge[])(object)new PumaPlayerKnowledge[num];
					for (int j = 0; j < num; j++)
					{
						val.playerKnowledge[j] = (PumaPlayerKnowledge)((j < playerKnowledge.Length && playerKnowledge[j] != null) ? ((object)playerKnowledge[j]) : ((object)new PumaPlayerKnowledge(round.allPlayerScripts[j])));
					}
				}
			}
		}

		internal static void HideSpace(StartOfRound round)
		{
			if ((Object)(object)round.currentPlanetPrefab != (Object)null)
			{
				round.currentPlanetPrefab.SetActive(false);
			}
			((Component)round.outerSpaceSunAnimator).gameObject.SetActive(false);
		}

		internal static void RecountLiving(StartOfRound round)
		{
			int num = 0;
			PlayerControllerB[] allPlayerScripts = round.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isPlayerDead)
				{
					val.isPlayerControlled = false;
				}
				else if (val.isPlayerControlled)
				{
					num++;
				}
			}
			round.livingPlayers = num;
		}
	}
	[HarmonyPatch]
	internal static class LandingJournal
	{
		private enum Phase : byte
		{
			Generation,
			Setup,
			Spawn
		}

		private class Entry
		{
			public Phase phase;

			public float sentAt;

			public string message = "";

			public ulong objectId;

			public ushort behaviour;

			public uint method;

			public byte[] payload;
		}

		private const float SpawnSetupSeconds = 3f;

		private const int MaxJournalBytes = 262144;

		private const string OwnMessages = "aj.LateLanding.";

		private static readonly FieldInfo ExecStage = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_exec_stage");

		private static readonly FieldInfo RpcTable = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_func_table");

		private static readonly MethodInfo InvokeNamed = AccessTools.Method(typeof(CustomMessagingManager), "InvokeNamedMessage", (Type[])null, (Type[])null);

		private static readonly HashSet<string> EveryoneTargets = new HashSet<string> { "EveryoneRpcTarget", "ClientsAndHostRpcTarget", "NotServerRpcTarget", "NotMeRpcTarget", "NotOwnerRpcTarget" };

		private static readonly List<Entry> entries = new List<Entry>();

		private static readonly Dictionary<ulong, float> spawnedAt = new Dictionary<ulong, float>();

		private static readonly Dictionary<ulong, float> connectedAt = new Dictionary<ulong, float>();

		private static readonly Dictionary<(Type, uint), bool> fromOtherMods = new Dictionary<(Type, uint), bool>();

		private static bool generating;

		private static float setupEndsAt = -1f;

		private static int journalBytes;

		private static List<Entry> received = new List<Entry>();

		private static bool IsHost
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton != (Object)null)
				{
					return NetworkManager.Singleton.IsServer;
				}
				return false;
			}
		}

		private static Phase? LandingPhase
		{
			get
			{
				if (!generating)
				{
					if (!(Time.time < setupEndsAt))
					{
						return null;
					}
					return Phase.Setup;
				}
				return Phase.Generation;
			}
		}

		private static bool Executing(NetworkBehaviour b)
		{
			return ExecStage.GetValue(b).ToString() == "Execute";
		}

		[HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")]
		[HarmonyPrefix]
		private static void LandingStarts(RoundManager __instance)
		{
			if (!IsHost || Executing((NetworkBehaviour)(object)__instance))
			{
				return;
			}
			entries.Clear();
			journalBytes = 0;
			generating = true;
			setupEndsAt = -1f;
			Dictionary<ulong, NetworkObject> spawned = NetworkManager.Singleton.SpawnManager.SpawnedObjects;
			foreach (ulong item in spawnedAt.Keys.Where((ulong id) => !spawned.ContainsKey(id)).ToList())
			{
				spawnedAt.Remove(item);
			}
		}

		[HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")]
		[HarmonyPrefix]
		private static void SetupStarts(RoundManager __instance)
		{
			if (IsHost && generating && !Executing((NetworkBehaviour)(object)__instance))
			{
				generating = false;
				setupEndsAt = Time.time + 9f;
			}
		}

		[HarmonyPatch(typeof(NetworkSpawnManager), "SpawnNetworkObjectLocallyCommon")]
		[HarmonyPostfix]
		private static void Spawned(NetworkObject networkObject)
		{
			if (IsHost)
			{
				spawnedAt[networkObject.NetworkObjectId] = Time.time;
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "OnClientConnect")]
		[HarmonyPostfix]
		private static void Connected(ulong clientId)
		{
			if (IsHost)
			{
				connectedAt[clientId] = Time.time;
			}
		}

		[HarmonyPatch(typeof(NetworkBehaviour), "__endSendClientRpc")]
		[HarmonyPrefix]
		private static void ClientRpcGoesOut(NetworkBehaviour __instance, ref FastBufferWriter bufferWriter, uint rpcMethodId, ClientRpcParams clientRpcParams, RpcDelivery rpcDelivery)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if ((int)rpcDelivery != 1 && clientRpcParams.Send.TargetClientIds == null && !clientRpcParams.Send.TargetClientIdsNativeArray.HasValue)
			{
				Record(__instance, rpcMethodId, ref bufferWriter);
			}
		}

		[HarmonyPatch(typeof(NetworkBehaviour), "__endSendRpc")]
		[HarmonyPrefix]
		private static void RpcGoesOut(NetworkBehaviour __instance, ref FastBufferWriter bufferWriter, uint rpcMethodId, RpcParams rpcParams, SendTo defaultTarget, RpcDelivery rpcDelivery)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if ((int)rpcDelivery != 1 && ToEveryone(rpcParams.Send.Target, defaultTarget))
			{
				Record(__instance, rpcMethodId, ref bufferWriter);
			}
		}

		private static bool ToEveryone(BaseRpcTarget? target, SendTo defaultTarget)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if (target != null)
			{
				return EveryoneTargets.Contains(((object)target).GetType().Name);
			}
			if ((int)defaultTarget != 6 && (int)defaultTarget != 7 && (int)defaultTarget != 3 && (int)defaultTarget != 5)
			{
				return (int)defaultTarget == 1;
			}
			return true;
		}

		private static void Record(NetworkBehaviour b, uint method, ref FastBufferWriter payload)
		{
			if (!IsHost || !b.IsSpawned || journalBytes > 262144)
			{
				return;
			}
			Phase? phase = LandingPhase;
			if (!phase.HasValue)
			{
				if (!spawnedAt.TryGetValue(b.NetworkObjectId, out var value) || Time.time - value > 3f)
				{
					return;
				}
				phase = Phase.Spawn;
			}
			if (FromAnotherMod(((object)b).GetType(), method))
			{
				byte[] array = ((FastBufferWriter)(ref payload)).ToArray();
				journalBytes += array.Length + 24;
				entries.Add(new Entry
				{
					phase = phase.Value,
					sentAt = Time.time,
					objectId = b.NetworkObjectId,
					behaviour = b.NetworkBehaviourId,
					method = method,
					payload = array
				});
			}
		}

		[HarmonyPatch(typeof(CustomMessagingManager), "SendNamedMessage", new Type[]
		{
			typeof(string),
			typeof(IReadOnlyList<ulong>),
			typeof(FastBufferWriter),
			typeof(NetworkDelivery)
		})]
		[HarmonyPrefix]
		private static void NamedMessageGoesOut(string messageName, IReadOnlyList<ulong> clientIds, FastBufferWriter messageStream, NetworkDelivery networkDelivery)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			Phase? landingPhase = LandingPhase;
			if (IsHost && landingPhase.HasValue && journalBytes <= 262144 && !messageName.StartsWith("aj.LateLanding.") && (int)networkDelivery != 0 && (int)networkDelivery != 1 && NetworkManager.Singleton.ConnectedClientsIds.Where((ulong id) => id != 0).All((ulong id) => clientIds.Contains(id)))
			{
				byte[] array = ((FastBufferWriter)(ref messageStream)).ToArray();
				journalBytes += array.Length + messageName.Length + 24;
				entries.Add(new Entry
				{
					phase = landingPhase.Value,
					sentAt = Time.time,
					message = messageName,
					payload = array
				});
			}
		}

		private static bool FromAnotherMod(Type type, uint method)
		{
			if (!fromOtherMods.TryGetValue((type, method), out var value))
			{
				Assembly assembly = Handler(type, method)?.Method.DeclaringType?.Assembly;
				value = assembly != null && IsAnotherMod(assembly);
				fromOtherMods[(type, method)] = value;
			}
			return value;
		}

		private static bool IsAnotherMod(Assembly assembly)
		{
			string name = assembly.GetName().Name;
			if (assembly != typeof(LandingJournal).Assembly && name != "Assembly-CSharp" && name != "Assembly-CSharp-firstpass" && !name.StartsWith("Unity."))
			{
				return !name.StartsWith("UnityEngine");
			}
			return false;
		}

		private static Delegate? Handler(Type type, uint method)
		{
			if (!(RpcTable.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(type) || !(dictionary[type] is IDictionary dictionary2) || !dictionary2.Contains(method))
			{
				return null;
			}
			return dictionary2[method] as Delegate;
		}

		internal static byte[] Describe(ulong joiner)
		{
			float value;
			float cutoff = (connectedAt.TryGetValue(joiner, out value) ? value : float.MaxValue);
			Dictionary<ulong, NetworkObject> spawned = NetworkManager.Singleton.SpawnManager.SpawnedObjects;
			List<Entry> list = entries.Where((Entry e) => e.sentAt < cutoff && (e.message.Length > 0 || spawned.ContainsKey(e.objectId))).ToList();
			using MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write(list.Count);
				foreach (Entry item in list)
				{
					binaryWriter.Write((byte)item.phase);
					binaryWriter.Write(item.message);
					binaryWriter.Write(item.objectId);
					binaryWriter.Write(item.behaviour);
					binaryWriter.Write(item.method);
					binaryWriter.Write(item.payload.Length);
					binaryWriter.Write(item.payload);
				}
			}
			return memoryStream.ToArray();
		}

		internal static void Read(byte[] journal)
		{
			received = new List<Entry>();
			if (journal.Length == 0)
			{
				return;
			}
			using BinaryReader binaryReader = new BinaryReader(new MemoryStream(journal));
			int num = binaryReader.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				Entry entry = new Entry
				{
					phase = (Phase)binaryReader.ReadByte(),
					message = binaryReader.ReadString(),
					objectId = binaryReader.ReadUInt64(),
					behaviour = binaryReader.ReadUInt16(),
					method = binaryReader.ReadUInt32()
				};
				entry.payload = binaryReader.ReadBytes(binaryReader.ReadInt32());
				received.Add(entry);
			}
		}

		internal static void ReplayGeneration()
		{
			Replay("while the facility was generated", (Entry e) => e.phase == Phase.Generation);
		}

		internal static void ReplaySetup()
		{
			Replay("while the moon was set up and as things spawned", (Entry e) => e.phase != Phase.Generation);
		}

		private static void Replay(string when, Func<Entry, bool> which)
		{
			List<Entry> list = received.Where(which).ToList();
			if (list.Count == 0)
			{
				return;
			}
			List<string> ran = new List<string>();
			foreach (Entry e in list)
			{
				MoonSnapshot.Safely($"another mod's message ({e.message}{e.objectId}/{e.method})", delegate
				{
					string text2 = Run(e);
					if (text2 != null)
					{
						ran.Add(text2);
					}
				});
			}
			string text = string.Join(", ", from w in ran
				group w by w into g
				select (g.Count() <= 1) ? g.Key : $"{g.Key} x{g.Count()}");
			Plugin.Logger.LogInfo((object)$"Replayed {ran.Count} of {list.Count} messages other mods sent {when}: {text}.");
		}

		private unsafe static string? Run(Entry e)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			FastBufferReader val = default(FastBufferReader);
			((FastBufferReader)(ref val))..ctor(e.payload, (Allocator)2, -1, 0);
			try
			{
				if (e.message.Length > 0)
				{
					ulong? num = NamedHash(singleton, e.message);
					if (!num.HasValue)
					{
						return null;
					}
					InvokeNamed.Invoke(singleton.CustomMessagingManager, new object[4] { num.Value, 0uL, val, 0 });
					return e.message;
				}
				if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(e.objectId, out var value))
				{
					return null;
				}
				NetworkBehaviour networkBehaviourAtOrderIndex = value.GetNetworkBehaviourAtOrderIndex(e.behaviour);
				Delegate obj = (((Object)(object)networkBehaviourAtOrderIndex != (Object)null) ? Handler(((object)networkBehaviourAtOrderIndex).GetType(), e.method) : null);
				if ((object)obj == null)
				{
					return null;
				}
				obj.DynamicInvoke(networkBehaviourAtOrderIndex, val, (object)default(__RpcParams));
				return ((object)networkBehaviourAtOrderIndex).GetType().Name;
			}
			finally
			{
				((IDisposable)(*(FastBufferReader*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static ulong? NamedHash(NetworkManager nm, string name)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			bool flag = (int)nm.NetworkConfig.RpcHashSize == 0;
			foreach (KeyValuePair<ulong, string> item in Traverse.Create((object)nm.CustomMessagingManager).Field(flag ? "m_MessageHandlerNameLookup32" : "m_MessageHandlerNameLookup64").GetValue<Dictionary<ulong, string>>())
			{
				if (item.Value == name)
				{
					return item.Key;
				}
			}
			return null;
		}

		internal static void Reset()
		{
			received.Clear();
			entries.Clear();
			spawnedAt.Clear();
			connectedAt.Clear();
			generating = false;
			setupEndsAt = -1f;
			journalBytes = 0;
		}
	}
	[HarmonyPatch]
	internal static class LateJoiner
	{
		private static Vector3 shipSpot;

		private const float ScrapRecheckDelay = 4f;

		private static float recheckScrapAt = -1f;

		internal static bool Waiting { get; private set; }

		[HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc")]
		[HarmonyPostfix]
		private static void AskHost(StartOfRound __instance, ulong clientId)
		{
			if (!((NetworkBehaviour)__instance).IsServer && clientId == NetworkManager.Singleton.LocalClientId)
			{
				LateNet.SayHello();
			}
		}

		internal static void ApplyLanded(LateNet.LevelInfo info)
		{
			//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_0153: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Invalid comparison between Unknown and I4
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_024e: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayerController == (Object)null)
			{
				return;
			}
			Terminal val = Object.FindObjectOfType<Terminal>();
			for (int i = 0; i < instance.levels.Length && i < info.weathers.Length; i++)
			{
				instance.levels[i].currentWeather = (LevelWeatherType)info.weathers[i];
			}
			val.itemSalesPercentages = info.sales;
			List<UnlockableItem> unlockables = instance.unlockablesList.unlockables;
			val.ShipDecorSelection.Clear();
			val.ShipDecorSelection.AddRange(from index in info.decor
				where index >= 0 && index < unlockables.Count
				select unlockables[index].shopSelectionNode);
			GameNetworkManager.Instance.gameHasStarted = true;
			instance.inShipPhase = false;
			instance.shipHasLanded = true;
			instance.shipDoorsEnabled = true;
			instance.SetPlayerObjectExtrapolate(false);
			((Component)instance.shipAnimatorObject).GetComponent<Animator>().Play("ShipIdleLanded", 0, 0f);
			instance.SetShipDoorsClosed(info.hangarDoorsClosed);
			instance.shipDoorsAnimator.SetBool("Closed", info.hangarDoorsClosed);
			Object.FindObjectOfType<HangarShipDoor>().SetDoorButtonsEnabled(true);
			JoinMessageFix.HideSpace(instance);
			instance.SwitchMapMonitorPurpose(false);
			LevelWeatherType currentWeather = instance.currentLevel.currentWeather;
			TimeOfDay.Instance.currentLevelWeather = currentWeather;
			if ((int)currentWeather != -1)
			{
				WeatherEffect val2 = TimeOfDay.Instance.effects[currentWeather];
				val2.effectEnabled = true;
				if ((Object)(object)val2.effectPermanentObject != (Object)null)
				{
					val2.effectPermanentObject.SetActive(true);
				}
			}
			TimeOfDay.Instance.globalTime = info.globalTime;
			if (instance.currentLevel.planetHasTime)
			{
				TimeOfDay.Instance.currentDayTimeStarted = true;
				TimeOfDay.Instance.movingGlobalTimeForward = true;
			}
			StartMatchLever obj = Object.FindObjectOfType<StartMatchLever>();
			obj.leverHasBeenPulled = true;
			obj.triggerScript.animationString = "SA_PushLeverBack";
			obj.triggerScript.interactable = true;
			JoinMessageFix.RecountLiving(instance);
			DetachMoonScrap(instance);
			recheckScrapAt = Time.time + 4f;
			shipSpot = ((Component)localPlayerController).transform.position;
			Waiting = true;
			HUDManager.Instance.DisplayTip("Late Landing", "You landed late. Hang on in the ship while the moon catches up...", false, false, "LC_Tip1");
			Plugin.Logger.LogInfo((object)$"Joined while landed on {instance.currentLevel.PlanetName} ({currentWeather}); rebuilding the moon.");
			try
			{
				MoonRebuild.Start(info);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Couldn't rebuild the moon: {arg}");
				MoonRebuild.Reset();
				CouldNotMatch();
			}
		}

		internal static void ApplySnapshot(MoonSnapshot snapshot)
		{
			if (Waiting)
			{
				snapshot.Apply();
				Waiting = false;
				HideLoading();
				HUDManager.Instance.DisplayTip("Late Landing", "You landed with the crew. Go get some scrap!", false, false, "LC_Tip1");
				Plugin.Logger.LogInfo((object)$"Caught up with the round: {snapshot.players.Count} players, {snapshot.enemies.Count} monsters, {snapshot.webs.Count} webs, {snapshot.doors.Count} doors, {snapshot.scrap.Count} scrap. Playing.");
				LateNet.SayReady(playing: true);
			}
		}

		internal static void CouldNotMatch()
		{
			HideLoading();
			HUDManager.Instance.DisplayTip("Late Landing", "This moon couldn't be matched for you. Wait in the ship: you'll join the crew when it takes off.", true, false, "LC_Tip1");
			LateNet.SayReady(playing: false);
		}

		private static void HideLoading()
		{
			((Behaviour)HUDManager.Instance.loadingText).enabled = false;
			HUDManager.Instance.LoadingScreen.SetBool("IsLoading", false);
		}

		private static void DetachMoonScrap(StartOfRound round)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = round.shipBounds.bounds;
			Transform spawnedScrapContainer = RoundManager.Instance.spawnedScrapContainer;
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			foreach (GrabbableObject val in array)
			{
				if (!((Object)(object)((Component)val).transform.parent != (Object)(object)round.elevatorTransform) && !((Bounds)(ref bounds)).Contains(((Component)val).transform.position))
				{
					((Component)val).transform.SetParent(spawnedScrapContainer, true);
					val.isInElevator = false;
					val.isInShipRoom = false;
					val.scrapPersistedThroughRounds = false;
				}
			}
		}

		internal static void Tick()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (!Waiting)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayerController == (Object)null || instance.inShipPhase)
			{
				Waiting = false;
				MoonRebuild.Reset();
				return;
			}
			MoonRebuild.Tick();
			if (recheckScrapAt > 0f && Time.time >= recheckScrapAt)
			{
				recheckScrapAt = -1f;
				DetachMoonScrap(instance);
			}
			if (localPlayerController.isPlayerControlled && !localPlayerController.isPlayerDead && !localPlayerController.isInHangarShipRoom && !instance.shipIsLeaving)
			{
				localPlayerController.TeleportPlayer(shipSpot, false, 0f, false, true);
				HUDManager.Instance.DisplayTip("Late Landing", "Stay in the ship until it takes off.", false, false, "LC_Tip1");
			}
		}

		internal static void Reset()
		{
			Waiting = false;
			MoonRebuild.Reset();
		}

		[HarmonyPatch(typeof(EnemyAI), "ChangeOwnershipOfEnemy")]
		[HarmonyPrefix]
		private static bool KeepGhostGirlsVictim(EnemyAI __instance)
		{
			if (__instance is DressGirlAI && !((NetworkBehaviour)__instance).IsServer && (Object)(object)StartOfRound.Instance != (Object)null)
			{
				return StartOfRound.Instance.shipHasLanded;
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
		[HarmonyPrefix]
		private static bool NoDamageWhileWaiting(PlayerControllerB __instance)
		{
			if (Waiting)
			{
				return !((NetworkBehaviour)__instance).IsOwner;
			}
			return true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPrefix]
		private static bool NoDeathWhileWaiting(PlayerControllerB __instance)
		{
			if (Waiting && ((NetworkBehaviour)__instance).IsOwner)
			{
				return StartOfRound.Instance.shipIsLeaving;
			}
			return true;
		}
	}
	internal static class LateNet
	{
		internal class LevelInfo
		{
			public float globalTime;

			public int[] weathers;

			public int[] sales;

			public int[] decor;

			public bool hangarDoorsClosed;

			public int seed;

			public int levelID;

			public int moldIterations;

			public int moldStart;

			public int interiorNodes;

			public int[] destroyedMold = new int[0];

			public float interiorHash;

			public byte[] journal = new byte[0];

			public void Write(FastBufferWriter w)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: 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_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: 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_0068: 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_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: 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_0112: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref globalTime, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(weathers, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(sales, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(decor, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref hangarDoorsClosed, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref seed, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref levelID, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref moldIterations, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref moldStart, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(destroyedMold, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref interiorNodes, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref interiorHash, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<byte>(journal, default(ForPrimitives));
			}

			public static LevelInfo Read(FastBufferReader r)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: 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_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: 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_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: 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_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: 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_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				//IL_011e: Unknown result type (might be due to invalid IL or missing references)
				LevelInfo levelInfo = new LevelInfo();
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref levelInfo.globalTime, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.weathers, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.sales, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.decor, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref levelInfo.hangarDoorsClosed, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.seed, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.levelID, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.moldIterations, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.moldStart, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.destroyedMold, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref levelInfo.interiorNodes, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref levelInfo.interiorHash, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref levelInfo.journal, default(ForPrimitives));
				return levelInfo;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnHello;

			public static HandleNamedMessageDelegate <1>__OnLevelInfo;

			public static HandleNamedMessageDelegate <2>__OnBuilt;

			public static HandleNamedMessageDelegate <3>__OnSnapshot;

			public static HandleNamedMessageDelegate <4>__OnReady;

			public static HandleNamedMessageDelegate <5>__OnJoined;
		}

		private const string HelloMessage = "aj.LateLanding.Hello";

		private const string LevelInfoMessage = "aj.LateLanding.LevelInfo";

		private const string BuiltMessage = "aj.LateLanding.Built";

		private const string SnapshotMessage = "aj.LateLanding.Snapshot";

		private const string ReadyMessage = "aj.LateLanding.Ready";

		private const string JoinedMessage = "aj.LateLanding.Joined";

		private const int MaxMessageBytes = 524288;

		private static readonly string[] All = new string[6] { "aj.LateLanding.Hello", "aj.LateLanding.LevelInfo", "aj.LateLanding.Built", "aj.LateLanding.Snapshot", "aj.LateLanding.Ready", "aj.LateLanding.Joined" };

		private const int PieceBytes = 1000;

		private const int PiecesPerFrame = 24;

		private static readonly Queue<(ulong client, string message, int index, int pieces, byte[] bytes)> outgoing = new Queue<(ulong, string, int, int, byte[])>();

		private static readonly List<byte[]> received = new List<byte[]>();

		private static CustomMessagingManager? Messages
		{
			get
			{
				if (!((Object)(object)NetworkManager.Singleton != (Object)null))
				{
					return null;
				}
				return NetworkManager.Singleton.CustomMessagingManager;
			}
		}

		internal static void Register()
		{
			//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_002b: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006c: 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_0077: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//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_00c3: Expected O, but got Unknown
			//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_00e9: Expected O, but got Unknown
			CustomMessagingManager messages = Messages;
			if (messages != null)
			{
				object obj = <>O.<0>__OnHello;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnHello;
					<>O.<0>__OnHello = val;
					obj = (object)val;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.Hello", (HandleNamedMessageDelegate)obj);
				object obj2 = <>O.<1>__OnLevelInfo;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = OnLevelInfo;
					<>O.<1>__OnLevelInfo = val2;
					obj2 = (object)val2;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.LevelInfo", (HandleNamedMessageDelegate)obj2);
				object obj3 = <>O.<2>__OnBuilt;
				if (obj3 == null)
				{
					HandleNamedMessageDelegate val3 = OnBuilt;
					<>O.<2>__OnBuilt = val3;
					obj3 = (object)val3;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.Built", (HandleNamedMessageDelegate)obj3);
				object obj4 = <>O.<3>__OnSnapshot;
				if (obj4 == null)
				{
					HandleNamedMessageDelegate val4 = OnSnapshot;
					<>O.<3>__OnSnapshot = val4;
					obj4 = (object)val4;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.Snapshot", (HandleNamedMessageDelegate)obj4);
				object obj5 = <>O.<4>__OnReady;
				if (obj5 == null)
				{
					HandleNamedMessageDelegate val5 = OnReady;
					<>O.<4>__OnReady = val5;
					obj5 = (object)val5;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.Ready", (HandleNamedMessageDelegate)obj5);
				object obj6 = <>O.<5>__OnJoined;
				if (obj6 == null)
				{
					HandleNamedMessageDelegate val6 = OnJoined;
					<>O.<5>__OnJoined = val6;
					obj6 = (object)val6;
				}
				messages.RegisterNamedMessageHandler("aj.LateLanding.Joined", (HandleNamedMessageDelegate)obj6);
			}
		}

		internal static void Unregister()
		{
			outgoing.Clear();
			received.Clear();
			CustomMessagingManager messages = Messages;
			if (messages != null)
			{
				string[] all = All;
				foreach (string text in all)
				{
					messages.UnregisterNamedMessageHandler(text);
				}
			}
		}

		internal static void SayHello()
		{
			SendToHost("aj.LateLanding.Hello", null);
		}

		internal static void AskSnapshot()
		{
			SendToHost("aj.LateLanding.Built", null);
		}

		internal static void SayReady(bool playing)
		{
			SendToHost("aj.LateLanding.Ready", delegate(FastBufferWriter w)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref playing, default(ForPrimitives));
			});
		}

		private unsafe static void SendToHost(string message, Action<FastBufferWriter>? write)
		{
			//IL_002e: 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)
			CustomMessagingManager messages = Messages;
			if (messages == null || NetworkManager.Singleton.IsServer)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				write?.Invoke(val);
				messages.SendNamedMessage(message, 0uL, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnHello(ulong sender, FastBufferReader reader)
		{
			StartOfRound instance = StartOfRound.Instance;
			if (!NetworkManager.Singleton.IsServer || (Object)(object)instance == (Object)null || instance.inShipPhase)
			{
				return;
			}
			Terminal val = Object.FindObjectOfType<Terminal>();
			List<UnlockableItem> unlockables = instance.unlockablesList.unlockables;
			LevelInfo levelInfo = new LevelInfo
			{
				globalTime = TimeOfDay.Instance.globalTime,
				weathers = instance.levels.Select((SelectableLevel l) => (int)l.currentWeather).ToArray(),
				sales = val.itemSalesPercentages,
				decor = (from node in val.ShipDecorSelection
					select unlockables.FindIndex((UnlockableItem u) => (Object)(object)u.shopSelectionNode == (Object)(object)node) into i
					where i >= 0
					select i).ToArray(),
				hangarDoorsClosed = instance.hangarDoorsClosed
			};
			MoonRebuild.Describe(levelInfo, sender);
			SendTo(sender, "aj.LateLanding.LevelInfo", levelInfo.Write);
		}

		private static void OnBuilt(ulong sender, FastBufferReader reader)
		{
			if (NetworkManager.Singleton.IsServer && (Object)(object)StartOfRound.Instance != (Object)null && !StartOfRound.Instance.inShipPhase)
			{
				try
				{
					SendInOrder(sender, "aj.LateLanding.Snapshot", MoonSnapshot.Take().Write);
				}
				catch (Exception arg)
				{
					Plugin.Logger.LogError((object)$"Couldn't describe the round for the late joiner: {arg}");
				}
			}
		}

		private unsafe static void SendInOrder(ulong client, string message, Action<FastBufferWriter> write)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter obj = default(FastBufferWriter);
			((FastBufferWriter)(ref obj))..ctor(1024, (Allocator)2, 524288);
			byte[] array;
			try
			{
				write(obj);
				array = ((FastBufferWriter)(ref obj)).ToArray();
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&obj))/*cast due to .constrained prefix*/).Dispose();
			}
			int num = Mathf.Max(1, (array.Length + 1000 - 1) / 1000);
			for (int i = 0; i < num; i++)
			{
				int num2 = i * 1000;
				int num3 = Mathf.Min(1000, array.Length - num2);
				byte[] array2 = new byte[num3];
				Array.Copy(array, num2, array2, 0, num3);
				outgoing.Enqueue((client, message, i, num, array2));
			}
			Pump();
		}

		internal unsafe static void Pump()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			CustomMessagingManager messages = Messages;
			FastBufferWriter val = default(FastBufferWriter);
			for (int i = 0; i < 24; i++)
			{
				if (outgoing.Count <= 0)
				{
					break;
				}
				var (num, text, num2, num3, array) = outgoing.Dequeue();
				if (messages != null && NetworkManager.Singleton.ConnectedClientsIds.Contains(num))
				{
					((FastBufferWriter)(ref val))..ctor(1032, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num2, default(ForPrimitives));
						((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num3, default(ForPrimitives));
						((FastBufferWriter)(ref val)).WriteValueSafe<byte>(array, default(ForPrimitives));
						messages.SendNamedMessage(text, num, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
		}

		private static bool Collect(FastBufferReader reader, out byte[] whole)
		{
			//IL_0006: 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_0018: 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_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)
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			int num2 = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
			byte[] item = default(byte[]);
			((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref item, default(ForPrimitives));
			if (num == 0)
			{
				received.Clear();
			}
			received.Add(item);
			whole = null;
			if (received.Count < num2)
			{
				return false;
			}
			whole = received.SelectMany((byte[] p) => p).ToArray();
			received.Clear();
			return true;
		}

		private unsafe static void OnReady(ulong sender, FastBufferReader reader)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkManager.Singleton.IsServer || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return;
			}
			bool playing = default(bool);
			((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref playing, default(ForPrimitives));
			int value;
			int slot = (StartOfRound.Instance.ClientPlayerList.TryGetValue(sender, out value) ? value : (-1));
			CustomMessagingManager messages = Messages;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref slot, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref playing, default(ForPrimitives));
				List<ulong> list = NetworkManager.Singleton.ConnectedClientsIds.Where((ulong id) => id != 0L && id != sender).ToList();
				if (list.Count > 0)
				{
					messages.SendNamedMessage("aj.LateLanding.Joined", (IReadOnlyList<ulong>)list, val, (NetworkDelivery)2);
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
			LateRunner.AnnounceJoin(slot, playing);
			JoinMessageFix.RecountLiving(StartOfRound.Instance);
			if (JoinGate.Preparing == sender)
			{
				JoinGate.Preparing = null;
			}
		}

		private unsafe static void SendTo(ulong client, string message, Action<FastBufferWriter> write)
		{
			//IL_0013: 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)
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(1024, (Allocator)2, 524288);
			try
			{
				write(val);
				Messages.SendNamedMessage(message, client, val, (NetworkDelivery)4);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnLevelInfo(ulong sender, FastBufferReader reader)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if (sender == 0L)
			{
				LateJoiner.ApplyLanded(LevelInfo.Read(reader));
			}
		}

		private unsafe static void OnSnapshot(ulong sender, FastBufferReader reader)
		{
			//IL_0003: 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)
			if (sender != 0L || !Collect(reader, out byte[] whole))
			{
				return;
			}
			FastBufferReader r = default(FastBufferReader);
			((FastBufferReader)(ref r))..ctor(whole, (Allocator)2, -1, 0);
			try
			{
				LateJoiner.ApplySnapshot(MoonSnapshot.Read(r));
			}
			finally
			{
				((IDisposable)(*(FastBufferReader*)(&r))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnJoined(ulong sender, FastBufferReader reader)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			if (sender == 0L)
			{
				int slot = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref slot, default(ForPrimitives));
				bool playing = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref playing, default(ForPrimitives));
				LateRunner.AnnounceJoin(slot, playing);
			}
		}
	}
	[HarmonyPatch]
	internal class LateRunner : MonoBehaviour
	{
		private const float AnnounceDelay = 2.5f;

		private const float LobbyCheckEvery = 1f;

		private static readonly List<(int slot, bool playing, float at)> announcements = new List<(int, bool, float)>();

		private float nextLobbyCheck;

		private bool wasLanded;

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void Attach(StartOfRound __instance)
		{
			((Component)__instance).gameObject.AddComponent<LateRunner>();
			LateNet.Register();
			JoinGate.WarnAboutOtherGates();
		}

		internal static void AnnounceJoin(int slot, bool playing)
		{
			if (slot >= 0)
			{
				announcements.Add((slot, playing, Time.time + 2.5f));
			}
		}

		private void Update()
		{
			if (Time.time >= nextLobbyCheck)
			{
				nextLobbyCheck = Time.time + 1f;
				JoinGate.UpdateLobby();
			}
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && JoinGate.Landed != wasLanded)
			{
				wasLanded = JoinGate.Landed;
				if (wasLanded)
				{
					Plugin.Logger.LogInfo((object)("Ship landed on " + StartOfRound.Instance.currentLevel.PlanetName + ": late joins are open."));
				}
			}
			LateJoiner.Tick();
			MonsterCatchUp.Tick();
			LateNet.Pump();
			for (int num = announcements.Count - 1; num >= 0; num--)
			{
				if (!(Time.time < announcements[num].at))
				{
					PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
					var (num2, flag, _) = announcements[num];
					announcements.RemoveAt(num);
					if (num2 < allPlayerScripts.Length && (Object)(object)HUDManager.Instance != (Object)null)
					{
						HUDManager.Instance.DisplayTip("Late Landing", flag ? (allPlayerScripts[num2].playerUsername + " joined and landed with the crew.") : (allPlayerScripts[num2].playerUsername + " landed late. They'll join in when the ship takes off."), false, false, "LC_Tip1");
					}
				}
			}
		}

		private void OnDestroy()
		{
			LateNet.Unregister();
			JoinGate.Reset();
			LateJoiner.Reset();
			MonsterCatchUp.Reset();
			announcements.Clear();
		}
	}
	internal static class MonsterCatchUp
	{
		private class Handler
		{
			public Action<EnemyAI, BinaryWriter> describe;

			public Action<EnemyAI, BinaryReader> apply;

			public bool early;
		}

		private const float PlantSizeScale = 7.75f;

		private static readonly Vector3 PlantMarkerOffset = Vector3.up * 1.1f;

		private const float PlantMarkerMatch = 0.3f;

		private const float FlowerGrowthsPerInfection = 8f;

		private const string DescribeHook = "LateLandingDescribe";

		private const string CatchUpHook = "LateLandingCatchUp";

		private static readonly Dictionary<Type, Handler> handlers = new Dictionary<Type, Handler>
		{
			[typeof(SpringManAI)] = new Handler
			{
				describe = DescribeCoilHead,
				apply = ApplyCoilHead
			},
			[typeof(MaskedPlayerEnemy)] = new Handler
			{
				describe = DescribeMasked,
				apply = ApplyMasked,
				early = true
			},
			[typeof(BushWolfEnemy)] = new Handler
			{
				describe = DescribeFox,
				apply = ApplyFox
			},
			[typeof(CrawlerAI)] = new Handler
			{
				describe = DescribeThumper,
				apply = ApplyThumper
			},
			[typeof(NutcrackerEnemyAI)] = new Handler
			{
				describe = DescribeNutcracker,
				apply = ApplyNutcracker,
				early = true
			},
			[typeof(HoarderBugAI)] = new Handler
			{
				describe = DescribeHoardingBug,
				apply = ApplyHoardingBug
			},
			[typeof(BaboonBirdAI)] = new Handler
			{
				describe = DescribeBaboonHawk,
				apply = ApplyBaboonHawk
			},
			[typeof(GiantKiwiAI)] = new Handler
			{
				describe = DescribeSapsucker,
				apply = ApplySapsucker
			},
			[typeof(CaveDwellerAI)] = new Handler
			{
				describe = DescribeManeater,
				apply = ApplyManeater,
				early = true
			},
			[typeof(RedLocustBees)] = new Handler
			{
				describe = DescribeBees,
				apply = ApplyBees
			},
			[typeof(ClaySurgeonAI)] = new Handler
			{
				describe = DescribeBarber,
				apply = ApplyBarber
			},
			[typeof(DressGirlAI)] = new Handler
			{
				describe = DescribeGhostGirl,
				apply = ApplyGhostGirl
			},
			[typeof(CentipedeAI)] = new Handler
			{
				describe = DescribeSnareFlea,
				apply = ApplySnareFlea
			},
			[typeof(ForestGiantAI)] = new Handler
			{
				describe = DescribeForestGiant,
				apply = ApplyForestGiant
			},
			[typeof(PumaAI)] = new Handler
			{
				describe = DescribeFeiopar,
				apply = ApplyFeiopar
			},
			[typeof(StingrayAI)] = new Handler
			{
				describe = DescribeStingray,
				apply = ApplyStingray
			},
			[typeof(MouthDogAI)] = new Handler
			{
				describe = DescribeDog,
				apply = ApplyDog,
				early = true
			},
			[typeof(RadMechAI)] = new Handler
			{
				describe = DescribeOldBird,
				apply = ApplyOldBird
			},
			[typeof(ButlerEnemyAI)] = new Handler
			{
				describe = DescribeButler,
				apply = ApplyButler
			},
			[typeof(FlowerSnakeEnemy)] = new Handler
			{
				describe = DescribeTulipSnake,
				apply = ApplyTulipSnake
			},
			[typeof(SandSpiderAI)] = new Handler
			{
				describe = DescribeSpider,
				apply = ApplySpider
			},
			[typeof(FlowermanAI)] = new Handler
			{
				describe = DescribeBracken,
				apply = ApplyBracken
			},
			[typeof(JesterAI)] = new Handler
			{
				describe = DescribeJester,
				apply = ApplyJester
			},
			[typeof(CadaverGrowthAI)] = new Handler
			{
				describe = DescribeCadaverGrowth,
				apply = ApplyCadaverGrowth
			},
			[typeof(CadaverBloomAI)] = new Handler
			{
				describe = DescribeCadaverBloom,
				apply = ApplyCadaverBloom,
				early = true
			}
		};

		private static readonly Dictionary<Type, (MethodInfo? describe, MethodInfo? apply)> hooks = new Dictionary<Type, (MethodInfo, MethodInfo)>();

		private const int FramesToLetStateStart = 2;

		private static readonly List<(int frame, string what, Action action)> later = new List<(int, string, Action)>();

		private static void DescribeCadaverGrowth(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: 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_0233: Unknown result type (might be due to invalid IL or missing references)
			CadaverGrowthAI val = (CadaverGrowthAI)e;
			Traverse val2 = Traverse.Create((object)e);
			ReadOnlyCollection<Tile> allTiles = RoundManager.Instance.dungeonGenerator.Generator.CurrentDungeon.AllTiles;
			w.Write(val.GrowthTiles.Count);
			foreach (TileWithGrowth growthTile in val.GrowthTiles)
			{
				w.Write(allTiles.IndexOf(growthTile.tile));
				Write(w, growthTile.lastPlantGrownPosition);
				w.Write(growthTile.eradicated);
				w.Write(growthTile.cannotSpread);
			}
			(int, int, int) value = val2.Field<(int, int, int)>("growingPlant").Value;
			float value2 = val2.Field<float>("recentPlantSizeTarget").Value;
			w.Write(val.plantBatchers.Length);
			for (int i = 0; i < val.plantBatchers.Length; i++)
			{
				BatchAllMeshChildren obj = val.plantBatchers[i];
				List<Matrix4x4> list = obj.Batches.SelectMany((List<Matrix4x4> b) => b).ToList();
				List<Vector3> list2 = obj.batchedPositions ?? new List<Vector3>();
				List<int> list3 = obj.batchedPositionTiles ?? new List<int>();
				int num = Mathf.Min(list.Count, Mathf.Min(list2.Count, list3.Count));
				w.Write(num);
				for (int num2 = 0; num2 < num; num2++)
				{
					int num3 = list3[num2];
					bool flag = val.growingRecentPlant && value.Item3 == i && value.Item1 * 1000 + value.Item2 == num2;
					w.Write(num3);
					Write(w, list2[num2]);
					Matrix4x4 val3 = list[num2];
					Quaternion rotation = ((Matrix4x4)(ref val3)).rotation;
					w.Write(rotation.x);
					w.Write(rotation.y);
					w.Write(rotation.z);
					w.Write(rotation.w);
					float num4;
					if (!flag)
					{
						val3 = list[num2];
						num4 = ((Matrix4x4)(ref val3)).lossyScale.x;
					}
					else
					{
						num4 = value2;
					}
					w.Write(num4 / 7.75f);
					var (value3, value4) = PlantMarkers(val, num3, list2[num2]);
					w.Write(value3);
					w.Write(value4);
				}
			}
			w.Write(val.playerInfections.Length);
			for (int num5 = 0; num5 < val.playerInfections.Length; num5++)
			{
				PlayerInfection val4 = val.playerInfections[num5];
				w.Write(val4.infected);
				w.Write(val4.severe);
				w.Write(val4.emittingSpores);
				w.Write(val4.bloomOnDeath);
				w.Write(val4.infectionMeter);
				bool flag2 = (Object)(object)Player(num5) == (Object)(object)GameNetworkManager.Instance.localPlayerController;
				w.Write((flag2 && val4.infected) ? (-1) : (val4.backFlowerRenderers?.Count((MeshRenderer r) => (Object)(object)r != (Object)null && ((Renderer)r).enabled) ?? 0));
			}
			w.Write(val.bloomEnemies.Length);
			CadaverBloomAI[] bloomEnemies = val.bloomEnemies;
			foreach (CadaverBloomAI c in bloomEnemies)
			{
				WriteObject(w, (Component?)(object)c);
			}
		}

		private static (bool scan, bool decal) PlantMarkers(CadaverGrowthAI growth, int tileIndex, Vector3 plant)
		{
			//IL_003c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//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)
			bool item = false;
			bool item2 = false;
			GameObject val = ((tileIndex >= 0 && tileIndex < growth.GrowthTiles.Count) ? growth.GrowthTiles[tileIndex].scanNodesContainer : null);
			if ((Object)(object)val == (Object)null)
			{
				return (scan: false, decal: false);
			}
			Vector3 val2 = plant + PlantMarkerOffset;
			foreach (Transform item3 in val.transform)
			{
				Transform val3 = item3;
				if (!(Vector3.Distance(val3.position, val2) > 0.3f))
				{
					if ((Object)(object)((Component)val3).GetComponent<ScanNodeProperties>() != (Object)null)
					{
						item = true;
					}
					else
					{
						item2 = true;
					}
				}
			}
			return (scan: item, decal: item2);
		}

		private static void ApplyCadaverGrowth(EnemyAI e, BinaryReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Expected O, but got Unknown
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			CadaverGrowthAI growth = (CadaverGrowthAI)e;
			Traverse val = Traverse.Create((object)e);
			ReadOnlyCollection<Tile> allTiles = RoundManager.Instance.dungeonGenerator.Generator.CurrentDungeon.AllTiles;
			foreach (TileWithGrowth growthTile in growth.GrowthTiles)
			{
				GameObject[] array = (GameObject[])(object)new GameObject[4] { growthTile.plantsContainer, growthTile.particlesContainer, growthTile.scanNodesContainer, growthTile.decalsContainer };
				foreach (GameObject val2 in array)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						Object.Destroy((Object)(object)val2);
					}
				}
			}
			growth.GrowthTiles.Clear();
			BatchAllMeshChildren[] plantBatchers = growth.plantBatchers;
			foreach (BatchAllMeshChildren obj in plantBatchers)
			{
				obj.Batches.Clear();
				obj.batchedPositions = new List<Vector3>();
				obj.batchedPositionTiles = new List<int>();
				obj.amountOfMatrices = 0;
			}
			growth.growingRecentPlant = false;
			val.Field<(int, int, int)>("growingPlant").Value = (-1, -1, -1);
			int num = r.ReadInt32();
			for (int j = 0; j < num; j++)
			{
				int num2 = r.ReadInt32();
				Vector3 val3 = ReadVector(r);
				bool eradicated = r.ReadBoolean();
				bool cannotSpread = r.ReadBoolean();
				if (num2 < 0 || num2 >= allTiles.Count)
				{
					throw new InvalidDataException($"room {num2} isn't in this facility");
				}
				growth.GrowthTiles.Add(new TileWithGrowth(allTiles[num2], growth.TileCapacity, growth.CaveTileTag, growth.RoomTileTag, growth.TunnelTileTag, val3)
				{
					eradicated = eradicated,
					cannotSpread = cannotSpread
				});
			}
			growth.plantAudio.mute = true;
			int num3 = r.ReadInt32();
			int num4 = 0;
			for (int k = 0; k < num3; k++)
			{
				int num5 = r.ReadInt32();
				for (int l = 0; l < num5; l++)
				{
					int tileIndex = r.ReadInt32();
					Vector3 position = ReadVector(r);
					Quaternion rotation = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
					float size = r.ReadSingle();
					bool scan = r.ReadBoolean();
					bool decal = r.ReadBoolean();
					if (k < growth.plantBatchers.Length && tileIndex < growth.GrowthTiles.Count)
					{
						int plantType = k;
						MoonRebuild.RunAsReceived((NetworkBehaviour)(object)growth, delegate
						{
							//IL_0018: 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)
							growth.SyncSpawnPlantRpc(plantType, tileIndex, position, rotation, size, scan, decal);
						});
						num4++;
					}
				}
			}
			if (num4 > 0)
			{
				AccessTools.Method(typeof(CadaverGrowthAI), "QuickFinishGrowingPlant", (Type[])null, (Type[])null).Invoke(growth, null);
			}
			Later("the Cadaver plants' sound", delegate
			{
				growth.plantAudio.mute = false;
			});
			int num6 = r.ReadInt32();
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			for (int num7 = 0; num7 < num6; num7++)
			{
				bool num8 = r.ReadBoolean();
				bool flag = r.ReadBoolean();
				bool flag2 = r.ReadBoolean();
				bool bloomOnDeath = r.ReadBoolean();
				float num9 = r.ReadSingle();
				int num10 = r.ReadInt32();
				PlayerControllerB val4 = Player(num7);
				if (!num8 || (Object)(object)val4 == (Object)null || (Object)(object)val4 == (Object)(object)localPlayerController || num7 >= growth.playerInfections.Length)
				{
					continue;
				}
				growth.InfectPlayer(val4, flag, flag2);
				PlayerInfection val5 = growth.playerInfections[num7];
				val5.infectionMeter = num9;
				val5.bloomOnDeath = bloomOnDeath;
				MethodInfo methodInfo = AccessTools.Method(typeof(CadaverGrowthAI), "IncreaseBackFlowers", (Type[])null, (Type[])null);
				if (num10 < 0)
				{
					for (int num11 = 0; num11 < Mathf.CeilToInt(num9 * 8f); num11++)
					{
						methodInfo.Invoke(growth, new object[1] { num7 });
					}
				}
				else if (num10 > 0)
				{
					methodInfo.Invoke(growth, new object[1] { num7 });
					int num12 = 0;
					while (val5.backFlowerRenderers != null && num12 < val5.backFlowerRenderers.Length)
					{
						((Renderer)val5.backFlowerRenderers[num12]).enabled = num12 < num10;
						num12++;
					}
				}
			}
			int num13 = r.ReadInt32();
			CadaverBloomAI[] array2 = (CadaverBloomAI[])(object)new CadaverBloomAI[growth.bloomEnemies.Length];
			for (int num14 = 0; num14 < num13; num14++)
			{
				NetworkObject? obj2 = ReadObject(r);
				CadaverBloomAI val6 = ((obj2 != null) ? ((Component)obj2).GetComponent<CadaverBloomAI>() : null);
				if (num14 < array2.Length)
				{
					array2[num14] = val6;
				}
			}
			growth.bloomEnemies = array2;
		}

		private static void DescribeCadaverBloom(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			CadaverBloomAI val = (CadaverBloomAI)e;
			w.Write(val.hasBurst);
			w.Write(Slot(val.burstPlayer));
			w.Write(e.isEnemyDead);
		}

		private static void ApplyCadaverBloom(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0056: 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)
			CadaverBloomAI val = (CadaverBloomAI)e;
			bool num = r.ReadBoolean();
			PlayerControllerB val2 = Player(r.ReadInt32());
			bool flag = r.ReadBoolean();
			if (num && !((Object)(object)val2 == (Object)null) && !val.hasBurst)
			{
				if (flag)
				{
					val.burstPlayer = val2;
					val.hasBurst = true;
					val2.redirectToEnemy = (EnemyAI)(object)val;
				}
				else
				{
					val.BurstForth(val2, false, ((Component)val).transform.position, ((Component)val).transform.eulerAngles);
				}
			}
		}

		internal static byte[]? Describe(EnemyAI enemy)
		{
			Type type = ((object)enemy).GetType();
			if (handlers.TryGetValue(type, out Handler value))
			{
				using (MemoryStream memoryStream = new MemoryStream())
				{
					using (BinaryWriter arg = new BinaryWriter(memoryStream))
					{
						value.describe(enemy, arg);
					}
					return memoryStream.ToArray();
				}
			}
			MethodInfo item = Hooks(type).describe;
			if (!(item != null))
			{
				return null;
			}
			return item.Invoke(enemy, null) as byte[];
		}

		internal static void Apply(EnemyAI enemy, byte[] data, bool early)
		{
			Type type = ((object)enemy).GetType();
			if (handlers.TryGetValue(type, out Handler value))
			{
				if (value.early == early)
				{
					using (BinaryReader arg = new BinaryReader(new MemoryStream(data)))
					{
						value.apply(enemy, arg);
					}
				}
			}
			else if (!early)
			{
				Hooks(type).apply?.Invoke(enemy, new object[1] { data });
			}
		}

		private static (MethodInfo? describe, MethodInfo? apply) Hooks(Type type)
		{
			if (!hooks.TryGetValue(type, out (MethodInfo, MethodInfo) value))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "LateLandingDescribe", Type.EmptyTypes, (Type[])null);
				MethodInfo item = AccessTools.Method(type, "LateLandingCatchUp", new Type[1] { typeof(byte[]) }, (Type[])null);
				value = ((methodInfo != null && methodInfo.ReturnType == typeof(byte[])) ? methodInfo : null, item);
				hooks[type] = value;
				if (value.Item1 != null && value.Item2 != null)
				{
					Plugin.Logger.LogInfo((object)(type.Name + " catches late joiners up itself."));
				}
			}
			return value;
		}

		private static void DescribeCoilHead(EnemyAI e, BinaryWriter w)
		{
			Traverse val = Traverse.Create((object)e);
			w.Write(val.Field<bool>("stoppingMovement").Value);
			w.Write(val.Field<bool>("setOnCooldown").Value);
			w.Write(val.Field<float>("onCooldownPhase").Value);
		}

		private static void ApplyCoilHead(EnemyAI e, BinaryReader r)
		{
			Traverse val = Traverse.Create((object)e);
			val.Field<bool>("stoppingMovement").Value = r.ReadBoolean();
			bool num = r.ReadBoolean();
			float value = r.ReadSingle();
			if (num)
			{
				val.Field<bool>("setOnCooldown").Value = true;
				val.Field<bool>("inCooldownAnimation").Value = true;
				val.Field<float>("onCooldownPhase").Value = value;
			}
		}

		private static void DescribeMasked(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			MaskedPlayerEnemy val = (MaskedPlayerEnemy)e;
			w.Write(val.allowSpawningWithoutPlayer);
			w.Write(((Object)(object)val.mimickingPlayer != (Object)null) ? ((int)val.mimickingPlayer.playerClientId) : (-1));
			w.Write(((Object)(object)val.mimickingPlayer != (Object)null) ? val.mimickingPlayer.currentSuitID : 0);
			w.Write((Traverse.Create((object)val).Field<int>("maskTypeIndex").Value == 1) ? 5 : 4);
			Traverse val2 = Traverse.Create((object)val);
			w.Write(val2.Field<bool>("crouching").Value);
			w.Write(val2.Field<bool>("handsOut").Value);
			w.Write(val2.Field<bool>("running").Value);
			Transform stareAtTransform = val.stareAtTransform;
			w.Write(((Object)(object)stareAtTransform != (Object)null) ? Slot(((Component)stareAtTransform).GetComponentInParent<PlayerControllerB>()) : (-1));
		}

		private static void ApplyMasked(EnemyAI e, BinaryReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			MaskedPlayerEnemy masked = (MaskedPlayerEnemy)e;
			masked.allowSpawningWithoutPlayer = r.ReadBoolean();
			int num = r.ReadInt32();
			int suit = r.ReadInt32();
			int maskType = r.ReadInt32();
			if (num >= 0 && num < StartOfRound.Instance.allPlayerScripts.Length)
			{
				PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[num];
				masked.mimickingPlayer = val;
				masked.SetSuit(suit);
				masked.SetMaskType(maskType);
				val.redirectToEnemy = (EnemyAI)(object)masked;
			}
			masked.SetVisibilityOfMaskedEnemy();
			bool crouch = r.ReadBoolean();
			bool hands = r.ReadBoolean();
			bool run = r.ReadBoolean();
			PlayerControllerB watched = Player(r.ReadInt32());
			Later("the Masked's pose", delegate
			{
				Traverse obj = Traverse.Create((object)masked);
				obj.Field<bool>("crouching").Value = crouch;
				((EnemyAI)masked).creatureAnimator.SetBool("Crouching", crouch);
				obj.Field<bool>("handsOut").Value = hands;
				((EnemyAI)masked).creatureAnimator.SetBool("HandsOut", hands);
				obj.Field<bool>("running").Value = run;
				((EnemyAI)masked).creatureAnimator.SetBool("Running", run);
				masked.stareAtTransform = (((Object)(object)watched != (Object)null) ? ((Component)watched.gameplayCamera).transform : null);
			});
		}

		private static void DescribeFox(EnemyAI e, BinaryWriter w)
		{
			//IL_0013: 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_003f: 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_0050: Expected O, but got Unknown
			Traverse val = Traverse.Create((object)e);
			Write(w, val.Field<Vector3>("mostHiddenPosition").Value);
			Write(w, val.Field<Vector3>("aggressivePosition").Value);
			Write(w, val.Field<Vector3>("currentHidingSpot").Value);
			BushWolfEnemy val2 = (BushWolfEnemy)e;
			w.Write(val2.nestRange);
			w.Write(val.Field<float>("baseNestRange").Value);
		}

		private static void ApplyFox(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0014: 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_0025: 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_0054: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ReadVector(r);
			Vector3 value = ReadVector(r);
			Vector3 value2 = ReadVector(r);
			float nestRange = r.ReadSingle();
			float value3 = r.ReadSingle();
			if (!(val == Vector3.zero))
			{
				Traverse obj = Traverse.Create((object)e);
				obj.Field<Vector3>("mostHiddenPosition").Value = val;
				obj.Field<Vector3>("aggressivePosition").Value = value;
				obj.Field<Vector3>("currentHidingSpot").Value = value2;
				((BushWolfEnemy)e).nestRange = nestRange;
				obj.Field<float>("baseNestRange").Value = value3;
			}
		}

		private static void DescribeThumper(EnemyAI e, BinaryWriter w)
		{
			w.Write((e.movingTowardsTargetPlayer && (Object)(object)e.targetPlayer != (Object)null) ? ((int)e.targetPlayer.playerClientId) : (-1));
		}

		private static void ApplyThumper(EnemyAI e, BinaryReader r)
		{
			int num = r.ReadInt32();
			if (num >= 0 && num < StartOfRound.Instance.allPlayerScripts.Length)
			{
				e.SetMovingTowardsTargetPlayer(StartOfRound.Instance.allPlayerScripts[num]);
			}
		}

		private static void DescribeNutcracker(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			NutcrackerEnemyAI val = (NutcrackerEnemyAI)e;
			Traverse val2 = Traverse.Create((object)e);
			w.Write(e.isEnemyDead);
			WriteObject(w, (Component?)(object)val.gun);
			w.Write((Object)(object)val.gun != (Object)null && (Object)(object)((GrabbableObject)val.gun).parentObject == (Object)(object)val.gunPoint);
			w.Write(((Object)(object)val.gun != (Object)null) ? val.gun.shellsLoaded : 0);
			w.Write(val2.Field<int>("randomSeedNumber").Value);
			w.Write(val2.Field<int>("timesDoingInspection").Value);
			w.Write(val.lastPlayerSeenMoving);
			w.Write(val2.Field<bool>("lostPlayerInChase").Value);
			w.Write(e.currentBehaviourStateIndex == 1);
		}

		private static void ApplyNutcracker(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			NutcrackerEnemyAI val = (NutcrackerEnemyAI)e;
			Traverse val2 = Traverse.Create((object)e);
			bool flag = r.ReadBoolean();
			NetworkObject val3 = ReadObject(r);
			bool flag2 = r.ReadBoolean();
			int shellsLoaded = r.ReadInt32();
			val2.Field<int>("randomSeedNumber").Value = r.ReadInt32();
			int value = r.ReadInt32();
			int num = r.ReadInt32();
			bool value2 = r.ReadBoolean();
			val2.Field<int>("timesDoingInspection").Value = value;
			if (r.ReadBoolean())
			{
				val2.Field<int>("previousBehaviourState").Value = 1;
			}
			ShotgunItem val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<ShotgunItem>() : null);
			if ((Object)(object)val4 != (Object)null)
			{
				val2.Field<NetworkObjectReference>("gunObjectRef").Value = new NetworkObjectReference(val3);
				if (flag)
				{
					val.gun = val4;
					if (flag2)
					{
						((GrabbableObject)val4).parentObject = val.gunPoint;
						((GrabbableObject)val4).isHeldByEnemy = false;
						((GrabbableObject)val4).grabbable = true;
						((GrabbableObject)val4).grabbableToEnemies = true;
					}
				}
				else
				{
					AccessTools.Method(typeof(NutcrackerEnemyAI), "GrabGun", (Type[])null, (Type[])null).Invoke(val, new object[1] { ((Component)val4).gameObject });
					val4.shellsLoaded = shellsLoaded;
				}
			}
			if (num >= 0 && num < StartOfRound.Instance.allPlayerScripts.Length)
			{
				AccessTools.Method(typeof(NutcrackerEnemyAI), "SwitchTargetToPlayer", (Type[])null, (Type[])null).Invoke(val, new object[1] { num });
			}
			val2.Field<bool>("lostPlayerInChase").Value = value2;
		}

		private static void DescribeHoardingBug(EnemyAI e, BinaryWriter w)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected I4, but got Unknown
			HoarderBugAI bug = (HoarderBugAI)e;
			Write(w, bug.nestPosition);
			GrabbableObject c = bug.heldItem?.itemGrabbableObject;
			WriteObject(w, (Component?)(object)c);
			List<HoarderBugItem> list = HoarderBugAI.HoarderBugItems.Where((HoarderBugItem i) => i != null && (Object)(object)i.itemGrabbableObject != (Object)null && i.itemNestPosition == bug.nestPosition).ToList();
			if (bug.heldItem != null)
			{
				list.Remove(bug.heldItem);
			}
			w.Write(list.Count);
			foreach (HoarderBugItem item in list)
			{
				WriteObject(w, (Component?)(object)item.itemGrabbableObject);
				w.Write((int)item.status);
			}
		}

		private static void ApplyHoardingBug(EnemyAI e, BinaryReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			HoarderBugAI bug = (HoarderBugAI)e;
			bug.nestPosition = ReadVector(r);
			NetworkObject val = ReadObject(r);
			HoarderBugAI.HoarderBugItems.RemoveAll((HoarderBugItem i) => i == null || (Object)(object)i.itemGrabbableObject == (Object)null || i.itemNestPosition == bug.nestPosition);
			int num = r.ReadInt32();
			for (int num2 = 0; num2 < num; num2++)
			{
				NetworkObject val2 = ReadObject(r);
				HoarderBugItemStatus val3 = (HoarderBugItemStatus)r.ReadInt32();
				GrabbableObject val4 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<GrabbableObject>() : null);
				if ((Object)(object)val4 != (Object)null)
				{
					HoarderBugAI.HoarderBugItems.Add(new HoarderBugItem(val4, val3, bug.nestPosition));
				}
			}
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<GrabbableObject>() != (Object)null)
			{
				AccessTools.Method(typeof(HoarderBugAI), "GrabItem", (Type[])null, (Type[])null).Invoke(bug, new object[1] { val });
			}
		}

		private static void DescribeBaboonHawk(EnemyAI e, BinaryWriter w)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			WriteObject(w, (Component?)(object)((BaboonBirdAI)e).heldScrap);
			Traverse val = Traverse.Create((object)e);
			w.Write(val.Field<int>("aggressiveMode").Value);
			w.Write(e.creatureAnimator.GetBool("sit") || e.creatureAnimator.GetBool("sleep"));
			w.Write(val.Field<bool>("eyesClosed").Value);
			w.Write(val.Field<bool>("restingAtCamp").Value);
		}

		private static void ApplyBaboonHawk(EnemyAI e, BinaryReader r)
		{
			NetworkObject val = ReadObject(r);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<GrabbableObject>() != (Object)null)
			{
				AccessTools.Method(typeof(BaboonBirdAI), "GrabScrap", (Type[])null, (Type[])null).Invoke(e, new object[1] { val });
			}
			Traverse val2 = Traverse.Create((object)e);
			val2.Field<int>("aggressiveMode").Value = r.ReadInt32();
			bool num = r.ReadBoolean();
			bool flag = r.ReadBoolean();
			bool value = r.ReadBoolean();
			if (num)
			{
				val2.Field<bool>("restingAtCamp").Value = value;
				val2.Field<bool>("eyesClosed").Value = flag;
				e.creatureAnimator.SetBool("sleep", flag);
				e.creatureAnimator.SetBool("sit", !flag);
			}
		}

		private static void DescribeSapsucker(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GiantKiwiAI val = (GiantKiwiAI)e;
			Traverse val2 = Traverse.Create((object)e);
			w.Write(val2.Field<bool>("hasSpawnedEggs").Value);
			List<KiwiBabyItem> list = val.eggs.Where((KiwiBabyItem egg) => (Object)(object)egg != (Object)null).ToList();
			w.Write(list.Count);
			foreach (KiwiBabyItem item in list)
			{
				WriteObject(w, (Component?)(object)item);
			}
			KiwiBabyItem value = val2.Field<KiwiBabyItem>("takeEggBackToNest").Value;
			WriteObject(w, (Component?)(object)(val.carryingEgg ? value : null));
			IVisibleThreat value2 = val2.Field<IVisibleThreat>("attackingThreat").Value;
			WriteObject(w, (Component?)(object)((value2 is Component) ? value2 : null));
			IVisibleThreat value3 = val2.Field<IVisibleThreat>("watchingThreat").Value;
			WriteObject(w, (Component?)(object)((value3 is Component) ? value3 : null));
			w.Write(Slot(((EnemyAI)val).targetPlayer));
			w.Write(Slot(val.abandonedThreat));
			int[] array = (from tr in val2.Field<List<Transform>>("seenThreatsHoldingEgg").Value
				select (!((Object)(object)tr != (Object)null)) ? (-1) : Slot(((Component)tr).GetComponentInParent<PlayerControllerB>()) into i
				where i >= 0
				select i).ToArray();
			w.Write(array.Length);
			int[] array2 = array;
			foreach (int value4 in array2)
			{
				w.Write(value4);
			}
			w.Write(val2.Field<int>("idleBehaviour").Value);
			w.Write(e.creatureAnimator.GetBool("Asleep"));
			w.Write(val2.Field<bool>("isPeckingTree").Value);
		}

		private static void ApplySapsucker(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GiantKiwiAI val = (GiantKiwiAI)e;
			Traverse.Create((object)e).Field<bool>("hasSpawnedEggs").Value = r.ReadBoolean();
			int num = r.ReadInt32();
			val.eggs.Clear();
			for (int i = 0; i < num; i++)
			{
				NetworkObject? obj = ReadObject(r);
				KiwiBabyItem val2 = ((obj != null) ? ((Component)obj).GetComponent<KiwiBabyItem>() : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					val.eggs.Add(val2);
					ScanNodeProperties componentInChildren = ((Component)val2).GetComponentInChildren<ScanNodeProperties>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.headerText = "Egg";
					}
				}
			}
			NetworkObject val3 = ReadObject(r);
			if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).GetComponent<KiwiBabyItem>() != (Object)null)
			{
				AccessTools.Method(typeof(GiantKiwiAI), "GrabScrap", (Type[])null, (Type[])null).Invoke(val, new object[1] { val3 });
			}
			Traverse val4 = Traverse.Create((object)e);
			NetworkObject val5 = ReadObject(r);
			NetworkObject val6 = ReadObject(r);
			IVisibleThreat value = default(IVisibleThreat);
			if ((Object)(object)val5 != (Object)null && ((Component)val5).TryGetComponent<IVisibleThreat>(ref value))
			{
				val4.Field<IVisibleThreat>("attackingThreat").Value = value;
			}
			IVisibleThreat value2 = default(IVisibleThreat);
			if ((Object)(object)val6 != (Object)null && ((Component)val6).TryGetComponent<IVisibleThreat>(ref value2))
			{
				val4.Field<IVisibleThreat>("watchingThreat").Value = value2;
			}
			((EnemyAI)val).targetPlayer = Player(r.ReadInt32());
			val.abandonedThreat = Player(r.ReadInt32());
			int[] array = new int[r.ReadInt32()];
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = r.ReadInt32();
			}
			if (array.Length != 0)
			{
				AccessTools.Method(typeof(GiantKiwiAI), "AddPlayerIDsToSeenThreatsHoldingEggsList", (Type[])null, (Type[])null).Invoke(val, new object[1] { array });
			}
			val4.Field<int>("idleBehaviour").Value = r.ReadInt32();
			if (r.ReadBoolean())
			{
				((EnemyAI)val).creatureSFX.Play();
				((EnemyAI)val).creatureAnimator.SetBool("Asleep", true);
			}
			bool flag = r.ReadBoolean();
			val4.Field<bool>("isPeckingTree").Value = flag;
			((EnemyAI)val).creatureAnimator.SetBool("peckTree", flag);
		}

		private static void DescribeManeater(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0037: 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)
			CaveDwellerAI val = (CaveDwellerAI)e;
			Traverse val2 = Traverse.Create((object)e);
			w.Write(val.adultContainer.activeSelf);
			w.Write(val.leapSpeed);
			Write(w, val2.Field<Vector3>("caveHidingSpot").Value);
			w.Write(val2.Field<bool>("isFakingBabyVoice").Value);
			w.Write(val2.Field<bool>("clickingMandibles").Value);
			w.Write(val2.Field<bool>("chasingAfterLeap").Value);
			w.Write(val.babyCrying);
			w.Write(val.rolledOver);
			w.Write(val2.Field<int>("scrapEaten").Value);
			Write(w, val.spine2.localScale);
		}

		private static void ApplyManeater(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_01dd: Unknown result type (might be due to invalid IL or missing references)
			CaveDwellerAI val = (CaveDwellerAI)e;
			Traverse val2 = Traverse.Create((object)e);
			bool flag = r.ReadBoolean();
			if (flag && !val.adultContainer.activeSelf)
			{
				((EnemyAI)val).agent.acceleration = 425f;
				((EnemyAI)val).agent.angularSpeed = 700f;
				((EnemyAI)val).syncMovementSpeed = 0.15f;
				((EnemyAI)val).addPlayerVelocityToDestination = 1f;
				((EnemyAI)val).updatePositionThreshold = 0.8f;
				((GrabbableObject)val.propScript).EnablePhysics(false);
				((GrabbableObject)val.propScript).grabbable = false;
				((GrabbableObject)val.propScript).grabbableToEnemies = false;
				((Behaviour)val.propScript).enabled = false;
				val.babyContainer.SetActive(false);
				val.adultContainer.SetActive(true);
			}
			val.leapSpeed = r.ReadSingle();
			val2.Field<Vector3>("caveHidingSpot").Value = ReadVector(r);
			val2.Field<bool>("isFakingBabyVoice").Value = r.ReadBoolean();
			val2.Field<bool>("clickingMandibles").Value = r.ReadBoolean();
			bool flag2 = r.ReadBoolean();
			val2.Field<bool>("chasingAfterLeap").Value = flag2;
			if (flag2)
			{
				((EnemyAI)val).syncMovementSpeed = 0.2f;
			}
			bool flag3 = r.ReadBoolean();
			bool flag4 = r.ReadBoolean();
			int value = r.ReadInt32();
			Vector3 localScale = ReadVector(r);
			if (!flag)
			{
				if (flag3 != val.babyCrying)
				{
					AccessTools.Method(typeof(CaveDwellerAI), "SetCryingLocalClient", (Type[])null, (Type[])null).Invoke(val, new object[1] { flag3 });
				}
				if (flag4 != val.rolledOver)
				{
					AccessTools.Method(typeof(CaveDwellerAI), "SetRolledOverLocalClient", (Type[])null, (Type[])null).Invoke(val, new object[2] { flag4, false });
				}
				val2.Field<int>("scrapEaten").Value = value;
				val.spine2.localScale = localScale;
			}
			else
			{
				val.babyCrying = flag3;
			}
		}

		private static void DescribeBees(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			RedLocustBees val = (RedLocustBees)e;
			Traverse val2 = Traverse.Create((object)e);
			WriteObject(w, (Component?)(object)(val2.Field<bool>("hasSpawnedHive").Value ? val.hive : null));
			Write(w, val.lastKnownHivePosition);
			w.Write(val2.Field<bool>("syncedLastKnownHivePosition").Value);
		}

		private static void ApplyBees(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			RedLocustBees val = (RedLocustBees)e;
			Traverse val2 = Traverse.Create((object)e);
			NetworkObject? obj = ReadObject(r);
			GrabbableObject val3 = ((obj != null) ? ((Component)obj).GetComponent<GrabbableObject>() : null);
			val.lastKnownHivePosition = ReadVector(r);
			val2.Field<bool>("syncedLastKnownHivePosition").Value = r.ReadBoolean();
			if ((Object)(object)val3 != (Object)null)
			{
				val.hive = val3;
				ScanNodeProperties componentInChildren = ((Component)val3).GetComponentInChildren<ScanNodeProperties>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.headerText = "Bee hive";
				}
				val2.Field<bool>("hasSpawnedHive").Value = true;
			}
		}

		private static void DescribeBarber(EnemyAI e, BinaryWriter w)
		{
			w.Write(Traverse.Create((object)e).Field<bool>("isMaster").Value);
		}

		private static void ApplyBarber(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ClaySurgeonAI val = (ClaySurgeonAI)e;
			if (r.ReadBoolean() && (Object)(object)val.master == (Object)null)
			{
				MoonRebuild.RunAsReceived((NetworkBehaviour)(object)val, (Action)val.SyncMasterClaySurgeonClientRpc);
			}
		}

		private static void DescribeGhostGirl(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			DressGirlAI val = (DressGirlAI)e;
			w.Write(Slot(val.hauntingPlayer));
			w.Write(Traverse.Create((object)e).Field<int>("timesChoosingAPlayer").Value);
		}

		private static void ApplyGhostGirl(EnemyAI e, BinaryReader r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			DressGirlAI val = (DressGirlAI)e;
			PlayerControllerB val2 = Player(r.ReadInt32());
			Traverse.Create((object)e).Field<int>("timesChoosingAPlayer").Value = r.ReadInt32();
			if ((Object)(object)val2 != (Object)null)
			{
				val.hauntingPlayer = val2;
				val.hauntingLocalPlayer = (Object)(object)val2 == (Object)(object)GameNetworkManager.Instance.localPlayerController;
			}
		}

		private static void DescribeSnareFlea(EnemyAI e, BinaryWriter w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			CentipedeAI val = (CentipedeAI)e;
			w.Write(e.currentBehaviourStateIndex);
			Write(w, val.ceilingHidingPoint);
			w.Write(Slot(val.clingingToPlayer));
		}

		private static void ApplySnareFlea(EnemyAI e, BinaryReader r)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//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_0038: 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_005d: 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)
			CentipedeAI flea = (CentipedeAI)e;
			int num = r.ReadInt32();
			Vector3 ceiling = ReadVector(r);
			PlayerControllerB val = Player(r.ReadInt32());
			flea.ceilingHidingPoint = ceiling;
			if ((Object)(object)val != (Object)null)
			{
				ClingToPlayer(flea, val);
			}
			else if (num == 1 && ceiling != Vector3.zero)
			{
				MoonRebuild.RunAsReceived((NetworkBehaviour)(object)flea, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					flea.SwitchToHidingOnCeilingClientRpc(ceiling);
				});
			}
		}

		private static void ClingToPlayer(CentipedeAI flea, PlayerControllerB victim)
		{
			Traverse val = Traverse.Create((object)flea);
			Coroutine value = val.Field<Coroutine>("ceilingAnimationCoroutine").Value;
			if (value != null)
			{
				((MonoBehaviour)flea).StopCoroutine(value);
				val.Field<Coroutine>("ceilingAnimationCoroutine").Value = null;
			}
			val.Field<bool>("startedCeilingAnimationCoroutine").Value = false;
			val.Field<bool>("clingingToCeiling").Value = false;
			val.Fi