Decompiled source of Cabinet Item Storage v0.0.4

NicholaScott.LethalCompany.CabinetStorage.dll

Decompiled 11 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using NicholaScott.BepInEx.Utils.Configuration;
using NicholaScott.BepInEx.Utils.Instancing;
using NicholaScott.BepInEx.Utils.Patching;
using NicholaScott.LethalCompany.API;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("NicholaScott.LethalCompany.CabinetStorage")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NicholaScott.LethalCompany.CabinetStorage")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1268DCF6-2C4D-46DB-B877-1F13F206E02D")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NicholaScott.LethalCompany.CabinetStorage;

public class CabinetManager : MonoBehaviour
{
	private enum NetworkMessageType
	{
		ServerRequestSync,
		ServerSpawnItem,
		ClientSyncNewItem
	}

	private const string NetTransferCabinetData = "CabMagTransferData";

	private const string StoringText = "Storing {0}...";

	private const string GrabbingText = "Taking {0}...";

	private const string EmptyHoverText = "[USE] Empty Drawer";

	private const string HoverText = "({0}) {1}";

	private Sprite emptyIcon;

	private (InteractTrigger trigger, LethalInventory inventory)[] slots = new(InteractTrigger, LethalInventory)[6];

	private static string StoreFormatted(string heldItemName)
	{
		return $"Storing {heldItemName}...";
	}

	private static string GrabFormatted(string storedItemName)
	{
		return $"Taking {storedItemName}...";
	}

	private static string HoverFormatted(int storedCount, string storedItemName)
	{
		return $"({storedCount}) {storedItemName}";
	}

	private static Item ItemFromID(string id)
	{
		return StartOfRound.Instance.allItemsList.itemsList.First((Item f) => f.itemName.ToLower().Replace(" ", "") == id);
	}

	private static string ItemToID(Item item)
	{
		return item.itemName.ToLower().Replace(" ", "");
	}

	private static Sprite GrabEmptyIcon()
	{
		return Extensions.FindPrefabByName<Item>(StartOfRound.Instance, new string[2] { "gold", "bar" }).itemIcon;
	}

	private static IEnumerator WaitUntilNotTheSame(InteractTrigger trigger)
	{
		bool stillSame = true;
		float cfgCDTime = Singleton<CabinetStorage, CabinetStorage.Configuration>.Configuration.CooldownBetweenInteract;
		while (stillSame)
		{
			yield return (object)new WaitForSeconds(5f);
			if (Math.Abs(trigger.cooldownTime - cfgCDTime) > 0.01f)
			{
				Singleton<CabinetStorage>.Logger.LogInfo((object)$"Cabinet Storage InteractTrigger had it's cooldown time overwitten to {trigger.cooldownTime}. Changing back to {cfgCDTime}.");
				stillSame = false;
				trigger.cooldownTime = cfgCDTime;
			}
		}
	}

