Decompiled source of VSS ValheimStorageSystem v0.4.0

plugins/VSS/VSS.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.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 VSS
{
	public sealed class VssAccessStand : MonoBehaviour, Interactable, Hoverable
	{
		internal static readonly HashSet<VssAccessStand> Instances = new HashSet<VssAccessStand>();

		internal const string AutoKey = "vss_auto_refill";

		internal const string CollectKey = "vss_auto_collect";

		private bool _registered;

		internal static int Searches;

		internal bool AutoRefill
		{
			get
			{
				ZNetView component = ((Component)this).GetComponent<ZNetView>();
				return component != null && component.IsValid() && component.GetZDO().GetBool("vss_auto_refill", false);
			}
		}

		internal bool AutoCollect
		{
			get
			{
				ZNetView component = ((Component)this).GetComponent<ZNetView>();
				return component != null && component.IsValid() && component.GetZDO().GetBool("vss_auto_collect", false);
			}
		}

		private void Awake()
		{
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			Register(component);
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
		}

		private void Start()
		{
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			Register(component);
		}

		private void Register(ZNetView view)
		{
			if ((Object)(object)view == (Object)null || !view.IsValid())
			{
				return;
			}
			Instances.Add(this);
			if (!_registered)
			{
				_registered = true;
				view.Register<long, bool>("VSS_SetAutoRefill", (Action<long, long, bool>)SetAutoRefill);
				view.Register<long, bool>("VSS_SetAutoCollect", (Action<long, long, bool>)delegate(long sender, long actor, bool enabled)
				{
					SetMaster(sender, actor, enabled, "vss_auto_collect");
				});
			}
		}

		internal void ToggleAutoRefill(Player player)
		{
			//IL_0017: 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_0027: 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 (!((Object)(object)player == (Object)null) && VssSettings.Ready)
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 25f))
				{
					((Component)this).GetComponent<ZNetView>().InvokeRPC("VSS_SetAutoRefill", new object[2]
					{
						player.GetPlayerID(),
						!AutoRefill
					});
				}
			}
		}

		private void SetAutoRefill(long sender, long actor, bool enabled)
		{
			SetMaster(sender, actor, enabled, "vss_auto_refill");
		}

		internal void ToggleAutoCollect(Player player)
		{
			//IL_0017: 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_0027: 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 (!((Object)(object)player == (Object)null) && VssSettings.Ready)
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 25f))
				{
					((Component)this).GetComponent<ZNetView>().InvokeRPC("VSS_SetAutoCollect", new object[2]
					{
						player.GetPlayerID(),
						!AutoCollect
					});
				}
			}
		}

		private void SetMaster(long sender, long actor, bool enabled, string key)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == actor));
			ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
			if (component.IsOwner() && VssSettings.Ready && !((Object)(object)val2 == (Object)null) && val2.IsValid() && val2.GetZDO().GetOwner() == sender && !((Character)val).IsDead())
			{
				Vector3 val3 = ((Component)val).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val3)).sqrMagnitude > 25f) && HasWardAccess(actor, ((Component)this).transform.position))
				{
					component.GetZDO().Set(key, enabled);
					VssGame.ForceSend(ZDOMan.instance, component.GetZDO().m_uid);
				}
			}
		}

		internal static VssAccessStand FindAutomatic(Vector3 origin)
		{
			//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)
			//IL_006a: 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_00a3: 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)
			VssAccessStand vssAccessStand = null;
			float num = VssSettings.Radius * VssSettings.Radius;
			foreach (VssAccessStand instance in Instances)
			{
				if (!((Object)(object)instance == (Object)null) && ((Component)instance).gameObject.activeInHierarchy)
				{
					ZNetView component = ((Component)instance).GetComponent<ZNetView>();
					Piece component2 = ((Component)instance).GetComponent<Piece>();
					Vector3 val = ((Component)instance).transform.position - origin;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (!((Object)(object)component == (Object)null) && component.IsValid() && !((Object)(object)component2 == (Object)null) && !(sqrMagnitude > num) && HasWardAccess(component2.GetCreator(), origin) && HasWardAccess(component2.GetCreator(), ((Component)instance).transform.position) && (sqrMagnitude != num || !((Object)(object)vssAccessStand != (Object)null) || StringComparer.Ordinal.Compare(((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<ZDOID, ZDOID>(ref ((Component)vssAccessStand).GetComponent<ZNetView>().GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString()) < 0))
					{
						vssAccessStand = instance;
						num = sqrMagnitude;
					}
				}
			}
			return vssAccessStand;
		}

		internal static VssAccessStand Find(Vector3 origin, long actor, bool automatic = false)
		{
			//IL_001a: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			Searches++;
			if (Instances.Count == 0 || !HasWardAccess(actor, origin))
			{
				return null;
			}
			float num = VssSettings.Radius * VssSettings.Radius;
			VssAccessStand vssAccessStand = null;
			float num2 = float.MaxValue;
			foreach (VssAccessStand instance in Instances)
			{
				if ((Object)(object)instance == (Object)null || !((Component)instance).gameObject.activeInHierarchy)
				{
					continue;
				}
				Vector3 val = ((Component)instance).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude > num) && !(sqrMagnitude > num2))
				{
					ZNetView component = ((Component)instance).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid() && (!automatic || instance.AutoRefill) && HasWardAccess(actor, ((Component)instance).transform.position) && (sqrMagnitude != num2 || !((Object)(object)vssAccessStand != (Object)null) || StringComparer.Ordinal.Compare(((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<ZDOID, ZDOID>(ref ((Component)vssAccessStand).GetComponent<ZNetView>().GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString()) < 0))
					{
						vssAccessStand = instance;
						num2 = sqrMagnitude;
					}
				}
			}
			return vssAccessStand;
		}

		public string GetHoverText()
		{
			return Localization.instance.Localize("Storage Inventory\n[<color=yellow><b>$KEY_Use</b></color>] Open storage");
		}

		public string GetHoverName()
		{
			return "Storage Inventory";
		}

		public float GetHoverOffset()
		{
			return 0.75f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!hold)
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
				{
					if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
					{
						return true;
					}
					VssUi.Open(val, this);
					return true;
				}
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		internal static bool HasWardAccess(long playerId, Vector3 point)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			List<PrivateArea> wards = VssGame.Wards;
			bool flag = false;
			foreach (PrivateArea item in wards)
			{
				if (!((Object)(object)item == (Object)null) && VssGame.WardEnabled(item) && VssGame.WardInside(item, point, 0f))
				{
					flag = true;
					Piece component = ((Component)item).GetComponent<Piece>();
					if (((Object)(object)component != (Object)null && component.GetCreator() == playerId) || VssGame.WardPermitted(item, playerId))
					{
						return true;
					}
				}
			}
			return !flag;
		}
	}
	internal static class VssAssets
	{
		private const string BundleName = "vss_assets";

		private const string StandPrefabName = "vss_access_stand";

		private static GameObject _standModel;

		private static AssetBundle _bundle;

		internal static Sprite Panel;

		internal static Sprite Wood;

		internal static Sprite Inset;

		internal static Sprite ControllerIcon;

		internal static Sprite ChestIcon;

		internal static bool HasStandModel => (Object)(object)_standModel != (Object)null;

		public static GameObject GetStandModel()
		{
			return ((Object)(object)_standModel != (Object)null) ? Object.Instantiate<GameObject>(_standModel) : VssProceduralStand.CreateModel();
		}

		public static void Load(ManualLogSource log)
		{
			string directoryName = Path.GetDirectoryName(typeof(VssPlugin).Assembly.Location);
			if (string.IsNullOrEmpty(directoryName))
			{
				return;
			}
			string path = Path.Combine(directoryName, "ui");
			Texture2D val = LoadTexture(Path.Combine(directoryName, "icons", "controller.png"), log);
			if ((Object)(object)val != (Object)null)
			{
				ControllerIcon = WholeSprite(val, "Controller icon");
			}
			Texture2D val2 = LoadTexture(Path.Combine(directoryName, "icons", "chest-preference.png"), log);
			if ((Object)(object)val2 != (Object)null)
			{
				ChestIcon = WholeSprite(val2, "Chest preference icon");
			}
			Texture2D val3 = LoadTexture(Path.Combine(path, "outer-frame.png"), log);
			if ((Object)(object)val3 != (Object)null)
			{
				float num = Mathf.Ceil((float)Mathf.Min(((Texture)val3).width, ((Texture)val3).height) * 0.16f);
				Panel = WholeSprite(val3, "Outer frame", num * 100f / 72f, num);
			}
			Texture2D val4 = LoadTexture(Path.Combine(path, "backing.png"), log);
			if ((Object)(object)val4 != (Object)null)
			{
				Wood = WholeSprite(val4, "Continuous oak backing");
			}
			Texture2D val5 = LoadTexture(Path.Combine(path, "panel-skin.png"), log);
			if ((Object)(object)val5 != (Object)null)
			{
				Inset = WholeSprite(val5, "Blank panel skin", 1000f, Mathf.Ceil((float)((Texture)val5).width * 0.055f));
			}
			string text = Path.Combine(directoryName, "vss_assets");
			if (!File.Exists(text))
			{
				log.LogInfo((object)"No vss_assets bundle found; using generated access stand model.");
				return;
			}
			_bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)_bundle == (Object)null)
			{
				log.LogWarning((object)"Could not load vss_assets bundle; using generated access stand model.");
				return;
			}
			_standModel = _bundle.LoadAsset<GameObject>("vss_access_stand");
			if ((Object)(object)_standModel == (Object)null)
			{
				log.LogWarning((object)"vss_assets did not contain prefab vss_access_stand; using generated access stand model.");
			}
			else
			{
				log.LogInfo((object)"Loaded VSS_StorageInventory_001 pedestal model from vss_assets.");
			}
		}

		private static Texture2D LoadTexture(string path, ManualLogSource log)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if (!File.Exists(path))
			{
				log.LogWarning((object)("Missing UI layer: " + path));
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			((Object)val).name = "VSS " + Path.GetFileNameWithoutExtension(path);
			return val;
		}

		private static Sprite WholeSprite(Texture2D texture, string name, float pixelsPerUnit = 100f, float border = 0f)
		{
			//IL_001a: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), pixelsPerUnit, 0u, (SpriteMeshType)0, Vector4.one * border);
			((Object)val).name = "VSS " + name;
			return val;
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	internal static class VssBuildingPatch
	{
		private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

		private static readonly FieldRef<Player, float> LastTool = AccessTools.FieldRefAccess<Player, float>("m_lastToolUseTime");

		private static readonly FieldRef<Player, int> Debt = AccessTools.FieldRefAccess<Player, int>("m_buildRemoveDebt");

		private static readonly Func<Player, float> Stamina = AccessTools.MethodDelegate<Func<Player, float>>(AccessTools.Method(typeof(Player), "GetBuildStamina", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<Player, ItemData, float> Durability = AccessTools.MethodDelegate<Func<Player, ItemData, float>>(AccessTools.Method(typeof(Player), "GetPlaceDurability", (Type[])null, (Type[])null), (object)null, true);

		private static bool Prefix(Player __instance, Piece piece, ref bool __result)
		{
			//IL_0056: 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_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: 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)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || VssResources.Current != null || __instance.NoCostCheat() || ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey()))
			{
				return true;
			}
			VssAccessStand vssAccessStand = VssAccessStand.Find(((Component)__instance).transform.position, __instance.GetPlayerID());
			if ((Object)(object)vssAccessStand == (Object)null)
			{
				return true;
			}
			VssContext context = new VssContext
			{
				Stand = vssAccessStand,
				Player = __instance,
				Actor = __instance.GetPlayerID(),
				Mode = VssAccessMode.Resources
			};
			List<Container> source = VssStorageScanner.Sources(context);
			List<VssNeed> needs = VssMaterialPlan.Needs(__instance, piece.m_resources, 0, 1);
			VssMaterialPlan plan = VssMaterialPlan.Build(((Humanoid)__instance).GetInventory(), source.Select((Container c) => c.GetInventory()), needs);
			if (plan == null)
			{
				__result = false;
				return false;
			}
			if (!plan.UsesStorage)
			{
				return true;
			}
			if (VssTransfer.Busy)
			{
				__result = false;
				return false;
			}
			Player player = __instance;
			ItemData tool = ((Humanoid)player).RightItem;
			GameObject ghost = Ghost.Invoke(player);
			if (tool == null || (Object)(object)ghost == (Object)null)
			{
				__result = false;
				return false;
			}
			Vector3 position = ghost.transform.position;
			Quaternion rotation = ghost.transform.rotation;
			VssTransactions.Start(context, source.Where((Container c) => plan.ChestInventories.Contains(c.GetInventory())), Guard, delegate(List<Container> locked)
			{
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Invalid comparison between Unknown and I4
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Invalid comparison between Unknown and I4
				//IL_023a: Unknown result type (might be due to invalid IL or missing references)
				//IL_023f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0251: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bb: Invalid comparison between Unknown and I4
				VssMaterialPlan vssMaterialPlan = VssMaterialPlan.Build(((Humanoid)player).GetInventory(), locked.Select((Container c) => c.GetInventory()), needs);
				if (vssMaterialPlan != null && vssMaterialPlan.Validate())
				{
					vssMaterialPlan.Player = player;
					vssMaterialPlan.Requirements = piece.m_resources;
					VssResources.Current = vssMaterialPlan;
					try
					{
						if (!player.HaveRequirements(piece, (RequirementMode)0))
						{
							return false;
						}
						if (!player.TryPlacePiece(piece))
						{
							return false;
						}
						vssMaterialPlan.Pay();
						Hud instance = Hud.instance;
						if (instance != null)
						{
							instance.m_buildUi.AddRecentPiece(piece);
						}
						LastTool.Invoke(player) = Time.time;
						((Character)player).UseStamina(Stamina(player));
						PieceTable buildPieces = tool.m_shared.m_buildPieces;
						if ((Object)(object)buildPieces != (Object)null && (int)buildPieces.m_skill > 0)
						{
							if ((int)buildPieces.m_skill == 107)
							{
								Game.instance.IncrementPlayerStat((PlayerStatType)168, 1f, false);
							}
							if (Debt.Invoke(player) > 0)
							{
								Debt.Invoke(player)--;
							}
							else
							{
								((Character)player).RaiseSkill(buildPieces.m_skill, 1f);
								if ((int)buildPieces.m_skill == 107)
								{
									Game.instance.IncrementPlayerStat((PlayerStatType)169, 1f, false);
								}
							}
						}
						if (tool.m_shared.m_useDurability)
						{
							ItemData obj = tool;
							obj.m_durability -= Durability(player, tool) * Game.m_durabilityRate;
						}
						tool.m_shared.m_buildEffect.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, ((Character)player).GetZDOID());
						return true;
					}
					finally
					{
						VssResources.Current = null;
					}
				}
				return false;
			}, delegate(string error)
			{
				if (!string.IsNullOrEmpty(error) && (Object)(object)player != (Object)null)
				{
					((Character)player).Message((MessageType)1, error, 0, (Sprite)null, false);
				}
			});
			__result = false;
			return false;
			bool Guard()
			{
				//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_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: 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)
				int result;
				if ((Object)(object)player.GetSelectedPiece() == (Object)(object)piece && ((Humanoid)player).RightItem == tool && (Object)(object)Ghost.Invoke(player) == (Object)(object)ghost && !InventoryGui.IsVisible() && (Object)(object)ghost != (Object)null)
				{
					Vector3 val = ghost.transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude < 0.0025f && Quaternion.Angle(ghost.transform.rotation, rotation) < 1f)
					{
						result = (((Character)player).HaveStamina(Stamina(player)) ? 1 : 0);
						goto IL_00ce;
					}
				}
				result = 0;
				goto IL_00ce;
				IL_00ce:
				return (byte)result != 0;
			}
		}
	}
	public sealed class VssChestBridge : MonoBehaviour
	{
		internal const string TokenKey = "vss_lease_token";

		internal const string UntilKey = "vss_lease_until";

		private Container _chest;

		private ZNetView _view;

		private string _pendingToken;

		private long _expectedOwner;

		internal bool Rejected { get; private set; }

		internal bool Granted { get; private set; }

		internal static long Now => ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime().Ticks : 0;

		internal static bool IsLeased(ZDO zdo)
		{
			return zdo != null && VssLeaseRules.Active(zdo.GetLong("vss_lease_until", 0L), Now);
		}

		private void Awake()
		{
			_chest = ((Component)this).GetComponent<Container>();
			_view = (((Object)(object)_chest != (Object)null) ? VssGame.View.Invoke(_chest) : null);
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_view.Register<ZPackage>("VSS_AcquireV3", (Action<long, ZPackage>)Request);
			_view.Register<string, bool>("VSS_Grant", (Action<long, string, bool>)Reply);
		}

		internal string Begin(Player player, VssAccessStand stand)
		{
			return Begin(new VssContext
			{
				Player = player,
				Actor = player.GetPlayerID(),
				Stand = stand,
				Mode = VssAccessMode.Grid
			});
		}

		internal string Begin(VssContext context)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_005b: 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)
			Granted = false;
			Rejected = false;
			_pendingToken = Guid.NewGuid().ToString("N");
			_expectedOwner = _view.GetZDO().GetOwner();
			string pendingToken = _pendingToken;
			ZPackage val = new ZPackage();
			val.Write(context.Actor);
			val.Write(context.StandId);
			val.Write(context.TargetId);
			val.Write((int)context.Mode);
			val.Write(pendingToken);
			_view.InvokeRPC("VSS_AcquireV3", new object[1] { val });
			return pendingToken;
		}

		private void Request(long sender, ZPackage package)
		{
			//IL_0024: 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_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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			if (!_view.IsOwner())
			{
				return;
			}
			long num;
			ZDOID val;
			ZDOID val2;
			VssAccessMode mode;
			string text;
			try
			{
				num = package.ReadLong();
				val = package.ReadZDOID();
				val2 = package.ReadZDOID();
				mode = (VssAccessMode)package.ReadInt();
				text = package.ReadString();
			}
			catch
			{
				return;
			}
			ZDO zDO = _view.GetZDO();
			if (!VssSettings.Ready || string.IsNullOrEmpty(text) || text.Length > 64 || _chest.IsInUse() || IsLeased(zDO) || !VssStorageScanner.Supported(_chest) || !VssGame.CheckAccess(_chest, num))
			{
				Deny(sender, text);
				return;
			}
			ZDO zDO2 = ZDOMan.instance.GetZDO(val);
			ZDO target = ((val2 == ZDOID.None) ? null : ZDOMan.instance.GetZDO(val2));
			if (VssContext.Authorize(sender, num, zDO2, target, mode))
			{
				Vector3 val3 = zDO2.GetPosition() - ((Component)this).transform.position;
				if (!(((Vector3)(ref val3)).sqrMagnitude > VssSettings.Radius * VssSettings.Radius) && (!_chest.m_checkGuardStone || VssAccessStand.HasWardAccess(num, ((Component)this).transform.position)) && VssAccessStand.HasWardAccess(num, zDO2.GetPosition()))
				{
					VssGame.Load(_chest);
					zDO.Set("vss_lease_token", text);
					zDO.Set("vss_lease_until", Now + TimeSpan.FromSeconds(10.0).Ticks);
					zDO.SetOwner(sender);
					ZDOMan.instance.ForceSendZDO(sender, zDO.m_uid);
					_view.InvokeRPC(sender, "VSS_Grant", new object[2] { text, true });
					return;
				}
			}
			Deny(sender, text);
		}

		private void Deny(long sender, string token)
		{
			_view.InvokeRPC(sender, "VSS_Grant", new object[2]
			{
				token ?? "",
				false
			});
		}

		private void Reply(long sender, string token, bool accepted)
		{
			if (!(token != _pendingToken) && sender == _expectedOwner)
			{
				Granted = accepted;
				Rejected = !accepted;
			}
		}

		internal bool CanCommit(string token)
		{
			return (Object)(object)_view != (Object)null && _view.IsValid() && VssLeaseRules.CanCommit(_view.IsOwner(), _view.GetZDO().GetString("vss_lease_token", ""), token, _view.GetZDO().GetLong("vss_lease_until", 0L), Now);
		}

		internal void Release(string token)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (_pendingToken == token)
			{
				_pendingToken = null;
			}
			if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner() && !(_view.GetZDO().GetString("vss_lease_token", "") != token))
			{
				_chest.SetInUse(false);
				_view.GetZDO().Set("vss_lease_until", 0L);
				_view.GetZDO().Set("vss_lease_token", "");
				VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class VssContainerAwakePatch
	{
		private static void Postfix(Container __instance)
		{
			if (VssStorageScanner.Supported(__instance))
			{
				VssStorageScanner.Containers.Add(__instance);
				if ((Object)(object)((Component)__instance).GetComponent<VssChestBridge>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<VssChestBridge>();
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class VssVanillaChestLeasePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Container), "RPC_RequestOpen", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Container), "RPC_RequestStack", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Container), "RPC_RequestTakeAll", (Type[])null, (Type[])null);
		}

		private static bool Prefix(Container __instance, long __0, MethodBase __originalMethod)
		{
			ZNetView val = VssGame.View.Invoke(__instance);
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner() || !VssChestBridge.IsLeased(val.GetZDO()))
			{
				return true;
			}
			string text = ((__originalMethod.Name == "RPC_RequestOpen") ? "RPC_OpenResponse" : ((__originalMethod.Name == "RPC_RequestStack") ? "RPC_StackResponse" : "RPC_TakeAllResponse"));
			val.InvokeRPC(__0, text, new object[1] { false });
			return false;
		}
	}
	public sealed class VssRefillBridge : MonoBehaviour
	{
		internal const string CollectKey = "vss_object_auto_collect";

		private string _collectRequest;

		private long _collectOwner;

		private float _collectUntil;

		private static float _nextCollect;

		private static int _collectCursor;

		private static readonly MethodInfo SetCookingSlot = AccessTools.Method(typeof(CookingStation), "SetSlot", (Type[])null, (Type[])null);

		private static readonly object EmptySlotStatus = Enum.ToObject(SetCookingSlot.GetParameters()[3].ParameterType, 0);

		internal const string AutoKey = "vss_object_auto_refill";

		internal static readonly HashSet<VssRefillBridge> Instances = new HashSet<VssRefillBridge>();

		private ZNetView _view;

		private Smelter _smelter;

		private Fireplace _fire;

		private CookingStation _cooking;

		private ShieldGenerator _shield;

		private string _request;

		private long _expectedOwner;

		private float _requestUntil;

		private float _lastUse;

		private string _autoRequest;

		private long _autoOwner;

		private float _autoUntil;

		private Player _hintPlayer;

		private VssAccessStand _hintStand;

		private Vector3 _hintPosition;

		private float _hintUntil;

		private float _hintRadius;

		private bool _hintAuto;

		private bool _hintMaster;

		private bool _hintCollect;

		private bool _hintCollectMaster;

		private KeyboardShortcut _hintRefillKey;

		private KeyboardShortcut _hintCollectKey;

		private string _hintText;

		private static float _nextAuto;

		private static int _cursor;

		private static readonly Func<CookingStation, bool> CookingFire = AccessTools.MethodDelegate<Func<CookingStation, bool>>(AccessTools.Method(typeof(CookingStation), "IsFireLit", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<CookingStation, int> FreeSlot = AccessTools.MethodDelegate<Func<CookingStation, int>>(AccessTools.Method(typeof(CookingStation), "GetFreeSlot", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<CookingStation, bool> DoneFood = AccessTools.MethodDelegate<Func<CookingStation, bool>>(AccessTools.Method(typeof(CookingStation), "HaveDoneItem", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Smelter, long> SmelterFuel = AccessTools.MethodDelegate<Action<Smelter, long>>(AccessTools.Method(typeof(Smelter), "RPC_AddFuel", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Smelter, long, string, bool> SmelterInput = AccessTools.MethodDelegate<Action<Smelter, long, string, bool>>(AccessTools.Method(typeof(Smelter), "RPC_AddOre", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Fireplace, long> FireFuel = AccessTools.MethodDelegate<Action<Fireplace, long>>(AccessTools.Method(typeof(Fireplace), "RPC_AddFuel", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<CookingStation, long> CookingFuel = AccessTools.MethodDelegate<Action<CookingStation, long>>(AccessTools.Method(typeof(CookingStation), "RPC_AddFuel", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<CookingStation, long, string, bool> CookingInput = AccessTools.MethodDelegate<Action<CookingStation, long, string, bool>>(AccessTools.Method(typeof(CookingStation), "RPC_AddItem", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<ShieldGenerator, long> ShieldFuel = AccessTools.MethodDelegate<Action<ShieldGenerator, long>>(AccessTools.Method(typeof(ShieldGenerator), "RPC_AddFuel", (Type[])null, (Type[])null), (object)null, true);

		internal bool AutoCollect => (Object)(object)_view != (Object)null && _view.IsValid() && _view.GetZDO().GetBool("vss_object_auto_collect", false);

		internal bool CanAutoCollect => ((Object)(object)_smelter != (Object)null && _smelter.m_conversion.Any((ItemConversion c) => (Object)(object)c.m_to != (Object)null)) || ((Object)(object)_cooking != (Object)null && _cooking.m_slots != null && _cooking.m_slots.Length != 0 && _cooking.m_conversion.Any((ItemConversion c) => (Object)(object)c.m_to != (Object)null));

		internal bool AutoRefill => (Object)(object)_view != (Object)null && _view.IsValid() && _view.GetZDO().GetBool("vss_object_auto_refill", false);

		internal bool CanAutoRefill => ((Object)(object)_smelter != (Object)null && ((_smelter.m_maxFuel > 0 && (Object)(object)_smelter.m_fuelItem != (Object)null) || (_smelter.m_maxOre > 0 && _smelter.m_conversion.Count > 0))) || ((Object)(object)_fire != (Object)null && _fire.m_canRefill && !_fire.m_infiniteFuel && _fire.m_maxFuel > 0f && (Object)(object)_fire.m_fuelItem != (Object)null) || ((Object)(object)_cooking != (Object)null && _cooking.m_useFuel && _cooking.m_maxFuel > 0 && (Object)(object)_cooking.m_fuelItem != (Object)null) || ((Object)(object)_shield != (Object)null && _shield.m_maxFuel > 0 && _shield.m_fuelItems.Count > 0);

		internal static bool CollectEnabled(ZDO controller, ZDO target)
		{
			return controller != null && target != null && controller.GetBool("vss_auto_collect", false) && target.GetBool("vss_object_auto_collect", false);
		}

		internal static bool CollectSupportedPrefab(int hash)
		{
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(hash) : null);
			return (Object)(object)val != (Object)null && ((Object)(object)val.GetComponentInChildren<Smelter>(true) != (Object)null || (Object)(object)val.GetComponentInChildren<CookingStation>(true) != (Object)null);
		}

		private void RegisterCollectRpc()
		{
			_view.Register<long, bool, string>("VSS_SetObjectCollect", (Action<long, long, bool, string>)SetAutoCollect);
			_view.Register<string, bool, bool>("VSS_ObjectCollectResult", (Action<long, string, bool, bool>)CollectReply);
		}

		private bool CanToggleCollect(Player player)
		{
			//IL_0055: 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_0065: 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_0085: 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)
			int result;
			if ((Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && VssSettings.Ready && (Object)(object)_view != (Object)null && _view.IsValid() && CanAutoCollect)
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude <= 25f && VssAccessStand.HasWardAccess(player.GetPlayerID(), ((Component)this).transform.position))
				{
					result = (((Object)(object)VssAccessStand.Find(((Component)this).transform.position, player.GetPlayerID()) != (Object)null) ? 1 : 0);
					goto IL_00b1;
				}
			}
			result = 0;
			goto IL_00b1;
			IL_00b1:
			return (byte)result != 0;
		}

		internal bool ToggleAutoCollect(Player player)
		{
			if ((Object)(object)player != (Object)(object)Player.m_localPlayer || !CanToggleCollect(player))
			{
				return false;
			}
			if (_collectRequest != null && Time.unscaledTime < _collectUntil)
			{
				return true;
			}
			_collectRequest = Guid.NewGuid().ToString("N");
			_collectOwner = _view.GetZDO().GetOwner();
			_collectUntil = Time.unscaledTime + 3f;
			_view.InvokeRPC("VSS_SetObjectCollect", new object[3]
			{
				player.GetPlayerID(),
				!AutoCollect,
				_collectRequest
			});
			return true;
		}

		private void SetAutoCollect(long sender, long actor, bool enabled, string token)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner() && !string.IsNullOrEmpty(token) && token.Length <= 64)
			{
				Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == actor));
				ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
				bool flag = (Object)(object)val2 != (Object)null && val2.IsValid() && val2.GetZDO().GetOwner() == sender && CanToggleCollect(val);
				if (flag)
				{
					_view.GetZDO().Set("vss_object_auto_collect", enabled);
					VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
				}
				_view.InvokeRPC(sender, "VSS_ObjectCollectResult", new object[3] { token, flag, AutoCollect });
			}
		}

		private void CollectReply(long sender, string token, bool accepted, bool enabled)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (sender == _collectOwner && !(token != _collectRequest))
			{
				_collectRequest = null;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					VssAccessStand vssAccessStand = VssAccessStand.Find(((Component)this).transform.position, localPlayer.GetPlayerID());
					((Character)localPlayer).Message((MessageType)1, (!accepted) ? "Cannot change VSS auto-collect here." : ("VSS auto-collect: " + (enabled ? "On" : "Off") + ((enabled && ((Object)(object)vssAccessStand == (Object)null || !vssAccessStand.AutoCollect)) ? " (collection master Off)." : ".")), 0, (Sprite)null, false);
				}
			}
		}

		internal static void CollectTick()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!VssSettings.Ready || VssTransfer.Busy || Time.unscaledTime < _nextCollect || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			_nextCollect = Time.unscaledTime + 0.5f;
			Instances.RemoveWhere((VssRefillBridge s) => (Object)(object)s == (Object)null);
			List<VssRefillBridge> list = Instances.Where((VssRefillBridge s) => (Object)(object)s._view != (Object)null && s._view.IsValid() && s._view.IsOwner() && ((Component)s).gameObject.activeInHierarchy && s.AutoCollect && s.CanAutoCollect).OrderBy<VssRefillBridge, string>((VssRefillBridge s) => ((object)Unsafe.As<ZDOID, ZDOID>(ref s._view.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal).ToList();
			for (int num = 0; num < list.Count; num++)
			{
				int num2 = (_collectCursor + num) % list.Count;
				VssRefillBridge vssRefillBridge = list[num2];
				VssAccessStand vssAccessStand = VssAccessStand.FindAutomatic(((Component)vssRefillBridge).transform.position);
				if (!((Object)(object)vssAccessStand == (Object)null) && vssAccessStand.AutoCollect)
				{
					VssContext context = new VssContext
					{
						Stand = vssAccessStand,
						Actor = ((Component)vssAccessStand).GetComponent<Piece>().GetCreator(),
						Target = vssRefillBridge._view,
						Mode = VssAccessMode.AutomaticCollect
					};
					if (vssRefillBridge.RunCollect(context))
					{
						_collectCursor = (num2 + 1) % list.Count;
						break;
					}
				}
			}
		}

		internal ItemData CookedOutput(int slot, out string name, out int status, out bool cheated)
		{
			name = _view.GetZDO().GetString("slot" + slot, "");
			status = _view.GetZDO().GetInt("slotstatus" + slot, 0);
			cheated = _view.GetZDO().GetBool(ZDOVars.s_cheatedQueued + slot, false);
			if (string.IsNullOrEmpty(name) || status == 0)
			{
				return null;
			}
			string itemName = name;
			ItemDrop val = (ItemDrop)(((Object)(object)_cooking.m_overCookedItem != (Object)null && itemName == ((Object)_cooking.m_overCookedItem).name) ? ((object)_cooking.m_overCookedItem) : ((object)_cooking.m_conversion.Select((ItemConversion c) => c.m_to).FirstOrDefault((Func<ItemDrop, bool>)((ItemDrop d) => (Object)(object)d != (Object)null && ((Object)d).name == itemName))));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ItemData val2 = val.m_itemData.Clone();
			val2.m_dropPrefab = ((Component)val).gameObject;
			val2.m_stack = 1;
			val2.m_equipped = false;
			val2.m_worldLevel = (byte)Game.m_worldLevel;
			val2.m_cheated = cheated;
			if (_cooking.m_spawnFullDurability)
			{
				val2.m_durability = val2.m_shared.m_maxDurability;
			}
			return val2;
		}

		internal bool CommitCooked(VssContext context, int slot, Inventory destination)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			if (!context.Valid() || (Object)(object)_cooking == (Object)null || slot < 0 || slot >= _cooking.m_slots.Length)
			{
				return false;
			}
			string name;
			int status;
			bool cheated;
			ItemData val = CookedOutput(slot, out name, out status, out cheated);
			if (val == null || VssInventoryOps.Capacity(destination, val) < 1)
			{
				return false;
			}
			Inventory val2 = new Inventory("VSS cooking output", (Sprite)null, 1, 1);
			val2.GetAllItems().Add(val);
			if (VssInventoryOps.Move(val2, destination, val, 1) != 1)
			{
				return false;
			}
			SetCookingSlot.Invoke(_cooking, new object[5] { slot, "", 0f, EmptySlotStatus, false });
			_view.InvokeRPC(ZNetView.Everybody, "RPC_SetSlotVisual", new object[2] { slot, "" });
			VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
			return true;
		}

		internal bool RunCollect(VssContext context)
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			if (VssTransfer.Busy || !context.Valid())
			{
				return false;
			}
			if ((Object)(object)_cooking != (Object)null)
			{
				for (int i = 0; i < _cooking.m_slots.Length; i++)
				{
					string name;
					int status;
					bool cheated;
					ItemData val = CookedOutput(i, out name, out status, out cheated);
					if (val != null)
					{
						List<Container> sources = VssStorageScanner.Sources(context);
						Container destination = Destination(sources, val);
						if ((Object)(object)destination == (Object)null)
						{
							return false;
						}
						int selected = i;
						return VssTransactions.Start(context, (IEnumerable<Container>)(object)new Container[1] { destination }, () => (Object)(object)this != (Object)null && context.Valid(), (List<Container> locked) => CommitCooked(context, selected, destination.GetInventory()), null);
					}
				}
				return false;
			}
			VssCollectOutput[] array = VssCollectOutput.For(_view.GetZDO().m_uid);
			foreach (VssCollectOutput output in array)
			{
				if ((Object)(object)output == (Object)null || !output.Eligible(this))
				{
					continue;
				}
				Container destination2 = Destination(VssStorageScanner.Sources(context), output.Item.m_itemData);
				if (!((Object)(object)destination2 == (Object)null))
				{
					return VssTransactions.Start(context, (IEnumerable<Container>)(object)new Container[1] { destination2 }, () => (Object)(object)this != (Object)null && (Object)(object)output != (Object)null && context.Valid() && output.Eligible(this), (List<Container> locked) => output.Commit(this, context, destination2.GetInventory()), null);
				}
			}
			return false;
		}

		internal static Container Destination(List<Container> sources, ItemData item)
		{
			return (from c in sources
				where VssInventoryOps.Capacity(c.GetInventory(), item) > 0
				orderby (VssInventoryOps.Capacity(c.GetInventory(), item, stacksOnly: true) <= 0) ? 1 : 0, VssPreferences.Rank(c, item)
				select c).FirstOrDefault();
		}

		internal static bool AutoEnabled(ZDO controller, ZDO target)
		{
			return controller != null && target != null && controller.GetBool("vss_auto_refill", false) && target.GetBool("vss_object_auto_refill", false);
		}

		internal static bool SupportedPrefab(int hash)
		{
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(hash) : null);
			return (Object)(object)val != (Object)null && ((Object)(object)val.GetComponentInChildren<Smelter>(true) != (Object)null || (Object)(object)val.GetComponentInChildren<Fireplace>(true) != (Object)null || (Object)(object)val.GetComponentInChildren<CookingStation>(true) != (Object)null || (Object)(object)val.GetComponentInChildren<ShieldGenerator>(true) != (Object)null);
		}

		private void Awake()
		{
			_view = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_smelter = ((Component)this).GetComponentInChildren<Smelter>(true);
			_fire = ((Component)this).GetComponentInChildren<Fireplace>(true);
			_cooking = ((Component)this).GetComponentInChildren<CookingStation>(true);
			_shield = ((Component)this).GetComponentInChildren<ShieldGenerator>(true);
			RegisterRpc();
			Instances.Add(this);
		}

		private void RegisterRpc()
		{
			_view.Register<ZPackage>("VSS_Refill", (Action<long, ZPackage>)Request);
			_view.Register<string, int, string>("VSS_RefillResult", (Action<long, string, int, string>)Reply);
			_view.Register<long, bool, string>("VSS_SetObjectAuto", (Action<long, long, bool, string>)SetAutoRefill);
			_view.Register<string, bool, bool>("VSS_ObjectAutoResult", (Action<long, string, bool, bool>)AutoReply);
			RegisterCollectRpc();
		}

		private bool CanToggle(Player player)
		{
			//IL_0055: 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_0065: 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_0085: 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)
			int result;
			if ((Object)(object)player != (Object)null && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && VssSettings.Ready && (Object)(object)_view != (Object)null && _view.IsValid() && CanAutoRefill)
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude <= 25f && VssAccessStand.HasWardAccess(player.GetPlayerID(), ((Component)this).transform.position))
				{
					result = (((Object)(object)VssAccessStand.Find(((Component)this).transform.position, player.GetPlayerID()) != (Object)null) ? 1 : 0);
					goto IL_00b1;
				}
			}
			result = 0;
			goto IL_00b1;
			IL_00b1:
			return (byte)result != 0;
		}

		internal bool ToggleAutoRefill(Player player)
		{
			if ((Object)(object)player != (Object)(object)Player.m_localPlayer || !CanToggle(player))
			{
				return false;
			}
			if (_autoRequest != null && Time.unscaledTime < _autoUntil)
			{
				return true;
			}
			_autoRequest = Guid.NewGuid().ToString("N");
			_autoOwner = _view.GetZDO().GetOwner();
			_autoUntil = Time.unscaledTime + 3f;
			_view.InvokeRPC("VSS_SetObjectAuto", new object[3]
			{
				player.GetPlayerID(),
				!AutoRefill,
				_autoRequest
			});
			return true;
		}

		private void SetAutoRefill(long sender, long actor, bool enabled, string token)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner() && !string.IsNullOrEmpty(token) && token.Length <= 64)
			{
				Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == actor));
				ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
				bool flag = (Object)(object)val2 != (Object)null && val2.IsValid() && val2.GetZDO().GetOwner() == sender && CanToggle(val);
				if (flag)
				{
					_view.GetZDO().Set("vss_object_auto_refill", enabled);
					VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
				}
				_view.InvokeRPC(sender, "VSS_ObjectAutoResult", new object[3] { token, flag, AutoRefill });
			}
		}

		private void AutoReply(long sender, string token, bool accepted, bool enabled)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (sender == _autoOwner && !(token != _autoRequest))
			{
				_autoRequest = null;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					VssAccessStand vssAccessStand = VssAccessStand.Find(((Component)this).transform.position, localPlayer.GetPlayerID());
					((Character)localPlayer).Message((MessageType)1, (!accepted) ? "Cannot change VSS auto-refill here." : ("VSS auto-refill: " + (enabled ? "On" : "Off") + ((enabled && ((Object)(object)vssAccessStand == (Object)null || !vssAccessStand.AutoRefill)) ? " (controller master Off)." : ".")), 0, (Sprite)null, false);
				}
			}
		}

		internal static string AutoHint(bool enabled, bool master, string key)
		{
			return "\n[<color=yellow><b>" + key + "</b></color>] VSS auto-refill: " + (enabled ? "On" : "Off") + ((enabled && !master) ? " <color=#b0a58d>(master Off)</color>" : "");
		}

		internal unsafe string HoverHint(Player player)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_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)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player == (Object)null) && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && VssSettings.Ready && !((Object)(object)_view == (Object)null) && _view.IsValid() && (CanAutoRefill || CanAutoCollect))
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 25f))
				{
					if (!((Object)(object)_hintPlayer != (Object)(object)player) && !(Time.unscaledTime >= _hintUntil) && _hintRadius == VssSettings.Radius)
					{
						val = ((Component)this).transform.position - _hintPosition;
						if (!(((Vector3)(ref val)).sqrMagnitude > 0.25f))
						{
							goto IL_013d;
						}
					}
					_hintPlayer = player;
					_hintPosition = ((Component)this).transform.position;
					_hintRadius = VssSettings.Radius;
					_hintStand = VssAccessStand.Find(((Component)this).transform.position, player.GetPlayerID());
					_hintUntil = Time.unscaledTime + 0.25f;
					_hintText = null;
					goto IL_013d;
				}
			}
			return "";
			IL_029e:
			return _hintText;
			IL_013d:
			if ((Object)(object)_hintStand == (Object)null)
			{
				return "";
			}
			bool autoRefill = AutoRefill;
			bool autoRefill2 = _hintStand.AutoRefill;
			bool autoCollect = AutoCollect;
			bool autoCollect2 = _hintStand.AutoCollect;
			KeyboardShortcut value = VssPlugin.ModConfig.AutoRefillToggleKey.Value;
			KeyboardShortcut value2 = VssPlugin.ModConfig.AutoCollectToggleKey.Value;
			if (_hintText != null && _hintAuto == autoRefill && _hintMaster == autoRefill2 && _hintCollect == autoCollect && _hintCollectMaster == autoCollect2)
			{
				ref KeyboardShortcut hintRefillKey = ref _hintRefillKey;
				object obj = value;
				if (((object)Unsafe.As<KeyboardShortcut, KeyboardShortcut>(ref hintRefillKey)/*cast due to .constrained prefix*/).Equals(obj))
				{
					ref KeyboardShortcut hintCollectKey = ref _hintCollectKey;
					object obj2 = value2;
					if (((object)Unsafe.As<KeyboardShortcut, KeyboardShortcut>(ref hintCollectKey)/*cast due to .constrained prefix*/).Equals(obj2))
					{
						goto IL_029e;
					}
				}
			}
			_hintAuto = autoRefill;
			_hintMaster = autoRefill2;
			_hintCollect = autoCollect;
			_hintCollectMaster = autoCollect2;
			_hintRefillKey = value;
			_hintCollectKey = value2;
			_hintText = (CanAutoRefill ? AutoHint(autoRefill, autoRefill2, ((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).ToString()) : "") + (CanAutoCollect ? AutoHint(autoCollect, autoCollect2, ((object)(*(KeyboardShortcut*)(&value2))/*cast due to .constrained prefix*/).ToString()).Replace("auto-refill", "auto-collect") : "");
			goto IL_029e;
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
		}

		internal static int FuelRoom(float fuel, float maximum, bool ceil)
		{
			return Math.Max(0, Mathf.FloorToInt(maximum - (ceil ? Mathf.Ceil(fuel) : fuel)));
		}

		internal int Room(VssRefillKind kind)
		{
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				return 0;
			}
			if (kind == VssRefillKind.Fuel)
			{
				if ((Object)(object)_fire != (Object)null && (!_fire.m_canRefill || _fire.m_infiniteFuel || (Object)(object)_fire.m_fuelItem == (Object)null))
				{
					return 0;
				}
				if (((Object)(object)_smelter != (Object)null && (Object)(object)_smelter.m_fuelItem == (Object)null) || ((Object)(object)_cooking != (Object)null && (!_cooking.m_useFuel || (Object)(object)_cooking.m_fuelItem == (Object)null)) || ((Object)(object)_shield != (Object)null && _shield.m_fuelItems.Count == 0))
				{
					return 0;
				}
				float maximum = (((Object)(object)_smelter != (Object)null) ? ((float)_smelter.m_maxFuel) : (((Object)(object)_fire != (Object)null) ? _fire.m_maxFuel : ((float)(((Object)(object)_cooking != (Object)null) ? _cooking.m_maxFuel : (((Object)(object)_shield != (Object)null) ? _shield.m_maxFuel : 0)))));
				return FuelRoom(_view.GetZDO().GetFloat(ZDOVars.s_fuel, ((Object)(object)_shield != (Object)null) ? ((float)_shield.m_defaultFuel) : 0f), maximum, (Object)(object)_fire != (Object)null);
			}
			if ((Object)(object)_smelter != (Object)null)
			{
				return Math.Max(0, _smelter.m_maxOre - _view.GetZDO().GetInt(ZDOVars.s_queued, 0));
			}
			if ((Object)(object)_cooking != (Object)null && (!_cooking.m_requireFire || CookingFire(_cooking)))
			{
				return (FreeSlot(_cooking) >= 0) ? 1 : 0;
			}
			return 0;
		}

		internal bool Allows(ItemData item, VssRefillKind kind, bool automatic)
		{
			if (item == null || item.m_equipped || item.m_stack <= 0 || item.m_worldLevel < Game.m_worldLevel || VssSettings.ProtectedWood(VssItemKey.Prefab(item)) || (automatic && VssSettings.AutoExcluded(VssItemKey.Prefab(item))))
			{
				return false;
			}
			if (kind == VssRefillKind.Fuel)
			{
				ItemDrop val = _smelter?.m_fuelItem ?? _fire?.m_fuelItem ?? _cooking?.m_fuelItem;
				return ((Object)(object)val != (Object)null) ? (val.m_itemData.m_shared.m_name == item.m_shared.m_name) : ((Object)(object)_shield != (Object)null && _shield.m_fuelItems.Any((ItemDrop f) => (Object)(object)f != (Object)null && f.m_itemData.m_shared.m_name == item.m_shared.m_name));
			}
			string prefab = VssItemKey.Prefab(item);
			if ((Object)(object)_smelter != (Object)null)
			{
				return _smelter.m_conversion.Any((ItemConversion c) => (Object)(object)c.m_from != (Object)null && ((Object)c.m_from).name == prefab);
			}
			return !automatic && (Object)(object)_cooking != (Object)null && _cooking.m_conversion.Any((ItemConversion c) => (Object)(object)c.m_from != (Object)null && ((Object)c.m_from).name == prefab);
		}

		private int Measure(VssRefillKind kind)
		{
			return (kind == VssRefillKind.Fuel) ? Mathf.RoundToInt(_view.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) * 10000f) : (((Object)(object)_smelter != (Object)null) ? _view.GetZDO().GetInt(ZDOVars.s_queued, 0) : (((Object)(object)_cooking != (Object)null) ? ((FreeSlot(_cooking) < 0) ? _cooking.m_slots.Length : FreeSlot(_cooking)) : 0));
		}

		private bool AddOne(ItemData item, VssRefillKind kind)
		{
			if (!_view.IsOwner() || Room(kind) <= 0)
			{
				return false;
			}
			int num = Measure(kind);
			try
			{
				if (kind == VssRefillKind.Input)
				{
					if ((Object)(object)_smelter != (Object)null)
					{
						SmelterInput(_smelter, _view.GetZDO().GetOwner(), VssItemKey.Prefab(item), item.m_cheated);
					}
					else if ((Object)(object)_cooking != (Object)null)
					{
						CookingInput(_cooking, _view.GetZDO().GetOwner(), VssItemKey.Prefab(item), item.m_cheated);
					}
				}
				else if ((Object)(object)_smelter != (Object)null)
				{
					SmelterFuel(_smelter, _view.GetZDO().GetOwner());
				}
				else if ((Object)(object)_fire != (Object)null)
				{
					FireFuel(_fire, _view.GetZDO().GetOwner());
				}
				else if ((Object)(object)_cooking != (Object)null)
				{
					CookingFuel(_cooking, _view.GetZDO().GetOwner());
				}
				else if ((Object)(object)_shield != (Object)null)
				{
					ShieldFuel(_shield, _view.GetZDO().GetOwner());
				}
			}
			catch (Exception ex)
			{
				VssPlugin.Log.LogError((object)ex);
			}
			return Measure(kind) > num;
		}

		internal bool SupplyOne(Inventory inventory, ItemData item, VssRefillKind kind, bool automatic)
		{
			if (inventory == null || !inventory.ContainsItem(item) || (automatic && !AutoRefill) || !Allows(item, kind, automatic) || !AddOne(item, kind))
			{
				return false;
			}
			inventory.RemoveOneItem(item);
			return true;
		}

		internal bool Manual(Player player, VssRefillKind kind)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !VssSettings.Ready || (Object)(object)_view == (Object)null || !_view.IsValid() || Room(kind) <= 0 || ((Humanoid)player).GetInventory().GetAllItems().Any((ItemData i) => Allows(i, kind, automatic: false)))
			{
				return false;
			}
			if ((Object)(object)_cooking != (Object)null && kind == VssRefillKind.Input && DoneFood(_cooking))
			{
				return false;
			}
			VssAccessStand vssAccessStand = VssAccessStand.Find(((Component)this).transform.position, player.GetPlayerID());
			if (!((Object)(object)vssAccessStand == (Object)null))
			{
				Vector3 val = ((Component)player).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 25f))
				{
					if ((_request != null && Time.unscaledTime < _requestUntil) || Time.unscaledTime - _lastUse < 0.2f)
					{
						return true;
					}
					VssContext context = new VssContext
					{
						Player = player,
						Actor = player.GetPlayerID(),
						Stand = vssAccessStand,
						Target = _view,
						Mode = VssAccessMode.Resources
					};
					if (!VssStorageScanner.Sources(context).Any((Container c) => c.GetInventory().GetAllItems().Any((ItemData i) => Allows(i, kind, automatic: false))))
					{
						return false;
					}
					_lastUse = Time.unscaledTime;
					_request = Guid.NewGuid().ToString("N");
					_requestUntil = Time.unscaledTime + 8f;
					_expectedOwner = _view.GetZDO().GetOwner();
					ZPackage val2 = new ZPackage();
					val2.Write(player.GetPlayerID());
					val2.Write(((Component)vssAccessStand).GetComponent<ZNetView>().GetZDO().m_uid);
					val2.Write((int)kind);
					val2.Write((!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303)) ? 1 : Math.Min(50, Room(kind)));
					val2.Write(_request);
					_view.InvokeRPC("VSS_Refill", new object[1] { val2 });
					return true;
				}
			}
			return false;
		}

		private void Request(long sender, ZPackage packet)
		{
			//IL_0048: 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)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			if (!_view.IsOwner() || !VssSettings.Ready)
			{
				return;
			}
			long actor;
			ZDOID standId;
			VssRefillKind vssRefillKind;
			int num;
			string token;
			try
			{
				actor = packet.ReadLong();
				standId = packet.ReadZDOID();
				vssRefillKind = (VssRefillKind)packet.ReadInt();
				num = packet.ReadInt();
				token = packet.ReadString();
			}
			catch
			{
				return;
			}
			if (!Enum.IsDefined(typeof(VssRefillKind), vssRefillKind) || num < 1 || num > 50 || string.IsNullOrEmpty(token) || token.Length > 64)
			{
				return;
			}
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == actor && !((Character)p).IsDead() && !((Character)p).IsTeleporting()));
			ZNetView val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
			VssAccessStand vssAccessStand = VssAccessStand.Instances.FirstOrDefault((VssAccessStand s) => (Object)(object)s != (Object)null && ((Component)s).GetComponent<ZNetView>().IsValid() && ((Component)s).GetComponent<ZNetView>().GetZDO().m_uid == standId);
			if ((Object)(object)val2 == (Object)null || !val2.IsValid() || val2.GetZDO().GetOwner() != sender || (Object)(object)vssAccessStand == (Object)null)
			{
				return;
			}
			Vector3 val3 = ((Component)val).transform.position - ((Component)this).transform.position;
			if (!(((Vector3)(ref val3)).sqrMagnitude > 25f) && VssAccessStand.HasWardAccess(actor, ((Component)this).transform.position))
			{
				VssContext context = new VssContext
				{
					Stand = vssAccessStand,
					Player = val,
					Actor = actor,
					Target = _view,
					Mode = VssAccessMode.Station
				};
				if (!Run(context, vssRefillKind, num, delegate(int count, string message)
				{
					if ((Object)(object)_view != (Object)null && _view.IsValid())
					{
						_view.InvokeRPC(sender, "VSS_RefillResult", new object[3] { token, count, message });
					}
				}))
				{
					_view.InvokeRPC(sender, "VSS_RefillResult", new object[3] { token, 0, "Storage is empty or busy." });
				}
			}
		}

		private void Reply(long sender, string token, int amount, string message)
		{
			if (sender == _expectedOwner && !(token != _request))
			{
				_request = null;
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, (amount > 0) ? $"Added {amount} from storage." : message, 0, (Sprite)null, false);
				}
			}
		}

		private bool Run(VssContext context, VssRefillKind kind, int maximum, Action<int, string> complete)
		{
			if (VssTransfer.Busy || !context.Valid() || Room(kind) <= 0)
			{
				return false;
			}
			bool automatic = context.Mode == VssAccessMode.Automatic;
			Container source = ((IEnumerable<Container>)VssStorageScanner.Sources(context)).FirstOrDefault((Func<Container, bool>)((Container c) => c.GetInventory().GetAllItems().Any((ItemData i) => Allows(i, kind, automatic))));
			if ((Object)(object)source == (Object)null)
			{
				return false;
			}
			int added = 0;
			return VssTransactions.Start(context, (IEnumerable<Container>)(object)new Container[1] { source }, () => (Object)(object)this != (Object)null && (Object)(object)_view != (Object)null && _view.IsValid() && _view.IsOwner(), delegate
			{
				//IL_0143: Unknown result type (might be due to invalid IL or missing references)
				Inventory inventory = source.GetInventory();
				foreach (ItemData item in inventory.GetAllItems().ToList())
				{
					for (; added < maximum; added++)
					{
						if (Room(kind) <= 0)
						{
							break;
						}
						if (!inventory.ContainsItem(item))
						{
							break;
						}
						if (!Allows(item, kind, automatic))
						{
							break;
						}
						if (automatic && !context.Valid())
						{
							break;
						}
						if (!SupplyOne(inventory, item, kind, automatic))
						{
							break;
						}
					}
					if (added >= maximum || Room(kind) <= 0)
					{
						break;
					}
				}
				if (added > 0)
				{
					VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
				}
				return added > 0;
			}, delegate(string error)
			{
				complete?.Invoke(added, error);
			});
		}

		internal static void Tick()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!VssSettings.Ready || VssTransfer.Busy || Time.unscaledTime < _nextAuto || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			_nextAuto = Time.unscaledTime + 1f;
			Instances.RemoveWhere((VssRefillBridge s) => (Object)(object)s == (Object)null);
			List<VssRefillBridge> list = Instances.Where((VssRefillBridge s) => (Object)(object)s._view != (Object)null && s._view.IsValid() && s._view.IsOwner() && ((Component)s).gameObject.activeInHierarchy && s.AutoRefill && s.CanAutoRefill).OrderBy<VssRefillBridge, string>((VssRefillBridge s) => ((object)Unsafe.As<ZDOID, ZDOID>(ref s._view.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal).ToList();
			for (int num = 0; num < list.Count; num++)
			{
				int num2 = (_cursor + num) % list.Count;
				VssRefillBridge vssRefillBridge = list[num2];
				VssAccessStand vssAccessStand = VssAccessStand.FindAutomatic(((Component)vssRefillBridge).transform.position);
				if ((Object)(object)vssAccessStand == (Object)null || !vssAccessStand.AutoRefill)
				{
					continue;
				}
				VssContext context = new VssContext
				{
					Stand = vssAccessStand,
					Actor = ((Component)vssAccessStand).GetComponent<Piece>().GetCreator(),
					Target = vssRefillBridge._view,
					Mode = VssAccessMode.Automatic
				};
				VssRefillKind[] array = new VssRefillKind[2]
				{
					VssRefillKind.Fuel,
					VssRefillKind.Input
				};
				foreach (VssRefillKind vssRefillKind in array)
				{
					if ((!((Object)(object)vssRefillBridge._cooking != (Object)null) || vssRefillKind != VssRefillKind.Input) && vssRefillBridge.Run(context, vssRefillKind, 50, null))
					{
						_cursor = (num2 + 1) % list.Count;
						return;
					}
				}
			}
		}

		internal static VssRefillBridge From(Component station)
		{
			ZNetView val = station.GetComponent<ZNetView>() ?? station.GetComponentInParent<ZNetView>();
			return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<VssRefillBridge>() : null;
		}
	}
	public sealed class VssCollectOutput : MonoBehaviour
	{
		internal const string SourceKey = "vss_output_machine";

		private static readonly Dictionary<ZDOID, HashSet<VssCollectOutput>> Outputs = new Dictionary<ZDOID, HashSet<VssCollectOutput>>();

		internal static VssRefillBridge Spawning;

		internal ItemDrop Item;

		private ZNetView _view;

		private ZDOID _source;

		private static readonly Action<ItemDrop> Load = AccessTools.MethodDelegate<Action<ItemDrop>>(AccessTools.Method(typeof(ItemDrop), "Load", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<ItemDrop> Save = AccessTools.MethodDelegate<Action<ItemDrop>>(AccessTools.Method(typeof(ItemDrop), "Save", (Type[])null, (Type[])null), (object)null, true);

		private void Awake()
		{
			//IL_004f: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			Item = ((Component)this).GetComponent<ItemDrop>();
			_view = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_view == (Object)null || !_view.IsValid())
			{
				return;
			}
			_source = _view.GetZDO().GetZDOID("vss_output_machine");
			if (!(_source == ZDOID.None))
			{
				if (!Outputs.TryGetValue(_source, out var value))
				{
					value = (Outputs[_source] = new HashSet<VssCollectOutput>());
				}
				value.Add(this);
			}
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (Outputs.TryGetValue(_source, out var value))
			{
				value.Remove(this);
				if (value.Count == 0)
				{
					Outputs.Remove(_source);
				}
			}
		}

		internal static VssCollectOutput[] For(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			HashSet<VssCollectOutput> value;
			return Outputs.TryGetValue(id, out value) ? value.ToArray() : Array.Empty<VssCollectOutput>();
		}

		internal static bool Tagged(ItemDrop item)
		{
			//IL_0026: 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)
			int result;
			if ((Object)(object)item != (Object)null)
			{
				ZNetView component = ((Component)item).GetComponent<ZNetView>();
				if (component != null && component.IsValid())
				{
					result = ((component.GetZDO().GetZDOID("vss_output_machine") != ZDOID.None) ? 1 : 0);
					goto IL_0038;
				}
			}
			result = 0;
			goto IL_0038;
			IL_0038:
			return (byte)result != 0;
		}

		internal static ItemDrop StackCandidate(ItemDrop item)
		{
			return Tagged(item) ? null : item;
		}

		internal static void Track(ItemDrop item)
		{
			if (Tagged(item) && (Object)(object)((Component)item).GetComponent<VssCollectOutput>() == (Object)null)
			{
				((Component)item).gameObject.AddComponent<VssCollectOutput>();
			}
		}

		internal bool Eligible(VssRefillBridge machine)
		{
			//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)
			//IL_005f: 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_006f: 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)
			if (!((Object)(object)Item == (Object)null) && ((Component)this).gameObject.activeInHierarchy && !((Object)(object)_view == (Object)null) && _view.IsValid() && !(_view.GetZDO().GetZDOID("vss_output_machine") != _source))
			{
				Vector3 val = ((Component)this).transform.position - ((Component)machine).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 100f))
				{
					if (!_view.IsOwner())
					{
						Item.RequestOwn();
						return false;
					}
					Load(Item);
					return Item.m_itemData.m_stack > 0;
				}
			}
			return false;
		}

		internal bool Commit(VssRefillBridge machine, VssContext context, Inventory destination)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (!context.Valid() || !Eligible(machine))
			{
				return false;
			}
			Inventory val = new Inventory("VSS machine output", (Sprite)null, 1, 1);
			val.GetAllItems().Add(Item.m_itemData);
			int num = VssInventoryOps.Move(val, destination, Item.m_itemData, Item.m_itemData.m_stack);
			if (num <= 0)
			{
				return false;
			}
			if (Item.m_itemData.m_stack <= 0)
			{
				_view.Destroy();
			}
			else
			{
				Save(Item);
				VssGame.ForceSend(ZDOMan.instance, _view.GetZDO().m_uid);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Smelter), "Spawn")]
	internal static class VssSmelterOutputPatch
	{
		private static void Prefix(Smelter __instance, out VssRefillBridge __state)
		{
			__state = VssCollectOutput.Spawning;
			VssCollectOutput.Spawning = VssRefillBridge.From((Component)(object)__instance);
		}

		private static Exception Finalizer(Exception __exception, VssRefillBridge __state)
		{
			VssCollectOutput.Spawning = __state;
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "OnCreateNew", new Type[]
	{
		typeof(ItemDrop),
		typeof(bool)
	})]
	internal static class VssOutputCreatedPatch
	{
		private static void Postfix(ItemDrop item)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			VssRefillBridge spawning = VssCollectOutput.Spawning;
			ZNetView val = (((Object)(object)spawning != (Object)null) ? ((Component)spawning).GetComponent<ZNetView>() : null);
			ZNetView val2 = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<ZNetView>() : null);
			if (!((Object)(object)spawning == (Object)null) && spawning.AutoCollect && !((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner() && !((Object)(object)val2 == (Object)null) && val2.IsValid() && val2.IsOwner())
			{
				val2.GetZDO().Set("vss_output_machine", val.GetZDO().m_uid);
				ItemDrop.SaveToZDO(item.m_itemData, val2.GetZDO(), -1);
				VssCollectOutput.Track(item);
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	internal static class VssOutputLoadedPatch
	{
		private static void Postfix(ItemDrop __instance)
		{
			VssCollectOutput.Track(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Load")]
	internal static class VssOutputRefreshedPatch
	{
		private static void Postfix(ItemDrop __instance)
		{
			VssCollectOutput.Track(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "SlowUpdate")]
	internal static class VssOutputOwnershipPatch
	{
		private static void Prefix(ItemDrop __instance)
		{
			VssCollectOutput.Track(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "AutoStackItems")]
	internal static class VssOutputStackPatch
	{
		private static bool Prefix(ItemDrop __instance)
		{
			return !VssCollectOutput.Tagged(__instance);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				object operand = instruction.operand;
				if (operand is MethodInfo { Name: "GetComponent" } method && method.ReturnType == typeof(ItemDrop))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(VssCollectOutput), "StackCandidate", (Type[])null, (Type[])null));
				}
			}
		}
	}
	internal static class VssCollectTests
	{
		internal static void Run(Action<bool, string> check, ZNetScene vanilla, GameObject root, ZDOMan manager, ZNetScene scene, Player actor, VssAccessStand controller)
		{
			//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_0019: 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_0052: 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_005c: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Expected O, but got Unknown
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0501: Expected O, but got Unknown
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Expected O, but got Unknown
			//IL_077a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0784: Expected O, but got Unknown
			//IL_0855: Unknown result type (might be due to invalid IL or missing references)
			//IL_085c: Expected O, but got Unknown
			check(((object)VssConfig.MigrateRefillKey(new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()))/*cast due to .constrained prefix*/).Equals((object)new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>())), "legacy G default migrates to F6");
			check(((object)VssConfig.MigrateRefillKey(new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()))/*cast due to .constrained prefix*/).Equals((object)new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>())), "custom refill key remains intact");
			check(((object)VssConfig.MigrateRefillKey(new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }))/*cast due to .constrained prefix*/).Equals((object)new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 })), "custom modified G shortcut remains intact");
			ZDO zDO = ((Component)controller).GetComponent<ZNetView>().GetZDO();
			zDO.Set(ZDOVars.s_creator, actor.GetPlayerID());
			check(!controller.AutoCollect, "collection master starts Off independently of refill");
			controller.ToggleAutoCollect(actor);
			check(controller.AutoCollect && controller.AutoRefill, "native collection master RPC does not alter refill master");
			string[] array = new string[7] { "charcoal_kiln", "smelter", "blastfurnace", "windmill", "piece_spinningwheel", "piece_cookingstation", "piece_oven" };
			foreach (string text in array)
			{
				check(VssRefillBridge.CollectSupportedPrefab(StringExtensionMethods.GetStableHashCode(text)), "native collection machine supported: " + text);
			}
			check(!VssRefillBridge.CollectSupportedPrefab(StringExtensionMethods.GetStableHashCode("piece_groundtorch")), "lamps offer only refill, not collection");
			CookingStation component = vanilla.GetPrefab("piece_cookingstation").GetComponent<CookingStation>();
			GameObject val = new GameObject("VSS isolated collector grill");
			val.transform.SetParent(root.transform);
			ZNetView val2 = val.AddComponent<ZNetView>();
			CookingStation val3 = val.AddComponent<CookingStation>();
			ZDO val4 = manager.CreateNewZDO(Vector3.zero, StringExtensionMethods.GetStableHashCode("piece_cookingstation"));
			val4.SetPrefab(StringExtensionMethods.GetStableHashCode("piece_cookingstation"));
			AccessTools.Field(typeof(ZNetView), "m_zdo").SetValue(val2, val4);
			AccessTools.Field(typeof(CookingStation), "m_nview").SetValue(val3, val2);
			scene.AddInstance(val4, val2);
			val3.m_conversion = component.m_conversion;
			val3.m_overCookedItem = component.m_overCookedItem;
			val3.m_slots = (Transform[])(object)new Transform[2] { val.transform, val.transform };
			val3.m_useFuel = false;
			VssRefillBridge vssRefillBridge = val.AddComponent<VssRefillBridge>();
			AccessTools.Field(typeof(VssRefillBridge), "_view").SetValue(vssRefillBridge, val2);
			AccessTools.Field(typeof(VssRefillBridge), "_cooking").SetValue(vssRefillBridge, val3);
			AccessTools.Method(typeof(VssRefillBridge), "RegisterRpc", (Type[])null, (Type[])null).Invoke(vssRefillBridge, null);
			int visuals = 0;
			val2.Register<int, string>("RPC_SetSlotVisual", (Action<long, int, string>)delegate
			{
				visuals++;
			});
			check(!vssRefillBridge.AutoCollect && vssRefillBridge.CanAutoCollect && !vssRefillBridge.CanAutoRefill, "wood grill supports independent collection without an oven fuel control");
			check(vssRefillBridge.ToggleAutoCollect(actor) && vssRefillBridge.AutoCollect && VssRefillBridge.CollectEnabled(zDO, val4), "native authenticated object collection toggle works");
			VssContext vssContext = new VssContext
			{
				Stand = controller,
				Actor = actor.GetPlayerID(),
				Target = val2,
				Mode = VssAccessMode.AutomaticCollect
			};
			check(vssContext.Valid() && VssContext.Authorize(ZDOMan.GetSessionID(), actor.GetPlayerID(), zDO, val4, VssAccessMode.AutomaticCollect), "owner-side collection authorization uses separate saved switches");
			check(!VssContext.Authorize(ZDOMan.GetSessionID() + 1, actor.GetPlayerID(), zDO, val4, VssAccessMode.AutomaticCollect), "remote non-owner cannot collect output");
			Action<VssRefillBridge, long, long, bool, string> action = AccessTools.MethodDelegate<Action<VssRefillBridge, long, long, bool, string>>(AccessTools.Method(typeof(VssRefillBridge), "SetAutoCollect", (Type[])null, (Type[])null), (object)null, true);
			action(vssRefillBridge, ZDOMan.GetSessionID() + 1, actor.GetPlayerID(), arg4: false, "spoofed");
			check(vssRefillBridge.AutoCollect, "spoofed toggle cannot turn off collection");
			((Component)actor).transform.position = new Vector3(0f, 0f, 6f);
			action(vssRefillBridge, ZDOMan.GetSessionID(), actor.GetPlayerID(), arg4: false, "too-far");
			check(vssRefillBridge.AutoCollect, "collection toggle requires interaction distance");
			((Component)actor).transform.position = Vector3.zero;
			ZPackage val5 = new ZPackage();
			val4.Serialize(val5);
			ZDO val6 = manager.CreateNewZDO(Vector3.zero, 88888);
			val6.Deserialize(new ZPackage(val5.GetArray()));
			check(val6.GetBool("vss_object_auto_collect", false), "collection switch survives native save replication");
			ItemDrop to = val3.m_conversion[0].m_to;
			ItemDrop val7 = val3.m_conversion[0].m_from;
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ObjectDB), "m_itemByHash").GetValue(ObjectDB.instance);
			dictionary[StringExtensionMethods.GetStableHashCode(((Object)to).name)] = ((Component)to).gameObject;
			dictionary[StringExtensionMethods.GetStableHashCode(((Object)val3.m_overCookedItem).name)] = ((Component)val3.m_overCookedItem).gameObject;
			val4.Set("slot0", ((Object)val7).name);
			val4.Set("slotstatus0", 0);
			Inventory val8 = new Inventory("VSS cooked-output destination", (Sprite)null, 1, 1);
			check(!vssRefillBridge.CommitCooked(vssContext, 0, val8) && val8.NrOfItems() == 0, "uncooked food cannot be collected");
			val4.Set("slot0", ((Object)to).name);
			val4.Set("slotstatus0", 1);
			val4.Set(ZDOVars.s_cheatedQueued, true);
			string name;
			int status;
			bool cheated;
			ItemData val9 = vssRefillBridge.CookedOutput(0, out name, out status, out cheated);
			val9.m_stack = val9.m_shared.m_maxStackSize - 1;
			val8.GetAllItems().Add(val9);
			check(vssRefillBridge.CommitCooked(vssContext, 0, val8) && val9.m_stack == val9.m_shared.m_maxStackSize && val4.GetString("slot0", "") == "" && visuals == 1, "finished food stacks exactly once before native slot and visuals clear");
			check(val9.m_cheated && val9.m_worldLevel == Game.m_worldLevel, "cooked output preserves native cheat and world flags");
			check(!vssRefillBridge.CommitCooked(vssContext, 0, val8), "cleared cooking slot cannot duplicate food");
			val4.Set("slot0", ((Object)to).name);
			val4.Set("slotstatus0", 1);
			check(!vssRefillBridge.CommitCooked(vssContext, 0, val8) && val4.GetString("slot0", "") == ((Object)to).name, "full storage leaves finished food on the grill");
			controller.ToggleAutoCollect(actor);
			check(!vssContext.Valid() && !vssRefillBridge.CommitCooked(vssContext, 0, new Inventory("empty", (Sprite)null, 1, 1)) && vssRefillBridge.AutoCollect, "master Off cancels pending collection while retaining object choice");
			check(vssRefillBridge.HoverHint(actor).Contains("F7") && vssRefillBridge.HoverHint(actor).Contains("VSS auto-collect: On") && vssRefillBridge.HoverHint(actor).Contains("master Off"), "grill hover explains separate F7 collection master");
			controller.ToggleAutoCollect(actor);
			ItemDrop[] array2 = (ItemDrop[])(object)new ItemDrop[2] { to, val3.m_overCookedItem };
			ItemDrop[] array3 = array2;
			foreach (ItemDrop val10 in array3)
			{
				val4.Set("slot0", ((Object)val10).name);
				val4.Set("slotstatus0", ((Object)(object)val10 == (Object)(object)to) ? 1 : 2);
				Inventory val11 = new Inventory("VSS cooked or already burnt output", (Sprite)null, 1, 1);
				check(vssRefillBridge.CommitCooked(vssContext, 0, val11) && val11.NrOfItems() == 1 && val11.GetAllItems()[0].m_shared.m_name == val10.m_itemData.m_shared.m_name, "native cooked/burnt output identity is preserved: " + ((Object)val10).name);
			}
			LeasedCooking(check, manager, val4, vssRefillBridge, vssContext, to);
			OutputDrop(check, root, manager, scene, vanilla, controller, actor);
			controller.ToggleAutoCollect(actor);
			check(!controller.AutoCollect && controller.AutoRefill, "collection master restores Off without changing refill");
		}

		private static void LeasedCooking(Action<bool, string> check, ZDOMan manager, ZDO grillZdo, VssRefillBridge bridge, VssContext context, ItemDrop cooked)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_003a: 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_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Expected O, but got Unknown
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			List<Container> list = new List<Container>();
			try
			{
				for (int i = 0; i < 2; i++)
				{
					GameObject val = new GameObject("piece_chest_vss_collection_test");
					val.SetActive(false);
					val.transform.position = new Vector3((float)(i + 1), 0f, 0f);
					ZNetView obj = val.AddComponent<ZNetView>();
					ZDO val2 = manager.CreateNewZDO(val.transform.position, 44444);
					val2.SetPrefab(44444);
					AccessTools.Field(typeof(ZNetView), "m_zdo").SetValue(obj, val2);
					Container val3 = val.AddComponent<Container>();
					val3.m_width = 1;
					val3.m_height = 1;
					list.Add(val3);
					ZNetView.m_initZDO = val2;
					val.SetActive(true);
				}
				ItemData val4 = cooked.m_itemData.Clone();
				val4.m_dropPrefab = ((Component)cooked).gameObject;
				val4.m_worldLevel = (byte)Game.m_worldLevel;
				val4.m_stack = val4.m_shared.m_maxStackSize - 1;
				list[1].GetInventory().GetAllItems().Add(val4);
				VssGame.Notify(list[1].GetInventory());
				grillZdo.Set("slot0", ((Object)cooked).name);
				grillZdo.Set("slotstatus0", 1);
				check(bridge.RunCollect(context), "collection starts the real exclusive chest lease transaction");
				check(!VssTransactions.Busy && list[1].GetInventory().CountItems(val4.m_shared.m_name, -1, true) == val4.m_shared.m_maxStackSize && list[0].GetInventory().NrOfItems() == 0 && grillZdo.GetString("slot0", "") == "", "leased collection stacks in a farther existing stack before a nearer empty chest");
				check(!VssChestBridge.IsLeased(VssGame.View.Invoke(list[1]).GetZDO()), "collection releases its chest lease after commit");
				Inventory val5 = new Inventory("VSS saved collection", (Sprite)null, 1, 1);
				val5.Load(new ZPackage(VssGame.View.Invoke(list[1]).GetZDO().GetByteArray(ZDOVars.s_items, (byte[])null)));
				check(val5.CountItems(val4.m_shared.m_name, -1, true) == val4.m_shared.m_maxStackSize, "leased collected food persists in native chest save");
				grillZdo.Set("slot0", ((Object)cooked).name);
				grillZdo.Set("slotstatus0", 1);
				list[0].SetInUse(true);
				check(!bridge.RunCollect(context) && grillZdo.GetString("slot0", "") == ((Object)cooked).name, "busy and full destinations leave output untouched");
				list[0].SetInUse(false);
			}
			finally
			{
				foreach (Container item in list)
				{
					VssStorageScanner.Containers.Remove(item);
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
			}
		}

		private static void OutputDrop(Action<bool, string> check, GameObject root, ZDOMan manager, ZNetScene scene, ZNetScene vanilla, VssAccessStand controller, Player actor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Expected O, but got Unknown
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Expected O, but got Unknown
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Expected O, but got Unknown
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Expected O, but got Unknown
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Expected O, but got Unknown
			//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Expected O, but got Unknown
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06da: Expected O, but got Unknown
			GameObject val = new GameObject("VSS isolated collector kiln");
			val.transform.SetParent(root.transform);
			ZNetView val2 = val.AddComponent<ZNetView>();
			Smelter val3 = val.AddComponent<Smelter>();
			ZDO val4 = manager.CreateNewZDO(Vector3.zero, StringExtensionMethods.GetStableHashCode("charcoal_kiln"));
			val4.SetPrefab(StringExtensionMethods.GetStableHashCode("charcoal_kiln"));
			AccessTools.Field(typeof(ZNetView), "m_zdo").SetValue(val2, val4);
			AccessTools.Field(typeof(Smelter), "m_nview").SetValue(val3, val2);
			scene.AddInstance(val4, val2);
			val3.m_conversion = vanilla.GetPrefab("charcoal_kiln").GetComponent<Smelter>().m_conversion;
			VssRefillBridge vssRefillBridge = val.AddComponent<VssRefillBridge>();
			AccessTools.Field(typeof(VssRefillBridge), "_view").SetValue(vssRefillBridge, val2);
			AccessTools.Field(typeof(VssRefillBridge), "_smelter").SetValue(vssRefillBridge, val3);
			val4.Set("vss_object_auto_collect", true);
			ItemDrop to = val3.m_conversion[0].m_to;
			GameObject val5 = new GameObject(((Object)to).name);
			val5.SetActive(false);
			ZNetView val6 = val5.AddComponent<ZNetView>();
			ZDO val7 = manager.CreateNewZDO(Vector3.zero, StringExtensionMethods.GetStableHashCode(((Object)to).name));
			val7.SetPrefab(StringExtensionMethods.GetStableHashCode(((Object)to).name));
			AccessTools.Field(typeof(ZNetView), "m_zdo").SetValue(val6, val7);
			val5.SetActive(false);
			ItemDrop val8 = val5.AddComponent<ItemDrop>();
			val8.m_itemData = to.m_itemData.Clone();
			val8.m_itemData.m_dropPrefab = ((Component)to).gameObject;
			val8.m_itemData.m_stack = 7;
			AccessTools.Field(typeof(ItemDrop), "m_nview").SetValue(val8, val6);
			VssCollectOutput.Spawning = vssRefillBridge;
			ItemDrop.OnCreateNew(val8, true);
			VssCollectOutput.Spawning = null;
			check(VssCollectOutput.Tagged(val8) && val7.GetZDOID("vss_output_machine") == val4.m_uid, "native output creation tags exact source machine");
			check((Object)(object)VssCollectOutput.StackCandidate(val8) == (Object)null, "ordinary loose piles cannot absorb tagged output");
			VssCollectOutput component = ((Component)val8).GetComponent<VssCollectOutput>();
			AccessTools.Method(typeof(VssCollectOutput), "Awake", (Type[])null, (Type[])null).Invoke(component, null);
			check(VssCollectOutput.For(val4.m_uid).Contains(component), "output provenance is indexed by machine without scene searches");
			GameObject val9 = new GameObject("ordinary untagged coal");
			val9.transform.SetParent(root.transform);
			ItemDrop val10 = val9.AddComponent<ItemDrop>();
			check((Object)(object)VssCollectOutput.StackCandidate(val10) == (Object)(object)val10, "unrelated loose loot retains vanilla stacking");
			ZPackage val11 = new ZPackage();
			val7.Serialize(val11);
			ZDO val12 = manager.CreateNewZDO(Vector3.zero, 99999);
			val12.Deserialize(new ZPackage(val11.GetArray()));
			check(val12.GetZDOID("vss_output_machine") == val4.m_uid, "output provenance survives native save replication");
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)AccessTools.Field(typeof(ObjectDB), "m_itemByHash").GetValue(ObjectDB.instance);
			dictionary[StringExtensionMethods.GetStableHashCode(((Object)to).name)] = ((Component)to).gameObject;
			((Behaviour)val8).enabled = false;
			ZNetView.m_initZDO = val7;
			val5.SetActive(true);
			scene.AddInstance(val7, val6);
			try
			{
				VssContext context = new VssContext
				{
					Stand = controller,
					Actor = actor.GetPlayerID(),
					Target = val2,
					Mode = VssAccessMode.AutomaticCollect
				};
				Inventory val13 = new Inventory("VSS output chest", (Sprite)null, 1, 1);
				ItemData val14 = val8.m_itemData.Clone();
				val14.m_stack = val14.m_shared.m_maxStackSize - 2;
				val13.GetAllItems().Add(val14);
				check(component.Commit(vssRefillBridge, context, val13) && val14.m_stack == val14.m_shared.m_maxStackSize && val8.m_itemData.m_stack == 5, "machine output deposits only available capacity and leaves remaining loose stack");
				check(!component.Commit(vssRefillBridge, context, val13) && val8.m_itemData.m_stack == 5, "full chest cannot lose or duplicate remaining output");
				val4.Set("vss_object_auto_collect", false);
				check(!component.Commit(vssRefillBridge, context, new Inventory("empty", (Sprite)null, 1, 1)), "object Off cancels pending output deposit");
				val4.Set("vss_object_auto_collect", true);
				val5.transform.position = new Vector3(11f, 0f, 0f);
				check(!component.Commit(vssRefillBridge, context, new Inventory("empty", (Sprite)null, 1, 1)), "output moved away from its machine is not collected");
				val5.transform.position = Vector3.zero;
				Inventory val15 = new Inventory("VSS final output destination", (Sprite)null, 1, 1);
				check(component.Commit(vssRefillBridge, context, val15) && val15.CountItems(to.m_itemData.m_shared.m_name, -1, true) == 5, "remaining output moves exactly once before native world drop is destroyed");
				check(!val6.IsValid(), "depleted output no longer has an active native network view");
			}
			finally
			{
				Object.DestroyImmediate((Object)(object)val5);
			}
			val3.m_outputPoint = val.transform;
			Action<Smelter, string, int> action = AccessTools.MethodDelegate<Action<Smelter, string, int>>(AccessTools.Method(typeof(Smelter), "Spawn", (Type[])null, (Type[])null), (object)null, true);
			action(val3, ((Object)val3.m_conversion[0].m_from).name, 3);
			VssCollectOutput vssCollectOutput = VssCollectOutput.For(val4.m_uid).Single();
			GameObject val16 = null;
			try
			{
				check(vssCollectOutput.Item.m_itemData.m_stack == 3 && !vssCollectOutput.Item.m_itemData.m_cheated && (Object)(object)VssCollectOutput.Spawning == (Object)null, "actual native smelter Spawn is captured with exact stack and restored scope");
				val16 = Object.Instantiate<GameObject>(((Component)to).gameObject, Vector3.zero, Quaternion.identity);
				ItemDrop component2 = val16.GetComponent<ItemDrop>();
				component2.m_itemData.m_stack = 4;
				ItemDrop.OnCreateNew(component2, false);
				ItemDrop.SaveToZDO(component2.m_itemData, ((Component)component2).GetComponent<ZNetView>().GetZDO(), -1);
				Physics.SyncTransforms();
				Action<ItemDrop> action2 = AccessTools.MethodDelegate<Action<ItemDrop>>(AccessTools.Method(typeof(ItemDrop), "AutoStackItems", (Type[])null, (Type[])null), (object)null, true);
				action2(component2);
				action2(vssCollectOutput.Item);
				check(component2.m_itemData.m_stack == 4 && vssCollectOutput.Item.m_itemData.m_stack == 3, "patched native ground auto-stack keeps machine output separate from unrelated loose loot");
				Inventory val17 = new Inventory("VSS native produced output", (Sprite)null, 1, 1);
				VssContext context2 = new VssContext
				{
					Stand = controller,
					Actor = actor.GetPlayerID(),
					Target = val2,
					Mode = VssAccessMode.AutomaticCollect
				};
				check(vssCollectOutput.Commit(vssRefillBridge, context2, val17) && val17.CountItems(to.m_itemData.m_shared.m_name, -1, true) == 3