Decompiled source of UFO Storage Manager v1.0.0

UFOStorageManager.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[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("UFOStorageManager")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UFOStorageManager")]
[assembly: AssemblyTitle("UFOStorageManager")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UFOStorageManager
{
	internal static class DefaultPosition
	{
		private static readonly string[] SaveKeys = new string[3] { "ShipUnlockMoved_", "ShipUnlockPos_", "ShipUnlockRot_" };

		internal static void Prepare(int unlockableId)
		{
			ResetLocal(unlockableId);
			DeleteSavedPosition(unlockableId);
			StorageNetwork.BroadcastResetDefault(unlockableId);
		}

		internal static void ResetLocal(int unlockableId)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			List<UnlockableItem> unlockables = StorageData.Unlockables;
			if (unlockables == null || unlockableId < 0 || unlockableId >= unlockables.Count)
			{
				return;
			}
			UnlockableItem val = unlockables[unlockableId];
			PlaceableShipObject val2 = Find(unlockableId);
			if ((Object)(object)val2 != (Object)null)
			{
				if (!val.spawnPrefab)
				{
					if ((Object)(object)ShipBuildModeManager.Instance != (Object)null)
					{
						ShipBuildModeManager.Instance.ResetShipObjectToDefaultPosition(val2);
					}
				}
				else
				{
					MoveToPrefabDefault(val, val2);
				}
			}
			val.placedPosition = Vector3.zero;
			val.placedRotation = Vector3.zero;
			val.hasBeenMoved = false;
		}

		private static void MoveToPrefabDefault(UnlockableItem item, PlaceableShipObject placeable)
		{
			//IL_0045: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			AutoParentToShip val = (((Object)(object)item.prefabObject != (Object)null) ? item.prefabObject.GetComponentInChildren<AutoParentToShip>(true) : null);
			if (!((Object)(object)val == (Object)null) && val.overrideOffset && !((Object)(object)placeable.parentObjectSecondary != (Object)null))
			{
				placeable.parentObject.positionOffset = val.positionOffset;
				placeable.parentObject.rotationOffset = val.rotationOffset;
				placeable.parentObject.MoveToOffset();
			}
		}

		private static PlaceableShipObject Find(int unlockableId)
		{
			PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>();
			foreach (PlaceableShipObject val in array)
			{
				if ((Object)(object)val != (Object)null && val.unlockableID == unlockableId && (Object)(object)val.parentObject != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static void DeleteSavedPosition(int unlockableId)
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			List<UnlockableItem> unlockables = StorageData.Unlockables;
			if ((Object)(object)instance == (Object)null || string.IsNullOrEmpty(instance.currentSaveFileName) || unlockables == null)
			{
				return;
			}
			string unlockableName = unlockables[unlockableId].unlockableName;
			try
			{
				string[] saveKeys = SaveKeys;
				foreach (string text in saveKeys)
				{
					if (ES3.KeyExists(text + unlockableName, instance.currentSaveFileName))
					{
						ES3.DeleteKey(text + unlockableName, instance.currentSaveFileName);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not clear the saved position of " + unlockableName + ": " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		private static bool ParsePlayerSentencePrefix(Terminal __instance, ref TerminalNode __result)
		{
			if ((Object)(object)__instance.screenText == (Object)null)
			{
				return true;
			}
			string text = __instance.screenText.text ?? "";
			int textAdded = __instance.textAdded;
			if (textAdded <= 0 || textAdded > text.Length)
			{
				return true;
			}
			try
			{
				if (StorageMenu.TryHandle(__instance, text.Substring(text.Length - textAdded), out var result))
				{
					__result = result;
					return false;
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Storage menu error: {arg}");
				StorageMenu.Reset();
			}
			return true;
		}

		[HarmonyPatch(typeof(Terminal), "QuitTerminal")]
		[HarmonyPostfix]
		private static void QuitTerminalPostfix()
		{
			StorageMenu.Reset();
		}

		[HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")]
		[HarmonyPrefix]
		private static void BeginUsingTerminalPrefix()
		{
			StorageMenu.Reset();
		}

		[HarmonyPatch(typeof(ShipBuildModeManager), "StoreObjectLocalClient")]
		[HarmonyPrefix]
		private static bool StoreObjectLocalClientPrefix(ShipBuildModeManager __instance, PlaceableShipObject ___placingObject, float ___timeSincePlacingObject)
		{
			if (!__instance.InBuildMode || (Object)(object)___placingObject == (Object)null || ___timeSincePlacingObject <= 0.25f || !StorageNetwork.LimitBuildMode)
			{
				return true;
			}
			int limit = StorageNetwork.Limit;
			if (limit <= 0)
			{
				return true;
			}
			int num = StorageData.StoredCount();
			if (num < limit)
			{
				return true;
			}
			__instance.CancelBuildMode(true);
			HUDManager.Instance.DisplayTip("Storage full!", $"Storage limit reached ({num}/{limit}). Retrieve something in the terminal (STORAGE).", true, false, "LC_Tip1");
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		private static void ConnectClientPostfix()
		{
			StorageNetwork.Register();
			if ((Object)(object)NetworkManager.Singleton != (Object)null && !NetworkManager.Singleton.IsServer)
			{
				StorageNetwork.SendHello();
			}
		}
	}
	[BepInPlugin("UFO.StorageManager", "UFO Storage Manager", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "UFO.StorageManager";

		public const string Name = "UFO Storage Manager";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> StorageLimit;

		internal static ConfigEntry<bool> HostOnly;

		internal static ConfigEntry<bool> LimitBuildMode;

		private void Awake()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			StorageLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Host", "StorageLimit", 10, "How many objects can be in storage at once. 0 = no limit. Host setting.");
			HostOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "HostOnly", false, "Only the host can store and retrieve objects from the terminal. Host setting.");
			LimitBuildMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "LimitBuildMode", true, "The storage limit also applies when storing objects in build mode (X key). Host setting.");
			new Harmony("UFO.StorageManager").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"UFO Storage Manager 1.0.0 loaded.");
		}
	}
	internal enum StorageAction : byte
	{
		Store = 1,
		Retrieve,
		StoreAll,
		RetrieveAll
	}
	internal static class StorageActions
	{
		private const int NoPlayer = -1;

		internal static string Execute(StorageAction action, ulong objectId, int unlockableId, int limit, bool toDefault)
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)ShipBuildModeManager.Instance == (Object)null)
			{
				return "The ship is not ready.";
			}
			return action switch
			{
				StorageAction.Store => Store(objectId, limit), 
				StorageAction.Retrieve => Retrieve(unlockableId, toDefault), 
				StorageAction.StoreAll => StoreAll(limit), 
				StorageAction.RetrieveAll => RetrieveAll(toDefault), 
				_ => "Unknown action.", 
			};
		}

		private static string Store(ulong objectId, int limit)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			DeployedObject deployedObject = StorageData.GetDeployed().Find((DeployedObject d) => d.ObjectId == objectId);
			if (deployedObject == null)
			{
				return "That object is no longer on the ship.";
			}
			if (deployedObject.Problem != null)
			{
				return "Can't store " + deployedObject.Label + ": " + deployedObject.Problem + ".";
			}
			int num = StorageData.StoredCount();
			if (limit > 0 && num >= limit)
			{
				return $"Storage is full ({num}/{limit}). Retrieve something first.";
			}
			ShipBuildModeManager.Instance.StoreObjectServerRpc(new NetworkObjectReference(deployedObject.NetworkObject), -1);
			return deployedObject.Label + " stored.";
		}

		private static string Retrieve(int unlockableId, bool toDefault)
		{
			StoredObject storedObject = StorageData.GetStored().Find((StoredObject s) => s.UnlockableId == unlockableId);
			if (storedObject == null)
			{
				return "That object is not in storage.";
			}
			if (toDefault)
			{
				DefaultPosition.Prepare(unlockableId);
			}
			StartOfRound.Instance.ReturnUnlockableFromStorageServerRpc(unlockableId);
			if (!toDefault)
			{
				return storedObject.Label + " retrieved to its last position.";
			}
			return storedObject.Label + " retrieved to its default position.";
		}

		private static string StoreAll(int limit)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			int num = StorageData.StoredCount();
			int num2 = 0;
			int num3 = 0;
			List<string> list = new List<string>();
			foreach (DeployedObject item in StorageData.GetDeployed())
			{
				if (item.Storable)
				{
					if (item.Problem != null)
					{
						list.Add(item.Label + " (" + item.Problem + ")");
						continue;
					}
					if (limit > 0 && num >= limit)
					{
						num3++;
						continue;
					}
					ShipBuildModeManager.Instance.StoreObjectServerRpc(new NetworkObjectReference(item.NetworkObject), -1);
					num++;
					num2++;
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append((num2 == 0) ? "Nothing was stored." : ("Stored " + Plural(num2) + "."));
			if (num3 > 0)
			{
				stringBuilder.Append("\nStorage is full: " + Plural(num3) + " did not fit.");
			}
			if (list.Count > 0)
			{
				stringBuilder.Append("\nSkipped:");
				foreach (string item2 in list)
				{
					stringBuilder.Append("\n * ").Append(item2);
				}
			}
			return stringBuilder.ToString();
		}

		private static string RetrieveAll(bool toDefault)
		{
			List<StoredObject> stored = StorageData.GetStored();
			if (stored.Count == 0)
			{
				return "Storage is empty.";
			}
			foreach (StoredObject item in stored)
			{
				if (toDefault)
				{
					DefaultPosition.Prepare(item.UnlockableId);
				}
				StartOfRound.Instance.ReturnUnlockableFromStorageServerRpc(item.UnlockableId);
			}
			return "Retrieved " + Plural(stored.Count) + " to their " + (toDefault ? "default" : "last") + " positions.";
		}

		private static string Plural(int count)
		{
			if (count != 1)
			{
				return count + " objects";
			}
			return "1 object";
		}
	}
	internal sealed class DeployedObject
	{
		public PlaceableShipObject Placeable;

		public NetworkObject NetworkObject;

		public ulong ObjectId;

		public int UnlockableId;

		public string Name;

		public string Label;

		public bool Storable;

		public string Problem;

		public Vector3 Position;
	}
	internal sealed class StoredObject
	{
		public int UnlockableId;

		public string Name;

		public string Label;
	}
	internal static class StorageData
	{
		private const float ScrapPlacedCooldown = 6f;

		internal static List<UnlockableItem> Unlockables
		{
			get
			{
				StartOfRound instance = StartOfRound.Instance;
				if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.unlockablesList != (Object)null))
				{
					return null;
				}
				return instance.unlockablesList.unlockables;
			}
		}

		internal static List<DeployedObject> GetDeployed()
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			List<DeployedObject> list = new List<DeployedObject>();
			List<UnlockableItem> unlockables = Unlockables;
			if (unlockables == null)
			{
				return list;
			}
			HashSet<ulong> hashSet = new HashSet<ulong>();
			PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>();
			foreach (PlaceableShipObject val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.parentObject == (Object)null)
				{
					continue;
				}
				int unlockableID = val.unlockableID;
				if (unlockableID < 0 || unlockableID >= unlockables.Count)
				{
					continue;
				}
				UnlockableItem val2 = unlockables[unlockableID];
				if (val2.inStorage || val.parentObject.disableObject)
				{
					continue;
				}
				NetworkObject networkObject = ((NetworkBehaviour)val.parentObject).NetworkObject;
				if (!((Object)(object)networkObject == (Object)null) && networkObject.IsSpawned && hashSet.Add(networkObject.NetworkObjectId))
				{
					DeployedObject deployedObject = new DeployedObject
					{
						Placeable = val,
						NetworkObject = networkObject,
						ObjectId = networkObject.NetworkObjectId,
						UnlockableId = unlockableID,
						Name = CleanName(val2.unlockableName),
						Storable = val2.canBeStored,
						Position = (((Object)(object)val.mainMesh != (Object)null) ? ((Component)val.mainMesh).transform.position : ((Component)val).transform.position)
					};
					if (!val2.canBeStored)
					{
						deployedObject.Problem = "can't be stored";
					}
					else if ((Object)(object)((Component)val.parentObject).GetComponentInChildren<GrabbableObject>() != (Object)null)
					{
						deployedObject.Problem = "has items on it";
					}
					else if (Time.realtimeSinceStartup - val.lastTimeScrapWasPlaced <= 6f)
					{
						deployedObject.Problem = "items were just placed on it, try again in a moment";
					}
					list.Add(deployedObject);
				}
			}
			list.Sort(delegate(DeployedObject a, DeployedObject b)
			{
				int num = string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
				return (num == 0) ? a.ObjectId.CompareTo(b.ObjectId) : num;
			});
			NumberLabels(list, (DeployedObject d) => d.Name, delegate(DeployedObject d, string label)
			{
				d.Label = label;
			});
			return list;
		}

		internal static List<StoredObject> GetStored()
		{
			List<StoredObject> list = new List<StoredObject>();
			List<UnlockableItem> unlockables = Unlockables;
			if (unlockables == null)
			{
				return list;
			}
			for (int i = 0; i < unlockables.Count; i++)
			{
				UnlockableItem val = unlockables[i];
				if (val.unlockableType != 0 && val.inStorage && (val.hasBeenUnlockedByPlayer || val.alreadyUnlocked))
				{
					list.Add(new StoredObject
					{
						UnlockableId = i,
						Name = CleanName(val.unlockableName)
					});
				}
			}
			list.Sort(delegate(StoredObject a, StoredObject b)
			{
				int num = string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
				return (num == 0) ? a.UnlockableId.CompareTo(b.UnlockableId) : num;
			});
			NumberLabels(list, (StoredObject s) => s.Name, delegate(StoredObject s, string label)
			{
				s.Label = label;
			});
			return list;
		}

		internal static int StoredCount()
		{
			return GetStored().Count;
		}

		private static void NumberLabels<T>(List<T> list, Func<T, string> name, Action<T, string> setLabel)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
			foreach (T item in list)
			{
				string text = name(item);
				dictionary.TryGetValue(text, out var value);
				value = (dictionary[text] = value + 1);
				setLabel(item, text + " #" + value);
			}
		}

		internal static string CleanName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return "Unknown object";
			}
			name = name.Trim();
			return char.ToUpperInvariant(name[0]) + name.Substring(1);
		}

		internal static string DescribePosition(Vector3 position, Terminal terminal)
		{
			//IL_000f: 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)
			if ((Object)(object)terminal == (Object)null)
			{
				return "";
			}
			return Vector3.Distance(position, ((Component)terminal).transform.position).ToString("0.0", CultureInfo.InvariantCulture) + "m from terminal";
		}
	}
	internal static class StorageMenu
	{
		private enum State
		{
			None,
			Main,
			View,
			Store,
			StoreConfirm,
			Retrieve,
			RetrieveWhere,
			StoreAllConfirm,
			RetrieveAllConfirm
		}

		private const string Header = "SHIP STORAGE MANAGER";

		private const string Line = "-----------------------------";

		private static readonly string[] OpenWords = new string[3] { "storage", "storage manager", "ship storage" };

		private static readonly string[] BackWords = new string[3] { "back", "menu", "return" };

		private static readonly string[] ConfirmWords = new string[4] { "confirm", "c", "yes", "y" };

		private static readonly string[] CancelWords = new string[4] { "cancel", "deny", "no", "n" };

		private static State state = State.None;

		private static TerminalNode node;

		private static Terminal activeTerminal;

		private static List<DeployedObject> shownDeployed = new List<DeployedObject>();

		private static List<StoredObject> shownStored = new List<StoredObject>();

		private static DeployedObject selected;

		private static StoredObject selectedStored;

		private static bool waitingForHost;

		internal static void Reset()
		{
			state = State.None;
			selected = null;
			selectedStored = null;
			waitingForHost = false;
			shownDeployed.Clear();
			shownStored.Clear();
		}

		internal static bool TryHandle(Terminal terminal, string rawInput, out TerminalNode result)
		{
			result = null;
			string text = Normalize(rawInput);
			if (text.Length == 0)
			{
				return false;
			}
			activeTerminal = terminal;
			if (Is(text, OpenWords))
			{
				result = ShowMain(null);
				return true;
			}
			if (state == State.None)
			{
				return false;
			}
			if (Is(text, BackWords))
			{
				result = ((state == State.StoreConfirm) ? ShowStoreList("Cancelled.") : ((state == State.RetrieveWhere) ? ShowRetrieveList("Cancelled.") : ShowMain(null)));
				return true;
			}
			switch (state)
			{
			case State.Main:
				result = HandleMain(text);
				break;
			case State.View:
				result = (IsNumber(text) ? ShowView("Type BACK to return to the menu.") : null);
				break;
			case State.Store:
				result = HandleStore(text);
				break;
			case State.StoreConfirm:
				result = HandleStoreConfirm(text);
				break;
			case State.Retrieve:
				result = HandleRetrieve(text);
				break;
			case State.RetrieveWhere:
				result = HandleRetrieveWhere(text);
				break;
			case State.StoreAllConfirm:
				result = HandleAllConfirm(text, StorageAction.StoreAll);
				break;
			case State.RetrieveAllConfirm:
				result = HandleRetrieveAll(text);
				break;
			}
			if ((Object)(object)result == (Object)null)
			{
				Reset();
				return false;
			}
			return true;
		}

		internal static void ShowResult(string text)
		{
			bool num = waitingForHost;
			waitingForHost = false;
			Terminal val = activeTerminal;
			if (num && state == State.Main && (Object)(object)val != (Object)null && val.terminalInUse)
			{
				val.LoadNewNode(ShowMain(text));
			}
			else if ((Object)(object)HUDManager.Instance != (Object)null && !string.IsNullOrEmpty(text))
			{
				HUDManager.Instance.DisplayTip("Ship storage", text, false, false, "LC_Tip1");
			}
		}

		private static TerminalNode ShowMain(string message)
		{
			state = State.Main;
			selected = null;
			List<DeployedObject> deployed = StorageData.GetDeployed();
			int stored = StorageData.StoredCount();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("SHIP STORAGE MANAGER").Append("\n\n");
			if (!string.IsNullOrEmpty(message))
			{
				stringBuilder.Append(message).Append("\n").Append("-----------------------------")
					.Append("\n\n");
			}
			stringBuilder.Append("1. View deployed objects\n");
			stringBuilder.Append("2. Store an object\n");
			stringBuilder.Append("3. Retrieve an object\n");
			stringBuilder.Append("4. Store all objects\n");
			stringBuilder.Append("5. Retrieve all objects\n\n");
			stringBuilder.Append("Deployed: ").Append(deployed.Count).Append("   Stored: ")
				.Append(StorageUsage(stored))
				.Append("\n");
			if (!StorageNetwork.CanUse)
			{
				stringBuilder.Append("Only the host can store or retrieve objects.\n");
			}
			stringBuilder.Append("\nPlease select an option:\n");
			return Node(stringBuilder);
		}

		private static TerminalNode ShowView(string message)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			state = State.View;
			List<DeployedObject> deployed = StorageData.GetDeployed();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("DEPLOYED OBJECTS\n\n");
			if (deployed.Count == 0)
			{
				stringBuilder.Append("No objects are deployed on the ship.\n");
			}
			for (int i = 0; i < deployed.Count; i++)
			{
				DeployedObject deployedObject = deployed[i];
				stringBuilder.Append(i + 1).Append(". ").Append(deployedObject.Label);
				string text = StorageData.DescribePosition(deployedObject.Position, activeTerminal);
				if (text.Length > 0)
				{
					stringBuilder.Append(" - ").Append(text);
				}
				if (deployedObject.Problem != null)
				{
					stringBuilder.Append(" (").Append(deployedObject.Problem).Append(")");
				}
				stringBuilder.Append("\n");
			}
			stringBuilder.Append("\n");
			if (!string.IsNullOrEmpty(message))
			{
				stringBuilder.Append(message).Append("\n");
			}
			else
			{
				stringBuilder.Append("Type BACK to return to the menu.\n");
			}
			return Node(stringBuilder);
		}

		private static TerminalNode ShowStoreList(string message)
		{
			state = State.Store;
			selected = null;
			shownDeployed = StorageData.GetDeployed().FindAll((DeployedObject d) => d.Storable);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("SELECT OBJECT TO STORE\n\n");
			if (!string.IsNullOrEmpty(message))
			{
				stringBuilder.Append(message).Append("\n\n");
			}
			if (shownDeployed.Count == 0)
			{
				stringBuilder.Append("There is nothing to store.\n\nType BACK to return to the menu.\n");
				return Node(stringBuilder);
			}
			for (int num = 0; num < shownDeployed.Count; num++)
			{
				DeployedObject deployedObject = shownDeployed[num];
				stringBuilder.Append(num + 1).Append(". ").Append(deployedObject.Label);
				if (deployedObject.Problem != null)
				{
					stringBuilder.Append(" (").Append(deployedObject.Problem).Append(")");
				}
				stringBuilder.Append("\n");
			}
			stringBuilder.Append("\nStorage: ").Append(StorageUsage(StorageData.StoredCount())).Append("\n");
			stringBuilder.Append("\nType object number:\n");
			return Node(stringBuilder);
		}

		private static TerminalNode ShowStoreConfirm(DeployedObject target)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			state = State.StoreConfirm;
			selected = target;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(target.Label).Append(" selected.\n");
			string text = StorageData.DescribePosition(target.Position, activeTerminal);
			if (text.Length > 0)
			{
				stringBuilder.Append("Position: ").Append(text).Append("\n");
			}
			stringBuilder.Append("\nDo you want to store this object?\n");
			stringBuilder.Append("[CONFIRM] / [CANCEL]\n");
			return Node(stringBuilder);
		}

		private static TerminalNode ShowRetrieveList(string message)
		{
			state = State.Retrieve;
			shownStored = StorageData.GetStored();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("SHIP STORAGE\n\n");
			if (!string.IsNullOrEmpty(message))
			{
				stringBuilder.Append(message).Append("\n\n");
			}
			stringBuilder.Append("Stored objects:\n\n");
			if (shownStored.Count == 0)
			{
				stringBuilder.Append("Storage is empty.\n");
			}
			for (int i = 0; i < shownStored.Count; i++)
			{
				stringBuilder.Append(i + 1).Append(". ").Append(shownStored[i].Label)
					.Append("\n");
			}
			stringBuilder.Append("\n").Append(AvailableLine(shownStored.Count)).Append("\n");
			stringBuilder.Append((shownStored.Count == 0) ? "\nType BACK to return to the menu.\n" : "\nType object number to retrieve:\n");
			return Node(stringBuilder);
		}

		private static TerminalNode ShowAllConfirm(StorageAction action)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (action == StorageAction.StoreAll)
			{
				state = State.StoreAllConfirm;
				int count = StorageData.GetDeployed().FindAll((DeployedObject d) => d.Storable && d.Problem == null).Count;
				stringBuilder.Append("STORE ALL OBJECTS\n\n");
				stringBuilder.Append(count).Append((count == 1) ? " object" : " objects").Append(" can be stored.\n");
				stringBuilder.Append(AvailableLine(StorageData.StoredCount())).Append("\n");
				stringBuilder.Append("\nDo you want to store all objects?\n");
				stringBuilder.Append("[CONFIRM] / [CANCEL]\n");
				return Node(stringBuilder);
			}
			state = State.RetrieveAllConfirm;
			int num = StorageData.StoredCount();
			stringBuilder.Append("RETRIEVE ALL OBJECTS\n\n");
			stringBuilder.Append(num).Append((num == 1) ? " object is" : " objects are").Append(" in storage.\n");
			stringBuilder.Append("\nWhere should they go?\n");
			AppendWhereOptions(stringBuilder);
			return Node(stringBuilder);
		}

		private static TerminalNode ShowRetrieveWhere(StoredObject target)
		{
			state = State.RetrieveWhere;
			selectedStored = target;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(target.Label).Append(" selected.\n");
			stringBuilder.Append("\nWhere should it go?\n");
			AppendWhereOptions(stringBuilder);
			return Node(stringBuilder);
		}

		private static void AppendWhereOptions(StringBuilder text)
		{
			text.Append("1. Last position\n");
			text.Append("2. Default position\n\n");
			text.Append("Use DEFAULT if an object got stuck outside the ship.\n");
			text.Append("\nType option number or CANCEL:\n");
		}

		private static bool? ParseWhere(string input)
		{
			if (input != null)
			{
				switch (input.Length)
				{
				case 1:
				{
					char c = input[0];
					if (c != '1')
					{
						if (c == '2')
						{
							goto IL_00ed;
						}
						if (c != 'c')
						{
							break;
						}
					}
					goto IL_00e6;
				}
				case 7:
				{
					char c = input[0];
					if (c != 'c')
					{
						if (c != 'd' || !(input == "default"))
						{
							break;
						}
						goto IL_00ed;
					}
					if (!(input == "confirm"))
					{
						break;
					}
					goto IL_00e6;
				}
				case 4:
					if (!(input == "last"))
					{
						break;
					}
					goto IL_00e6;
				case 13:
					if (!(input == "last position"))
					{
						break;
					}
					goto IL_00e6;
				case 14:
					if (!(input == "last positions"))
					{
						break;
					}
					goto IL_00e6;
				case 16:
					if (!(input == "default position"))
					{
						break;
					}
					goto IL_00ed;
				case 17:
					{
						if (!(input == "default positions"))
						{
							break;
						}
						goto IL_00ed;
					}
					IL_00e6:
					return false;
					IL_00ed:
					return true;
				}
			}
			return null;
		}

		private static TerminalNode HandleMain(string input)
		{
			switch (input)
			{
			case "1":
			case "list":
			case "view":
			case "deployed":
			case "view deployed objects":
				return ShowView(null);
			case "2":
			case "store":
			case "store an object":
				return ShowStoreList(null);
			case "3":
			case "retrieve":
			case "retrieve an object":
				return ShowRetrieveList(null);
			case "4":
			case "store all":
			case "store all objects":
				return ShowAllConfirm(StorageAction.StoreAll);
			case "5":
			case "retrieve all":
			case "retrieve all objects":
				return ShowAllConfirm(StorageAction.RetrieveAll);
			default:
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowMain("Invalid option.");
			}
		}

		private static TerminalNode HandleStore(string input)
		{
			if (shownDeployed.Count == 0)
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowStoreList(null);
			}
			string error;
			DeployedObject deployedObject = Pick(shownDeployed, input, (DeployedObject d) => d.Label, (DeployedObject d) => d.Name, out error);
			if (deployedObject == null)
			{
				if (error == null)
				{
					return null;
				}
				return ShowStoreList(error);
			}
			if (deployedObject.Problem != null)
			{
				return ShowStoreList("Can't store " + deployedObject.Label + ": " + deployedObject.Problem + ".");
			}
			return ShowStoreConfirm(deployedObject);
		}

		private static TerminalNode HandleStoreConfirm(string input)
		{
			if (Is(input, CancelWords))
			{
				return ShowStoreList("Cancelled.");
			}
			if (!Is(input, ConfirmWords))
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowStoreConfirm(selected);
			}
			DeployedObject deployedObject = selected;
			if (!StorageNetwork.CanUse)
			{
				return ShowMain("Only the host can store or retrieve objects.");
			}
			int limit = StorageNetwork.Limit;
			int num = StorageData.StoredCount();
			if (limit > 0 && num >= limit)
			{
				return ShowMain($"Storage is full ({num}/{limit}). Retrieve something first.");
			}
			return RunAction(StorageAction.Store, deployedObject.ObjectId, -1);
		}

		private static TerminalNode HandleRetrieve(string input)
		{
			if (shownStored.Count == 0)
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowRetrieveList(null);
			}
			string error;
			StoredObject storedObject = Pick(shownStored, input, (StoredObject s) => s.Label, (StoredObject s) => s.Name, out error);
			if (storedObject == null)
			{
				if (error == null)
				{
					return null;
				}
				return ShowRetrieveList(error);
			}
			return ShowRetrieveWhere(storedObject);
		}

		private static TerminalNode HandleRetrieveWhere(string input)
		{
			if (Is(input, CancelWords))
			{
				return ShowRetrieveList("Cancelled.");
			}
			bool? flag = ParseWhere(input);
			if (!flag.HasValue)
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowRetrieveWhere(selectedStored);
			}
			if (!StorageNetwork.CanUse)
			{
				return ShowMain("Only the host can store or retrieve objects.");
			}
			return RunAction(StorageAction.Retrieve, 0uL, selectedStored.UnlockableId, flag.Value);
		}

		private static TerminalNode HandleRetrieveAll(string input)
		{
			if (Is(input, CancelWords))
			{
				return ShowMain("Cancelled.");
			}
			bool? flag = ParseWhere(input);
			if (!flag.HasValue)
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowAllConfirm(StorageAction.RetrieveAll);
			}
			if (!StorageNetwork.CanUse)
			{
				return ShowMain("Only the host can store or retrieve objects.");
			}
			return RunAction(StorageAction.RetrieveAll, 0uL, -1, flag.Value);
		}

		private static TerminalNode HandleAllConfirm(string input, StorageAction action)
		{
			if (Is(input, CancelWords))
			{
				return ShowMain("Cancelled.");
			}
			if (!Is(input, ConfirmWords))
			{
				if (!IsNumber(input))
				{
					return null;
				}
				return ShowAllConfirm(action);
			}
			if (!StorageNetwork.CanUse)
			{
				return ShowMain("Only the host can store or retrieve objects.");
			}
			return RunAction(action, 0uL, -1);
		}

		private static TerminalNode RunAction(StorageAction action, ulong objectId, int unlockableId, bool toDefault = false)
		{
			string text = StorageNetwork.Request(action, objectId, unlockableId, toDefault);
			if (text != null)
			{
				waitingForHost = false;
				return ShowMain(text);
			}
			TerminalNode result = ShowMain("Sending request to the ship...");
			waitingForHost = true;
			return result;
		}

		private static T Pick<T>(List<T> list, string input, Func<T, string> label, Func<T, string> name, out string error) where T : class
		{
			error = null;
			if (int.TryParse(input, out var result))
			{
				if (result >= 1 && result <= list.Count)
				{
					return list[result - 1];
				}
				error = "Invalid number.";
				return null;
			}
			string wanted = Regex.Replace(input.Replace("#", " "), "\\s+", " ").Trim();
			foreach (T item in list)
			{
				if (Normalize(label(item).Replace("#", " ")) == wanted)
				{
					return item;
				}
			}
			List<T> list2 = list.FindAll((T e) => Normalize(name(e)) == wanted);
			if (list2.Count == 0)
			{
				list2 = list.FindAll((T e) => Normalize(name(e)).StartsWith(wanted, StringComparison.Ordinal));
			}
			if (list2.Count == 1)
			{
				return list2[0];
			}
			if (list2.Count > 1)
			{
				error = "Several objects match. Type the number instead.";
			}
			return null;
		}

		private static string StorageUsage(int stored)
		{
			int limit = StorageNetwork.Limit;
			if (limit <= 0)
			{
				return stored.ToString();
			}
			return $"{stored}/{limit}";
		}

		private static string AvailableLine(int stored)
		{
			int limit = StorageNetwork.Limit;
			if (limit <= 0)
			{
				return "Available storage: unlimited";
			}
			return $"Available storage: {Mathf.Max(0, limit - stored)}/{limit}";
		}

		private static string Normalize(string text)
		{
			if (text == null)
			{
				return "";
			}
			return Regex.Replace(text.Trim().ToLowerInvariant(), "\\s+", " ").TrimEnd('.', '!', '?');
		}

		private static bool Is(string input, string[] words)
		{
			return Array.IndexOf(words, input) >= 0;
		}

		private static bool IsNumber(string input)
		{
			int result;
			return int.TryParse(input, out result);
		}

		private static TerminalNode Node(StringBuilder text)
		{
			if ((Object)(object)node == (Object)null)
			{
				node = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)node).name = "UFOStorageManagerNode";
				((Object)node).hideFlags = (HideFlags)32;
				node.clearPreviousText = true;
				node.maxCharactersToType = 35;
			}
			node.displayText = text.Append("\n").ToString();
			return node;
		}
	}
	internal static class StorageNetwork
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnHello;

			public static HandleNamedMessageDelegate <1>__OnSettings;

			public static HandleNamedMessageDelegate <2>__OnRequest;

			public static HandleNamedMessageDelegate <3>__OnResult;

			public static HandleNamedMessageDelegate <4>__OnResetDefault;
		}

		private const string HelloMessage = "UFO.StorageManager.Hello";

		private const string SettingsMessage = "UFO.StorageManager.Settings";

		private const string RequestMessage = "UFO.StorageManager.Request";

		private const string ResultMessage = "UFO.StorageManager.Result";

		private const string ResetDefaultMessage = "UFO.StorageManager.ResetDefault";

		internal static bool HostHasMod;

		private static int hostLimit;

		private static bool hostOnly;

		private static bool hostLimitBuildMode;

		private static bool settingsHooked;

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

		internal static int Limit
		{
			get
			{
				if (IsHost)
				{
					return Mathf.Max(0, Plugin.StorageLimit.Value);
				}
				if (!HostHasMod)
				{
					return 0;
				}
				return hostLimit;
			}
		}

		internal static bool LimitBuildMode
		{
			get
			{
				if (!IsHost)
				{
					if (HostHasMod)
					{
						return hostLimitBuildMode;
					}
					return false;
				}
				return Plugin.LimitBuildMode.Value;
			}
		}

		internal static bool CanUse
		{
			get
			{
				if (!IsHost && HostHasMod)
				{
					return !hostOnly;
				}
				return true;
			}
		}

		internal static void Register()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_007f: 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_008a: Expected O, but got Unknown
			//IL_00a5: 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: Expected O, but got Unknown
			//IL_00cb: 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: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = (((Object)(object)singleton != (Object)null) ? singleton.CustomMessagingManager : null);
			if (val == null)
			{
				return;
			}
			object obj = <>O.<0>__OnHello;
			if (obj == null)
			{
				HandleNamedMessageDelegate val2 = OnHello;
				<>O.<0>__OnHello = val2;
				obj = (object)val2;
			}
			val.RegisterNamedMessageHandler("UFO.StorageManager.Hello", (HandleNamedMessageDelegate)obj);
			object obj2 = <>O.<1>__OnSettings;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val3 = OnSettings;
				<>O.<1>__OnSettings = val3;
				obj2 = (object)val3;
			}
			val.RegisterNamedMessageHandler("UFO.StorageManager.Settings", (HandleNamedMessageDelegate)obj2);
			object obj3 = <>O.<2>__OnRequest;
			if (obj3 == null)
			{
				HandleNamedMessageDelegate val4 = OnRequest;
				<>O.<2>__OnRequest = val4;
				obj3 = (object)val4;
			}
			val.RegisterNamedMessageHandler("UFO.StorageManager.Request", (HandleNamedMessageDelegate)obj3);
			object obj4 = <>O.<3>__OnResult;
			if (obj4 == null)
			{
				HandleNamedMessageDelegate val5 = OnResult;
				<>O.<3>__OnResult = val5;
				obj4 = (object)val5;
			}
			val.RegisterNamedMessageHandler("UFO.StorageManager.Result", (HandleNamedMessageDelegate)obj4);
			object obj5 = <>O.<4>__OnResetDefault;
			if (obj5 == null)
			{
				HandleNamedMessageDelegate val6 = OnResetDefault;
				<>O.<4>__OnResetDefault = val6;
				obj5 = (object)val6;
			}
			val.RegisterNamedMessageHandler("UFO.StorageManager.ResetDefault", (HandleNamedMessageDelegate)obj5);
			HostHasMod = singleton.IsServer;
			if (!settingsHooked)
			{
				settingsHooked = true;
				Plugin.StorageLimit.SettingChanged += delegate
				{
					BroadcastSettings();
				};
				Plugin.HostOnly.SettingChanged += delegate
				{
					BroadcastSettings();
				};
				Plugin.LimitBuildMode.SettingChanged += delegate
				{
					BroadcastSettings();
				};
			}
		}

		internal unsafe static void SendHello()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null || singleton.IsServer)
			{
				return;
			}
			HostHasMod = false;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				singleton.CustomMessagingManager.SendNamedMessage("UFO.StorageManager.Hello", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static string Request(StorageAction action, ulong objectId, int unlockableId, bool toDefault)
		{
			//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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening)
			{
				return "Not connected.";
			}
			if (singleton.IsServer)
			{
				return StorageActions.Execute(action, objectId, unlockableId, Limit, toDefault);
			}
			if (!HostHasMod)
			{
				if (toDefault)
				{
					return "The host needs UFO Storage Manager to retrieve to the default position.";
				}
				return StorageActions.Execute(action, objectId, unlockableId, 0, toDefault: false);
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1);
			try
			{
				byte b = (byte)action;
				((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref objectId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref unlockableId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref toDefault, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("UFO.StorageManager.Request", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
			return null;
		}

		private static void BroadcastSettings()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				return;
			}
			foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
			{
				if (connectedClientsId != singleton.LocalClientId)
				{
					SendSettings(connectedClientsId);
				}
			}
		}

		private unsafe static void SendSettings(ulong clientId)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1);
			try
			{
				int num = Mathf.Max(0, Plugin.StorageLimit.Value);
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				bool value = Plugin.HostOnly.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value, default(ForPrimitives));
				value = Plugin.LimitBuildMode.Value;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("UFO.StorageManager.Settings", clientId, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void SendResult(ulong clientId, string text)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, 8192);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(text ?? "", false);
				singleton.CustomMessagingManager.SendNamedMessage("UFO.StorageManager.Result", clientId, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnHello(ulong senderClientId, FastBufferReader reader)
		{
			if (IsHost)
			{
				SendSettings(senderClientId);
			}
		}

		private static void OnSettings(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (senderClientId == 0L)
			{
				HostHasMod = true;
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref hostLimit, default(ForPrimitives));
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref hostOnly, default(ForPrimitives));
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref hostLimitBuildMode, default(ForPrimitives));
			}
		}

		private static void OnRequest(ulong senderClientId, FastBufferReader reader)
		{
			//IL_000e: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				byte action = default(byte);
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref action, default(ForPrimitives));
				ulong objectId = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref objectId, default(ForPrimitives));
				int unlockableId = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref unlockableId, default(ForPrimitives));
				bool toDefault = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref toDefault, default(ForPrimitives));
				string text = ((!Plugin.HostOnly.Value || senderClientId == 0L) ? StorageActions.Execute((StorageAction)action, objectId, unlockableId, Mathf.Max(0, Plugin.StorageLimit.Value), toDefault) : "Only the host can store or retrieve objects.");
				SendResult(senderClientId, text);
			}
		}

		internal unsafe static void BroadcastResetDefault(int unlockableId)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
			{
				if (connectedClientsId != singleton.LocalClientId)
				{
					((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref unlockableId, default(ForPrimitives));
						singleton.CustomMessagingManager.SendNamedMessage("UFO.StorageManager.ResetDefault", connectedClientsId, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
		}

		private static void OnResetDefault(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (senderClientId == 0L && !IsHost)
			{
				int unlockableId = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref unlockableId, default(ForPrimitives));
				DefaultPosition.ResetLocal(unlockableId);
			}
		}

		private static void OnResult(ulong senderClientId, FastBufferReader reader)
		{
			if (senderClientId == 0L)
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				StorageMenu.ShowResult(text);
			}
		}
	}
}