	private static InteractTrigger CreateNewInteractTrigger(int id, Transform attachTo)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Expected O, but got Unknown
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Expected O, but got Unknown
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Expected O, but got Unknown
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Expected O, but got Unknown
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Expected O, but got Unknown
		GameObject val = new GameObject($"Drawer {id}", new Type[2]
		{
			typeof(SphereCollider),
			typeof(InteractTrigger)
		});
		val.transform.SetParent(attachTo);
		int num = id % 2;
		Vector3 val2 = attachTo.up * ((id <= 1) ? (-0.55f) : ((id < 4) ? 0f : 0.55f));
		Vector3 val3 = attachTo.right * 0.4f * ((num == 0) ? (-1f) : 0.75f);
		val.transform.localPosition = attachTo.forward * 0.45f + val2 + val3;
		val.layer = LayerMask.NameToLayer("InteractableObject");
		val.tag = "InteractTrigger";
		SphereCollider component = val.GetComponent<SphereCollider>();
		InteractTrigger component2 = val.GetComponent<InteractTrigger>();
		component.radius = 0.25f;
		((Collider)component).enabled = true;
		component2.interactable = true;
		component2.holdInteraction = true;
		component2.timeToHold = 0.4f;
		component2.cooldownTime = Singleton<CabinetStorage, CabinetStorage.Configuration>.Configuration.CooldownBetweenInteract;
		((MonoBehaviour)component2).StartCoroutine(WaitUntilNotTheSame(component2));
		component2.timeToHoldSpeedMultiplier = 1f;
		component2.hoverTip = "[USE] Empty Drawer";
		component2.onInteractEarly = new InteractEvent();
		component2.onInteract = new InteractEvent();
		component2.onCancelAnimation = new InteractEvent();
		component2.onStopInteract = new InteractEvent();
		component2.holdingInteractEvent = new InteractEventFloat();
		((UnityEvent<PlayerControllerB>)(object)component2.onInteractEarly).AddListener((UnityAction<PlayerControllerB>)delegate
		{
			AutoSingleton<CabinetManager>.Instance.PrepareHoldTip(id);
		});
		((UnityEvent<PlayerControllerB>)(object)component2.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate
		{
			AutoSingleton<CabinetManager>.Instance.TakeOrStoreHeldItem(id);
		});
		return component2;
	}

	private void Awake()
	{
		emptyIcon = GrabEmptyIcon();
		InitializeSlots();
	}

	private void Start()
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		//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)
		for (int i = 0; i < slots.Length; i++)
		{
			slots[i].inventory.RegisterNetworkMessages("CabMagTransferData", $"Slot{i}");
		}
		NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("CabMagTransferData", new HandleNamedMessageDelegate(NetworkMessageReceived));
		if (NetworkManager.Singleton.IsServer)
		{
			LoadCabinetDataIfExists();
		}
		else
		{
			RequestSyncServerRPC(0uL);
		}
	}

	private void SpawnItemServerRPC(ReducedItem item = default(ReducedItem), ulong client = 0uL, bool received = false, FastBufferReader data = default(FastBufferReader))
	{
		//IL_000a: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		if (received)
		{
			item = ReducedItem.Read(data);
			Item val = ItemFromID(item.ID);
			GameObject val2 = Object.Instantiate<GameObject>(val.spawnPrefab, ((Component)this).transform.position + Vector3.up, Quaternion.identity, StartOfRound.Instance.elevatorTransform);
			GrabbableObject component = val2.GetComponent<GrabbableObject>();
			component.fallTime = 1f;
			component.hasHitGround = true;
			component.scrapPersistedThroughRounds = true;
			component.isInElevator = true;
			component.isInShipRoom = true;
			((ReducedItem)(ref item)).ApplyToGrabbable(component);
			((NetworkBehaviour)component).NetworkObject.Spawn(false);
			SyncNewItemClientRPC(NetworkObjectReference.op_Implicit(((NetworkBehaviour)component).NetworkObject), item, 0uL);
			return;
		}
		FastBufferWriter val3 = default(FastBufferWriter);
		((FastBufferWriter)(ref val3))..ctor(128, (Allocator)2, -1);
		try
		{
			int num = 1;
			((FastBufferWriter)(ref val3)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			((ReducedItem)(ref item)).Write(val3);
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("CabMagTransferData", 0uL, val3, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val3)).Dispose();
		}
	}

	private void RequestSyncServerRPC(ulong client = 0uL, bool received = false, FastBufferReader data = default(FastBufferReader))
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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)
		if (received)
		{
			for (int i = 0; i < slots.Length; i++)
			{
				slots[i].inventory.SyncAllClientRPC(false, client, false, default(FastBufferReader));
			}
			return;
		}
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1);
		try
		{
			int num = 0;
			((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("CabMagTransferData", 0uL, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	private IEnumerator waitUntilSpawnToAssignData(NetworkObjectReference netObjRef, ReducedItem item)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		float startTime = Time.realtimeSinceStartup;
		NetworkObject networkObject = null;
		while (Time.realtimeSinceStartup - startTime <= 8f && !((NetworkObjectReference)(ref netObjRef)).TryGet(ref networkObject, (NetworkManager)null))
		{
			yield return (object)new WaitForSeconds(0.03f);
		}
		if (!((Object)(object)networkObject == (Object)null))
		{
			yield return (object)new WaitForEndOfFrame();
			GrabbableObject grabbable = ((Component)networkObject).GetComponent<GrabbableObject>();
			grabbable.fallTime = 1f;
			grabbable.hasHitGround = true;
			grabbable.scrapPersistedThroughRounds = true;
			grabbable.isInElevator = true;
			grabbable.isInShipRoom = true;
			((ReducedItem)(ref item)).ApplyToGrabbable(grabbable);
		}
	}

	private void SyncNewItemClientRPC(NetworkObjectReference netObjToSync = default(NetworkObjectReference), ReducedItem item = default(ReducedItem), ulong client = 0uL, bool received = false, FastBufferReader data = default(FastBufferReader))
	{
		//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_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_0027: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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)
		if (received)
		{
			((FastBufferReader)(ref data)).ReadValueSafe<NetworkObjectReference>(ref netObjToSync, default(ForNetworkSerializable));
			item = ReducedItem.Read(data);
			((MonoBehaviour)this).StartCoroutine(waitUntilSpawnToAssignData(netObjToSync, item));
			return;
		}
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1);
		try
		{
			int num = 2;
			((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe<NetworkObjectReference>(ref netObjToSync, default(ForNetworkSerializable));
			((ReducedItem)(ref item)).Write(val);
			NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("CabMagTransferData", client, val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	private void NetworkMessageReceived(ulong senderID, FastBufferReader message)
	{
		//IL_0007: 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_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: 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)
		int num = default(int);
		((FastBufferReader)(ref message)).ReadValueSafe<int>(ref num, default(ForPrimitives));
		Singleton<CabinetStorage>.Logger.LogInfo((object)$"[CabinetManager] Received network message {(NetworkMessageType)num}");
		switch ((NetworkMessageType)num)
		{
		case NetworkMessageType.ServerRequestSync:
			RequestSyncServerRPC(senderID, received: true, message);
			break;
		case NetworkMessageType.ServerSpawnItem:
		{
			FastBufferReader data = message;
			SpawnItemServerRPC(default(ReducedItem), senderID, received: true, data);
			break;
		}
		case NetworkMessageType.ClientSyncNewItem:
		{
			FastBufferReader data = message;
			SyncNewItemClientRPC(default(NetworkObjectReference), default(ReducedItem), 0uL, received: true, data);
			break;
		}
		default:
			throw new ArgumentOutOfRangeException();
		}
	}

	public void OnDestroy()
	{
		for (int i = 0; i < slots.Length; i++)
		{
			slots[i].inventory.PostContentsChanged -= UpdateHoverInformation;
		}
		NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("CabMagTransferData");
	}

	private bool CanStoreItemInSlot(GrabbableObject item, int slot)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)item))
		{
			return false;
		}
		Item tItem = item.itemProperties;
		bool flag = slots[slot].inventory.Contents.Count == 0;
		bool flag2 = !flag && ItemFromID(slots[slot].inventory.Contents[0].ID).isScrap;
		bool isScrap = tItem.isScrap;
		bool result = !flag && ItemToID(tItem) == slots[slot].inventory.Contents[0].ID;
		if (!StartOfRound.Instance.allItemsList.itemsList.Exists((Item f) => ItemToID(f) == ItemToID(tItem)))
		{
			return false;
		}
		if (flag)
		{
			return true;
		}
		if (flag2 && isScrap)
		{
			return true;
		}
		return result;
	}

	private void TakeOrStoreHeldItem(int slot)
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
		GrabbableObject val = (Object.op_Implicit((Object)(object)localPlayerController.currentlyHeldObjectServer) ? localPlayerController.currentlyHeldObjectServer : localPlayerController.currentlyHeldObject);
		if (CanStoreItemInSlot(val, slot))
		{
			slots[slot].inventory.AddItemServerRPC(val);
			localPlayerController.DespawnHeldObject();
		}
		else if (slots[slot].inventory.Contents.Count > 0)
		{
			SpawnItemServerRPC(slots[slot].inventory.Contents[0], 0uL);
			slots[slot].inventory.RemoveItemServerRPC(0, 0uL, false, default(FastBufferReader));
		}
	}

	private void UpdateHoverInformation()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		for (int j = 0; j < slots.Length; j++)
		{
			if (slots[j].inventory.Contents.Count == 0)
			{
				slots[j].trigger.hoverTip = "[USE] Empty Drawer";
				slots[j].trigger.hoverIcon = emptyIcon;
				continue;
			}
			Item val = ItemFromID(slots[j].inventory.Contents[0].ID);
			slots[j].trigger.hoverTip = (val.isScrap ? $"({slots[j].inventory.Contents.Count}) Scrap worth ${slots[j].inventory.Contents.Aggregate(0, (int i, ReducedItem item) => i + item.CreditValue)}" : HoverFormatted(slots[j].inventory.Contents.Count, val.itemName));
			slots[j].trigger.hoverIcon = val.itemIcon;
		}
	}

	private void PrepareHoldTip(int slot)
	{
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
		GrabbableObject val = (Object.op_Implicit((Object)(object)localPlayerController.currentlyHeldObjectServer) ? localPlayerController.currentlyHeldObjectServer : localPlayerController.currentlyHeldObject);
		if (CanStoreItemInSlot(val, slot))
		{
			slots[slot].trigger.timeToHoldSpeedMultiplier = 1f;
			slots[slot].trigger.holdTip = StoreFormatted(val.itemProperties.itemName);
		}
		else if (slots[slot].inventory.Contents.Count != 0)
		{
			slots[slot].trigger.holdTip = GrabFormatted(ItemFromID(slots[slot].inventory.Contents[0].ID).itemName);
		}
		else
		{
			slots[slot].trigger.timeToHoldSpeedMultiplier = 0.1f;
			slots[slot].trigger.holdTip = "Nothing to Store/Take!";
		}
	}

	private void InitializeSlots()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		for (int i = 0; i < slots.Length; i++)
		{
			slots[i] = (CreateNewInteractTrigger(i, ((Component)this).transform), new LethalInventory());
			slots[i].inventory.PostContentsChanged += UpdateHoverInformation;
			slots[i].trigger.hoverTip = "[USE] Empty Drawer";
			slots[i].trigger.hoverIcon = emptyIcon;
		}
	}

	private void LoadCabinetDataIfExists()
	{
		for (int i = 0; i < slots.Length; i++)
		{
			slots[i].inventory.LoadInventoryContents($"Slot{i}", "");
		}
		UpdateHoverInformation();
	}

	internal void SaveCabinetData()
	{
		for (int i = 0; i < slots.Length; i++)
		{
			slots[i].inventory.SaveInventoryContents($"Slot{i}", "");
		}
	}
}
[BepInPlugin("NicholaScott.LethalCompany.CabinetStorage", "Cabinet Item Storage", "0.0.4")]
[BepInDependency("NicholaScott.BepInEx.Utils", "1.2.1")]
[BepInDependency("NicholaScott.LethalCompany.API", "0.0.5")]
public class CabinetStorage : BaseUnityPlugin
{
	public struct Configuration
	{
		public float CooldownBetweenInteract;
	}

	private void Awake()
	{
		Singleton<CabinetStorage>.Instance = this;
		Singleton<CabinetStorage, Configuration>.Configuration = Extensions.BindStruct<Configuration>(((BaseUnityPlugin)this).Config, new Configuration
		{
			CooldownBetweenInteract = 0.25f
		});
		Extensions.PatchAttribute<Production>(Assembly.GetExecutingAssembly(), ((BaseUnityPlugin)this).Info.Metadata.GUID, (Action<object>)null);
	}
}
[Production]
public static class CabinetPatches
{
	private static CabinetManager manager;

	[HarmonyPatch(typeof(StartOfRound), "Start")]
	[HarmonyPostfix]
	public static void BindToFileCabinet(StartOfRound __instance)
	{
		Singleton<CabinetStorage>.Logger.LogInfo((object)NetworkManager.Singleton.IsServer);
		int fileCabId = __instance.unlockablesList.unlockables.FindIndex((UnlockableItem un) => un.unlockableName.ToLower().Contains("cabinet"));
		PlaceableShipObject val = Object.FindObjectsOfType<PlaceableShipObject>().First((PlaceableShipObject pc) => pc.unlockableID == fileCabId);
		manager = ((Component)val).gameObject.AddComponent<CabinetManager>();
	}

	[HarmonyPatch(typeof(GameNetworkManager), "SaveItemsInShip")]
	[HarmonyPostfix]
	public static void SaveFileCabinet()
	{
		if (Object.op_Implicit((Object)(object)manager))
		{
			manager.SaveCabinetData();
		}
	}
}