Decompiled source of BusinessEmployment v1.0.1

BusinessEmployment-IL2CPP.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BusinessEmployment;
using BusinessEmployment.Behaviours;
using BusinessEmployment.BetterSafe;
using BusinessEmployment.Helpers;
using BusinessEmployment.Persistence;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppFishNet.Connection;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.EntityFramework;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Money;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.Storage;
using Il2CppScheduleOne.UI;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using S1API.Building;
using S1API.GameTime;
using S1API.Internal.Abstraction;
using S1API.Items;
using S1API.Lifecycle;
using S1API.Rendering;
using S1API.Saveables;
using S1API.Shops;
using S1API.Storage;
using S1API.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::BusinessEmployment.BusinessEmployment), "BusinessEmployment", "1.0.1", "k073l", null)]
[assembly: MelonColor(1, 255, 195, 86)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BusinessEmployment-IL2CPP")]
[assembly: AssemblyConfiguration("IL2CPP")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+16384da6cef38c83df79b860c11807c9b0d3fcb3")]
[assembly: AssemblyProduct("BusinessEmployment-IL2CPP")]
[assembly: AssemblyTitle("BusinessEmployment-IL2CPP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BusinessEmployment
{
	public static class BuildInfo
	{
		public const string Name = "BusinessEmployment";

		public const string Description = "Adds employees to Businesses. Automates laundering.";

		public const string Author = "k073l";

		public const string Version = "1.0.1";
	}
	public class BusinessEmployment : MelonMod
	{
		[CompilerGenerated]
		private sealed class <AddDelayed>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AddDelayed>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (SafeCreator.SafeAdded)
					{
						return false;
					}
					_logger.Msg("Adding safe to the shop");
					SafeCreator.AddToShop();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static Instance _logger;

		private static MelonPreferences_Category _category;

		internal static MelonPreferences_Entry<float> EmpCut;

		internal static MelonPreferences_Entry<float> SafeCost;

		internal static MelonPreferences_Entry<bool> EnableSafeAutoRestock;

		public override void OnInitializeMelon()
		{
			_logger = ((MelonBase)this).LoggerInstance;
			_logger.Msg("BusinessEmployment initialized");
			_category = MelonPreferences.CreateCategory("BusinessEmployment", "Business Employment Settings");
			EmpCut = _category.CreateEntry<float>("BusinessEmploymentEmployeeCut", 5f, "Employee Cut", "Additional payment for Business employees for restocking the Golden Safe. (% of the cash total)", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 100f), (string)null);
			SafeCost = _category.CreateEntry<float>("BusinessEmploymentGoldSafeCost", 5000f, "Golden Safe price", "Price of the Golden Safe item in the Boutique", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 1E+09f), (string)null);
			EnableSafeAutoRestock = _category.CreateEntry<bool>("BusinessEmploymentEnableSafeAutoRestock", true, "Enable Golden Safe Auto-Restock", "If enabled, businesses with employees will automatically restock their Golden Safes when you sleep.", false, false, (ValueValidator)null, (string)null);
			GameLifecycle.OnPreLoad += CreateSafe;
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (!(sceneName == "Menu"))
			{
				if (sceneName == "Main")
				{
					MelonCoroutines.Start(AddDelayed());
					TimeManager.OnSleepStart = (Action)Delegate.Combine(TimeManager.OnSleepStart, new Action(SafeMethods.RefillSafe));
				}
			}
			else
			{
				SafeCreator.SafeCreated = false;
				SafeCreator.SafeAdded = false;
			}
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			if (sceneName != "Main")
			{
				return;
			}
			try
			{
				TimeManager.OnSleepStart = (Action)Delegate.Remove(TimeManager.OnSleepStart, new Action(SafeMethods.RefillSafe));
			}
			catch (Exception)
			{
			}
		}

		private static void CreateSafe()
		{
			if (!SafeCreator.SafeCreated)
			{
				_logger.Msg("Creating safe");
				SafeCreator.CreateSafe();
			}
		}

		[IteratorStateMachine(typeof(<AddDelayed>d__9))]
		private static IEnumerator AddDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AddDelayed>d__9(0);
		}
	}
}
namespace BusinessEmployment.Persistence
{
	public class LaunderBehaviourSave : Saveable
	{
		[SaveableField("BusinessEmploymentLaunderBehaviourSave")]
		public List<LaunderBehaviourSaveData> SaveDatas = new List<LaunderBehaviourSaveData>();

		public static LaunderBehaviourSave Instance { get; private set; } = new LaunderBehaviourSave();


		public LaunderBehaviourSave()
		{
			Instance = this;
		}

		protected override void OnLoaded()
		{
			foreach (LaunderBehaviourSaveData saveData in SaveDatas)
			{
			}
		}
	}
	public record LaunderBehaviourSaveData
	{
		public string PropertyCode { get; set; }

		public float MoneyLeftToLaunder { get; set; }
	}
}
namespace BusinessEmployment.Patches
{
	[HarmonyPatch(typeof(Business))]
	internal class BusinessIdlePoints
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AddIdlePointAndEmployeeCapacity(Business __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				Melon<BusinessEmployment>.Logger.Error("Business instance is null");
				return;
			}
			Transform spawnPoint = ((Property)__instance).SpawnPoint;
			if ((Object)(object)spawnPoint == (Object)null)
			{
				Melon<BusinessEmployment>.Logger.Error("SpawnPoint for " + ((Property)__instance).PropertyName + " is null");
				return;
			}
			GameObject val = new GameObject("EmployeeIdlePoints");
			val.transform.SetParent(((Component)__instance).transform);
			Transform val2 = Object.Instantiate<Transform>(spawnPoint, spawnPoint.position, spawnPoint.rotation);
			((Component)val2).transform.SetParent(val.transform);
			List<Transform> list = new List<Transform> { val2 };
			((Property)__instance).EmployeeIdlePoints = Il2CppReferenceArray<Transform>.op_Implicit(list.ToArray());
			((Property)__instance).EmployeeCapacity = 1;
		}
	}
	[HarmonyPatch(typeof(DialogueController_Fixer))]
	internal class FixerDialogue
	{
		[HarmonyPatch("ModifyChoiceList")]
		[HarmonyPrefix]
		private static bool IncludeBusinesses(DialogueController_Fixer __instance, string dialogueLabel, ref List<DialogueChoiceData> existingChoices)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (dialogueLabel != "SELECT_LOCATION")
			{
				return true;
			}
			List<DialogueChoiceData> list = new List<DialogueChoiceData>();
			Enumerator<DialogueChoiceData> enumerator = existingChoices.GetEnumerator();
			while (enumerator.MoveNext())
			{
				DialogueChoiceData current = enumerator.Current;
				list.Add(current);
			}
			Enumerator<Property> enumerator2 = Property.OwnedProperties.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				Property current2 = enumerator2.Current;
				if (current2.EmployeeCapacity > 0)
				{
					list.Add(new DialogueChoiceData
					{
						ChoiceText = current2.PropertyName,
						ChoiceLabel = current2.PropertyCode
					});
				}
			}
			existingChoices.Clear();
			foreach (DialogueChoiceData item in list)
			{
				existingChoices.Add(item);
			}
			MelonDebug.Msg("Sanity Check");
			Enumerator<DialogueChoiceData> enumerator4 = existingChoices.GetEnumerator();
			while (enumerator4.MoveNext())
			{
				DialogueChoiceData current4 = enumerator4.Current;
				MelonDebug.Msg(current4.ChoiceText + ": " + current4.ChoiceLabel);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(DialogueCanvas))]
	public static class DialoguePagingPatches
	{
		private const int ChoicesPerPage = 7;

		private static DialogueHandler _handler;

		private static DialogueNodeData _node;

		private static string _text;

		private static List<DialogueChoiceData> _fullChoices;

		private static int _pageIndex;

		private static int _pageCount;

		private static bool PagingActive => _fullChoices != null && _pageCount > 1;

		private static int ClampInt(int value, int min, int max)
		{
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[HarmonyPatch("DisplayDialogueNode")]
		[HarmonyPrefix]
		private static void DisplayDialogueNodePrefix(DialogueHandler diag, DialogueNodeData node, string dialogueText, ref List<DialogueChoiceData> choices)
		{
			try
			{
				if (choices == null || choices.Count <= 8)
				{
					ClearPagingIfNewNode(diag, node);
					return;
				}
				if ((Object)(object)_handler != (Object)(object)diag || _node != node)
				{
					_handler = diag;
					_node = node;
					_text = dialogueText;
					_pageIndex = 0;
					_fullChoices = CopyList(choices);
					_pageCount = ComputePageCount(_fullChoices.Count);
				}
				else
				{
					_text = dialogueText;
					if (_fullChoices == null || _fullChoices.Count != choices.Count)
					{
						_fullChoices = CopyList(choices);
						_pageCount = ComputePageCount(_fullChoices.Count);
						_pageIndex = ClampInt(_pageIndex, 0, Math.Max(0, _pageCount - 1));
					}
				}
				if (PagingActive)
				{
					choices = BuildPageChoices(_fullChoices, _pageIndex, _pageCount);
				}
			}
			catch (Exception value)
			{
				Melon<BusinessEmployment>.Logger.Error($"Dialogue paging DisplayDialogueNodePrefix failed: {value}");
			}
		}

		[HarmonyPatch("DisplayDialogueNode")]
		[HarmonyPostfix]
		private static void DisplayDialogueNodePostfix(DialogueHandler diag)
		{
			try
			{
				if (PagingActive && !((Object)(object)_handler != (Object)(object)diag))
				{
					diag.CurrentChoices = _fullChoices;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("ChoiceSelected")]
		[HarmonyPrefix]
		private static bool ChoiceSelectedPrefix(DialogueCanvas __instance, ref int choiceIndex)
		{
			try
			{
				if (!PagingActive)
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)null)
				{
					return true;
				}
				if (_fullChoices == null || (Object)(object)_handler == (Object)null || _node == null || _text == null)
				{
					return true;
				}
				int count = _fullChoices.Count;
				int num = _pageIndex * 7;
				int val = Math.Max(0, count - num);
				int num2 = Math.Min(7, val);
				if (choiceIndex == num2)
				{
					_pageIndex = (_pageIndex + 1) % _pageCount;
					__instance.SkipNextRollout = true;
					__instance.DisplayDialogueNode(_handler, _node, _text, _fullChoices);
					return false;
				}
				if (choiceIndex < 0 || choiceIndex >= num2)
				{
					return true;
				}
				choiceIndex = num + choiceIndex;
				return true;
			}
			catch (Exception value)
			{
				Melon<BusinessEmployment>.Logger.Error($"Dialogue paging ChoiceSelectedPrefix failed: {value}");
				return true;
			}
		}

		[HarmonyPatch("EndDialogue")]
		[HarmonyPostfix]
		private static void EndDialoguePostfix()
		{
			ClearPaging();
		}

		[HarmonyPatch("IsChoiceValid")]
		[HarmonyPrefix]
		private static bool IsChoiceValidPrefix(int choiceIndex, ref string reason, ref bool __result)
		{
			try
			{
				if (!PagingActive)
				{
					return true;
				}
				if ((Object)(object)_handler == (Object)null || _fullChoices == null)
				{
					return true;
				}
				int count = _fullChoices.Count;
				int num = _pageIndex * 7;
				int val = Math.Max(0, count - num);
				int num2 = Math.Min(7, val);
				if (choiceIndex <= num2)
				{
					if (IsMoreIndex(choiceIndex))
					{
						reason = string.Empty;
						__result = true;
						return false;
					}
					if (choiceIndex < 0 || choiceIndex >= num2)
					{
						reason = string.Empty;
						__result = false;
						return false;
					}
					choiceIndex = num + choiceIndex;
				}
				List<DialogueChoiceData> currentChoices = _handler.CurrentChoices;
				if (currentChoices == null || choiceIndex < 0 || choiceIndex >= currentChoices.Count)
				{
					reason = string.Empty;
					__result = false;
					return false;
				}
				DialogueChoiceData val2 = currentChoices[choiceIndex];
				string text = ((val2 != null) ? val2.ChoiceLabel : null) ?? string.Empty;
				if (string.IsNullOrWhiteSpace(text))
				{
					reason = string.Empty;
					__result = false;
					return false;
				}
				string text2 = default(string);
				bool flag = _handler.CheckChoice(text, ref text2);
				reason = text2;
				__result = flag;
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static bool IsMoreIndex(int choiceIndex)
		{
			if (!PagingActive)
			{
				return false;
			}
			if (_fullChoices == null)
			{
				return false;
			}
			int count = _fullChoices.Count;
			int num = _pageIndex * 7;
			int val = Math.Max(0, count - num);
			int num2 = Math.Min(7, val);
			return choiceIndex == num2;
		}

		private static void ClearPagingIfNewNode(DialogueHandler diag, DialogueNodeData node)
		{
			if ((Object)(object)_handler != (Object)(object)diag || _node != node)
			{
				ClearPaging();
			}
		}

		private static void ClearPaging()
		{
			_handler = null;
			_node = null;
			_text = null;
			_fullChoices = null;
			_pageIndex = 0;
			_pageCount = 0;
		}

		private static int ComputePageCount(int totalChoices)
		{
			if (totalChoices <= 8)
			{
				return 0;
			}
			return (totalChoices + 7 - 1) / 7;
		}

		private static List<DialogueChoiceData> CopyList(List<DialogueChoiceData> src)
		{
			List<DialogueChoiceData> val = new List<DialogueChoiceData>();
			if (src == null)
			{
				return val;
			}
			for (int i = 0; i < src.Count; i++)
			{
				DialogueChoiceData val2 = src[i];
				if (val2 != null)
				{
					val.Add(val2);
				}
			}
			return val;
		}

		private static List<DialogueChoiceData> BuildPageChoices(List<DialogueChoiceData> full, int pageIndex, int pageCount)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			List<DialogueChoiceData> val = new List<DialogueChoiceData>();
			int count = full.Count;
			int num = pageIndex * 7;
			int num2 = Math.Min(7, Math.Max(0, count - num));
			for (int i = 0; i < num2; i++)
			{
				DialogueChoiceData val2 = full[num + i];
				if (val2 != null)
				{
					val.Add(val2);
				}
			}
			string choiceLabel = string.Empty;
			try
			{
				int num3 = (pageIndex + 1) % pageCount;
				int num4 = num3 * 7;
				if (num4 >= 0 && num4 < full.Count)
				{
					DialogueChoiceData val3 = full[num4];
					if (val3 != null && !string.IsNullOrWhiteSpace(val3.ChoiceLabel))
					{
						choiceLabel = val3.ChoiceLabel;
					}
				}
			}
			catch
			{
			}
			val.Add(new DialogueChoiceData
			{
				ChoiceLabel = choiceLabel,
				ChoiceText = $"More ({pageIndex + 1}/{pageCount})"
			});
			return val;
		}
	}
	[HarmonyPatch(typeof(Packager))]
	public class HandlerLaunderBehaviorInitialize
	{
		[HarmonyPatch("UpdateBehaviour")]
		[HarmonyPostfix]
		private static void AddLaunderBehaviour(Packager __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Employee)__instance).AssignedProperty == (Object)null) && Utils.Is<Business>((object)((Employee)__instance).AssignedProperty, out Business _) && ((Employee)__instance).CanWork() && !((Employee)__instance).Fired && !((Behaviour)__instance.PackagingBehaviour).Active && !((Behaviour)((Employee)__instance).MoveItemBehaviour).Active)
			{
				((Employee)__instance).MarkIsWorking();
				LaunderBehaviour.Tick(__instance);
			}
		}
	}
}
namespace BusinessEmployment.Helpers
{
	public static class MelonLoggerExtensions
	{
		public static void Debug(this Instance logger, string message, bool stacktrace = true)
		{
			MelonDebug.Msg(stacktrace ? ("[" + GetCallerInfo() + "] " + message) : message);
		}

		private static string GetCallerInfo()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 2; i < stackTrace.FrameCount; i++)
			{
				StackFrame frame = stackTrace.GetFrame(i);
				MethodBase method = frame.GetMethod();
				if (!(method?.DeclaringType == null))
				{
					return method.DeclaringType.FullName + "." + method.Name;
				}
			}
			return "unknown";
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}

		public static object ToNativeList<T>(this List<T> source)
		{
			return source.ToIl2CppList();
		}

		public static List<T> ToIl2CppList<T>(this IEnumerable<T> source)
		{
			List<T> val = new List<T>();
			foreach (T item in source)
			{
				val.Add(item);
			}
			return val;
		}

		public static List<T> ConvertToList<T>(List<T> il2CppList)
		{
			List<T> list = new List<T>();
			T[] collection = Il2CppArrayBase<T>.op_Implicit(il2CppList.ToArray());
			list.AddRange(collection);
			return list;
		}

		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			IEnumerable<T> result;
			if (list != null)
			{
				result = ((IEnumerable<T>)list._items).Take(list._size);
			}
			else
			{
				IEnumerable<T> enumerable = Array.Empty<T>();
				result = enumerable;
			}
			return result;
		}

		public static object ToNativeList<T>(this List<T> source)
		{
			return source;
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForCondition>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Func<bool> condition;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForCondition>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!condition())
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForNetwork>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForPlayer>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForPlayer>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly Instance Logger = new Instance("BusinessEmployment-Utils");

		public static T? FindObjectByName<T>(string objectName) where T : Object
		{
			try
			{
				foreach (T item in Resources.FindObjectsOfTypeAll<T>())
				{
					if (((Object)item).name != objectName)
					{
						continue;
					}
					Logger.Debug($"Found {typeof(T).Name} '{objectName}' directly in loaded objects");
					return item;
				}
				return default(T);
			}
			catch (Exception ex)
			{
				Logger.Error($"Error finding {typeof(T).Name} '{objectName}': {ex.Message}");
				return default(T);
			}
		}

		public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component
		{
			List<T> list = new List<T>();
			if ((Object)(object)obj == (Object)null)
			{
				return list;
			}
			T[] array = Il2CppArrayBase<T>.op_Implicit(obj.GetComponents<T>());
			if (array.Length != 0)
			{
				list.AddRange(array);
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform child = obj.transform.GetChild(i);
				list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject));
			}
			return list;
		}

		public static bool Is<T>(object obj, out T? result) where T : Object
		{
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				Type val2 = Il2CppType.Of<T>();
				Type il2CppType = val.GetIl2CppType();
				if (val2.IsAssignableFrom(il2CppType))
				{
					result = ((Il2CppObjectBase)val).TryCast<T>();
					return result != null;
				}
			}
			result = default(T);
			return false;
		}

		[IteratorStateMachine(typeof(<WaitForPlayer>d__4))]
		public static IEnumerator WaitForPlayer(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPlayer>d__4(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetwork>d__5))]
		public static IEnumerator WaitForNetwork(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetwork>d__5(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForCondition>d__6))]
		public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForCondition>d__6(0)
			{
				condition = condition,
				timeout = timeout,
				onTimeout = onTimeout,
				onFinish = onFinish
			};
		}

		public static string GetHierarchyPath(this Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "null";
			}
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T component = gameObject.GetComponent<T>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			component = gameObject.AddComponent<T>();
			Logger.Debug("Added component " + typeof(T).Name + " to GameObject " + ((Object)gameObject).name);
			return component;
		}

		public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			Renderer component = gameObject.GetComponent<Renderer>();
			if ((Object)(object)component == (Object)null)
			{
				Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component");
				return null;
			}
			Color valueOrDefault = color.GetValueOrDefault();
			if (!color.HasValue)
			{
				((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f);
				color = valueOrDefault;
			}
			Shader val = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val);
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 1f);
			}
			Color value = color.Value;
			if (value.a <= 0f)
			{
				value.a = 0.2f;
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", value);
			}
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.EnableKeyword("_EMISSION");
				val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f);
			}
			val2.SetInt("_ZWrite", 0);
			val2.renderQueue = 3000;
			Material material = component.material;
			component.material = val2;
			return material;
		}
	}
}
namespace BusinessEmployment.BetterSafe
{
	internal class FilterHelper
	{
		[CompilerGenerated]
		private sealed class <WaitSearchAdd>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float timeout;

			private float <startTime>5__1;

			private IEnumerable<StorageEntity> <betterSafes>5__2;

			private IEnumerator<StorageEntity> <>s__3;

			private StorageEntity <betterSafe>5__4;

			private Enumerator<ItemSlot> <>s__5;

			private ItemSlot <slot>5__6;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitSearchAdd>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<betterSafes>5__2 = null;
				<>s__3 = null;
				<betterSafe>5__4 = null;
				<>s__5 = null;
				<slot>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_026c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0276: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (filter_Cash == null)
					{
						filter_Cash = new ItemFilter_Cash();
					}
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					<betterSafes>5__2 = null;
					break;
				}
				if (Time.time - <startTime>5__1 <= timeout)
				{
					<betterSafes>5__2 = from bi in (from p in Property.Properties.AsEnumerable<Property>()
							select p.BuildableItems into items
							where items != null
							select items.AsEnumerable<BuildableItem>()).Aggregate((IEnumerable<BuildableItem> a, IEnumerable<BuildableItem> b) => a.Concat(b))
						select Utils.Is<PlaceableStorageEntity>((object)bi, out PlaceableStorageEntity result) ? result : null into r
						where (Object)(object)r != (Object)null
						select r into pse
						where ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
						select pse.StorageEntity;
					<>s__3 = <betterSafes>5__2.GetEnumerator();
					try
					{
						while (<>s__3.MoveNext())
						{
							<betterSafe>5__4 = <>s__3.Current;
							<>s__5 = <betterSafe>5__4.ItemSlots.GetEnumerator();
							while (<>s__5.MoveNext())
							{
								<slot>5__6 = <>s__5.Current;
								if (!<slot>5__6.HardFilters.AsEnumerable<ItemFilter>().Any((ItemFilter itFi) => ((object)itFi).GetType() == ((object)filter_Cash).GetType()))
								{
									<slot>5__6.AddFilter((ItemFilter)(object)filter_Cash);
									<slot>5__6 = null;
								}
							}
							<>s__5 = null;
							<betterSafe>5__4 = null;
						}
					}
					finally
					{
						if (<>s__3 != null)
						{
							<>s__3.Dispose();
						}
					}
					<>s__3 = null;
					<>2__current = (object)new WaitForSecondsRealtime(0.5f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ItemFilter_Cash filter_Cash;

		private static Instance _logger = Melon<BusinessEmployment>.Logger;

		[IteratorStateMachine(typeof(<WaitSearchAdd>d__2))]
		internal static IEnumerator WaitSearchAdd(float timeout)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitSearchAdd>d__2(0)
			{
				timeout = timeout
			};
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ItemFilter_Cash : ItemFilter
	{
		public ItemFilter_Cash(IntPtr ptr)
			: base(ptr)
		{
		}

		public ItemFilter_Cash()
			: base(ClassInjector.DerivedConstructorPointer<ItemFilter_Cash>())
		{
			ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
		}

		public override bool DoesItemMatchFilter(ItemInstance item)
		{
			CashInstance result;
			return Utils.Is<CashInstance>((object)item, out result);
		}
	}
	public class SafeCreator
	{
		internal const string SAFE_ID = "gold_safe";

		private const string SAFE_NAME = "Golden Safe";

		internal const int SLOT_COUNT = 20;

		public static bool SafeCreated;

		public static bool SafeAdded;

		private static readonly Color GoldMetalColor = new Color(1f, 0.766f, 0.336f, 1f);

		public static void CreateSafe()
		{
			BuildableItemDefinition val = BuildableItemCreator.CloneFrom("safe").WithBasicInfo("gold_safe", "Golden Safe", "An upgraded version of the safe. Can hold only cash.").WithPricing(BusinessEmployment.SafeCost.Value, 0.8f)
				.WithIcon(LoadIcon())
				.Build();
			BuildEvents.OnBuildableItemInitialized += ItemBuilt;
			BuildEvents.OnGridItemCreated += ItemBuilt;
			BuildEvents.OnSurfaceItemCreated += ItemBuilt;
			StorageEvents.OnStorageCreated += StorageCreated;
			StorageEvents.OnStorageLoading += StorageLoaded;
			StorageEvents.OnStorageOpening += StorageOpened;
			SafeCreated = true;
		}

		public static void AddToShop()
		{
			ItemDefinition itemDefinition = ItemManager.GetItemDefinition("gold_safe");
			if (itemDefinition == (ItemDefinition)null)
			{
				Melon<BusinessEmployment>.Logger.Error("Error while adding safe to shop");
				return;
			}
			Shop shopByName = ShopManager.GetShopByName("Bleuball's Boutique");
			if (shopByName == null)
			{
				Melon<BusinessEmployment>.Logger.Error("Shop not found");
				return;
			}
			shopByName.AddItem(itemDefinition, (float?)null);
			SafeAdded = true;
		}

		private static void EnsureCapacity(StorageEntity storage)
		{
			if (storage != null)
			{
				if (!storage.SetSlotCount(20))
				{
					Melon<BusinessEmployment>.Logger.Error("Failed to add additional slots");
				}
				else
				{
					MelonCoroutines.Start(FilterHelper.WaitSearchAdd(10f));
				}
			}
		}

		private static void StorageCreated(StorageEventArgs args)
		{
			if (args != null && args.Storage != null && args.ItemId == "gold_safe")
			{
				args.Storage.Name = "Golden Safe";
				EnsureCapacity(args.Storage);
			}
		}

		private static void StorageOpened(StorageEventArgs args)
		{
			if (args != null)
			{
				StorageEntity storage = args.Storage;
				if (storage != null)
				{
					storage.SyncCustomNameToDisplayName();
				}
			}
		}

		private static void StorageLoaded(StorageLoadingEventArgs args)
		{
			if (args != null && ((StorageEventArgs)args).Storage != null && ((StorageEventArgs)args).ItemId == "gold_safe")
			{
				((StorageEventArgs)args).Storage.Name = "Golden Safe";
				EnsureCapacity(((StorageEventArgs)args).Storage);
			}
		}

		private static void ItemBuilt(BuildEventArgs args)
		{
			if (SafeCreated && args != null && args.ItemId == "gold_safe")
			{
				MaterialHelper.ReplaceMaterials(args.GameObject, (Func<Material, bool>)((Material mat) => ((Object)mat).name.ToLower().Contains("safe_body")), (Action<Material>)delegate(Material material)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					MaterialHelper.RemoveAllTextures(material);
					MaterialHelper.SetColor(material, "_BaseColor", GoldMetalColor);
					MaterialHelper.SetColor(material, "_Color", GoldMetalColor);
					MaterialHelper.SetFloat(material, "_Metallic", 0.85f);
					MaterialHelper.SetFloat(material, "_Smoothness", 0.65f);
					MaterialHelper.SetFloat(material, "_Glossiness", 0.65f);
				});
			}
		}

		private static Sprite LoadIcon()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			return ImageUtils.LoadImageFromResource(executingAssembly, "BusinessEmployment.assets.safe_icon.png", 100f, (FilterMode)1);
		}
	}
	public class SafeMethods
	{
		public static void RefillSafe()
		{
			if (!BusinessEmployment.EnableSafeAutoRestock.Value)
			{
				return;
			}
			PlaceableStorageEntity result3;
			IEnumerable<StorageEntity> enumerable = from bi in (from b in Business.OwnedBusinesses.AsEnumerable<Business>()
					where ((Property)b).Employees.Count > 0
					select b into p
					select ((Property)p).BuildableItems into items
					where items != null
					select items.AsEnumerable<BuildableItem>()).Aggregate((IEnumerable<BuildableItem> a, IEnumerable<BuildableItem> b) => a.Concat(b))
				select Utils.Is<PlaceableStorageEntity>((object)bi, out result3) ? result3 : null into r
				where (Object)(object)r != (Object)null
				select r into pse
				where ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
				select pse.StorageEntity;
			float value = BusinessEmployment.EmpCut.Value;
			float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance;
			int num = ((((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).StackLimit == 1) ? 1000 : ((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).StackLimit);
			float num2 = 0f;
			float num3 = 1f + value / 100f;
			foreach (StorageEntity item in enumerable)
			{
				Enumerator<ItemSlot> enumerator2 = item.ItemSlots.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					ItemSlot current2 = enumerator2.Current;
					float num4 = 0f;
					if (Utils.Is<CashInstance>((object)current2.ItemInstance, out CashInstance result))
					{
						if (result != null)
						{
							float num5 = (float)num - result.Balance;
							num4 = num5;
						}
					}
					else
					{
						num4 = num;
					}
					float num6 = num2 + num4;
					float num7 = num6 * num3;
					if (num7 > cashBalance)
					{
						float num8 = cashBalance / num3;
						num4 = num8 - num2;
					}
					if (num4 > 0f)
					{
						if (Utils.Is<CashInstance>((object)((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).GetCopy(-1), out CashInstance result2))
						{
							if (result2 == null)
							{
								continue;
							}
							result2.Balance = num4;
							current2.InsertItem((ItemInstance)(object)result2);
						}
						num2 += num4;
					}
					if (num2 * num3 >= cashBalance)
					{
						break;
					}
				}
				if (num2 * num3 >= cashBalance)
				{
					break;
				}
			}
			float num9 = num2 * (value / 100f);
			float num10 = num2 + num9;
			NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(0f - num10, true, false);
			Melon<BusinessEmployment>.Logger.Msg($"Refilled safes! Inserted: {num2}, Employee cut: {num9}, Total cost: {num10}");
		}
	}
}
namespace BusinessEmployment.Behaviours
{
	public class LaunderBehaviour
	{
		private static readonly Dictionary<Packager, LaunderBehaviour> _instances = new Dictionary<Packager, LaunderBehaviour>();

		private readonly Packager employee;

		private readonly Property property;

		private Business propertyAsBusiness;

		private ELaunderEmployeeState state = ELaunderEmployeeState.Idle;

		private PlaceableStorageEntity? currentSE;

		private LaunderingStation? station;

		public LaunderBehaviourSaveData SaveData;

		private LaunderBehaviour(Packager employee)
		{
			this.employee = employee;
			property = ((Employee)employee).AssignedProperty;
			if (Utils.Is<Business>((object)property, out Business result))
			{
				if ((Object)(object)result == (Object)null)
				{
					Melon<BusinessEmployment>.Logger.Error("Property cannot be cast to business!");
				}
				propertyAsBusiness = result;
			}
			else
			{
				Melon<BusinessEmployment>.Logger.Error("Property cannot be cast to business!");
			}
			string propertyCode = property.PropertyCode;
			IEnumerable<LaunderBehaviourSaveData> source = LaunderBehaviourSave.Instance.SaveDatas.Where((LaunderBehaviourSaveData s) => s.PropertyCode == propertyCode);
			if (source.Any())
			{
				SaveData = source.First();
				return;
			}
			SaveData = new LaunderBehaviourSaveData
			{
				PropertyCode = propertyCode,
				MoneyLeftToLaunder = 0f
			};
			LaunderBehaviourSave.Instance.SaveDatas.Add(SaveData);
		}

		private static LaunderBehaviour? GetOrCreate(Packager employee)
		{
			if ((Object)(object)employee == (Object)null)
			{
				return null;
			}
			CleanupNullEmployees();
			if (_instances.TryGetValue(employee, out LaunderBehaviour value))
			{
				return value;
			}
			value = new LaunderBehaviour(employee);
			_instances[employee] = value;
			return value;
		}

		public static void Tick(Packager employee)
		{
			GetOrCreate(employee)?.Tick();
		}

		private void Tick()
		{
			if (!IsValidState())
			{
				SetIdleAndWaitOutside();
				return;
			}
			if (state == ELaunderEmployeeState.Idle && (!((Employee)employee).CanWork() || propertyAsBusiness.currentLaunderTotal >= propertyAsBusiness.LaunderCapacity))
			{
				SetIdleAndWaitOutside();
				return;
			}
			ProcessCurrentState();
			if (Time.frameCount % 30 == 0)
			{
				MelonDebug.Msg($"Cash: {SaveData.MoneyLeftToLaunder}, state: {state}");
			}
		}

		private bool IsValidState()
		{
			return (Object)(object)propertyAsBusiness != (Object)null && (Object)(object)property != (Object)null && (Object)(object)employee != (Object)null;
		}

		private void SetIdleAndWaitOutside()
		{
			state = ELaunderEmployeeState.Idle;
			((Employee)employee).SubmitNoWorkReason("There's nothing for me to do right now.", "I need to have cash to launder or free laundering capacity.", 0);
			((Employee)employee).SetIdle(true);
			Packager obj = employee;
			if (obj != null)
			{
				((Employee)obj).SetWaitOutside(true);
			}
		}

		private void ProcessCurrentState()
		{
			switch (state)
			{
			case ELaunderEmployeeState.Idle:
				HandleIdleState();
				break;
			case ELaunderEmployeeState.RetrieveCash:
				HandleRetrieveCashState();
				break;
			case ELaunderEmployeeState.DepositCash:
				HandleDepositCashState();
				break;
			default:
				HandleIdleState();
				break;
			}
		}

		private void HandleIdleState()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (SaveData.MoneyLeftToLaunder > 0f && propertyAsBusiness.currentLaunderTotal < propertyAsBusiness.LaunderCapacity && EnsureLaunderingStationExists())
			{
				((Employee)employee).SetWaitOutside(false);
				MoveToLaunderingStation();
				return;
			}
			List<PlaceableStorageEntity> list = GetAllStoragesWithCash().ToList();
			if (!list.Any())
			{
				MelonDebug.Msg("No reachable storage with cash found");
				return;
			}
			foreach (PlaceableStorageEntity item in list)
			{
				Vector3? val = FindReachableAccessPoint(item);
				if (val.HasValue)
				{
					((Employee)employee).SetWaitOutside(false);
					currentSE = item;
					((Employee)employee).SetDestination(val.Value, true);
					state = ELaunderEmployeeState.RetrieveCash;
					break;
				}
			}
		}

		private Vector3? FindReachableAccessPoint(PlaceableStorageEntity storage)
		{
			//IL_0051: 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)
			if (((storage != null) ? storage.AccessPoints : null) == null)
			{
				MelonDebug.Error("Storage accesspoints is null");
				return null;
			}
			foreach (Transform item in (Il2CppArrayBase<Transform>)(object)storage.AccessPoints)
			{
				if (((NPC)employee).Movement.CanGetTo(item.position, 1f))
				{
					return item.position;
				}
			}
			MelonDebug.Error("Wasn't able to find a good position to move to");
			return null;
		}

		private void HandleRetrieveCashState()
		{
			if (((NPC)employee).Movement.IsMoving)
			{
				return;
			}
			if ((Object)(object)currentSE == (Object)null)
			{
				state = ELaunderEmployeeState.Idle;
				return;
			}
			CollectCashFromStorage();
			if (!EnsureLaunderingStationExists())
			{
				state = ELaunderEmployeeState.Idle;
			}
			else
			{
				MoveToLaunderingStation();
			}
		}

		private void CollectCashFromStorage()
		{
			PlaceableStorageEntity? obj = currentSE;
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				StorageEntity storageEntity = obj.StorageEntity;
				obj2 = ((storageEntity != null) ? storageEntity.ItemSlots : null);
			}
			if (obj2 == null)
			{
				MelonDebug.Error("Storage itemslots is null");
				return;
			}
			List<ItemSlot> itemSlots = currentSE.StorageEntity.ItemSlots;
			for (int i = 0; i < itemSlots.Count; i++)
			{
				if (Utils.Is<CashInstance>((object)itemSlots[i].ItemInstance, out CashInstance result))
				{
					currentSE.StorageEntity.SetSlotLocked((NetworkConnection)null, i, true, ((NetworkBehaviour)employee).NetworkObject, "Taking out items");
					if (result != null)
					{
						WithdrawForLaunder(propertyAsBusiness.LaunderCapacity, result);
					}
				}
				currentSE.StorageEntity.SetSlotLocked((NetworkConnection)null, i, false, ((NetworkBehaviour)employee).NetworkObject, "Taking out items");
				if (SaveData.MoneyLeftToLaunder >= propertyAsBusiness.LaunderCapacity)
				{
					break;
				}
			}
		}

		private bool EnsureLaunderingStationExists()
		{
			if ((Object)(object)station != (Object)null)
			{
				return true;
			}
			station = (from bi in property.BuildableItems.AsEnumerable<BuildableItem>()
				select Utils.Is<LaunderingStation>((object)bi, out LaunderingStation result) ? result : null).FirstOrDefault((Func<LaunderingStation, bool>)((LaunderingStation r) => (Object)(object)r != (Object)null));
			if ((Object)(object)station != (Object)null)
			{
				return true;
			}
			Melon<BusinessEmployment>.Logger.Error("Laundering station not found!");
			return false;
		}

		private void MoveToLaunderingStation()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_006c: 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)
			if (!((Object)(object)station == (Object)null))
			{
				Vector3 val;
				if (!((Object)(object)((BuildableItem)station).BoundingCollider != (Object)null))
				{
					val = ((Component)station).transform.position;
				}
				else
				{
					Bounds bounds = ((Collider)((BuildableItem)station).BoundingCollider).bounds;
					val = ((Bounds)(ref bounds)).ClosestPoint(((Component)employee).transform.position);
				}
				Vector3 val2 = val;
				Vector3 val3 = default(Vector3);
				((NPC)employee).Movement.GetClosestReachablePoint(val2, ref val3);
				((Employee)employee).SetDestination(val3, true);
				currentSE = null;
				state = ELaunderEmployeeState.DepositCash;
			}
		}

		private void HandleDepositCashState()
		{
			if (!((NPC)employee).Movement.IsMoving)
			{
				((NPC)employee).SetAnimationTrigger_Networked((NetworkConnection)null, "GrabItem");
				float num = propertyAsBusiness.LaunderCapacity - propertyAsBusiness.currentLaunderTotal;
				if (num > 0f)
				{
					float num2 = Math.Min(SaveData.MoneyLeftToLaunder, num);
					propertyAsBusiness.StartLaunderingOperation(num2, 0);
					SaveData.MoneyLeftToLaunder -= num2;
				}
				state = ELaunderEmployeeState.Idle;
			}
		}

		private void WithdrawForLaunder(float launderTarget, CashInstance cashInstance)
		{
			float num = launderTarget - SaveData.MoneyLeftToLaunder;
			if (!(num <= 0f) && !(cashInstance.Balance <= 0f))
			{
				float num2 = Math.Min(num, cashInstance.Balance);
				((NPC)employee).SetAnimationTrigger_Networked((NetworkConnection)null, "GrabItem");
				cashInstance.ChangeBalance(0f - num2);
				SaveData.MoneyLeftToLaunder += num2;
			}
		}

		public IEnumerable<PlaceableStorageEntity?> GetAllStoragesWithCash()
		{
			PlaceableStorageEntity result2;
			CashInstance result;
			return from bi in property.BuildableItems.AsEnumerable<BuildableItem>()
				select Utils.Is<PlaceableStorageEntity>((object)bi, out result2) ? result2 : null into r
				where (Object)(object)r != (Object)null
				select r into pse
				where (Object)(object)pse.StorageEntity != (Object)(object)((Employee)employee).GetHome().Storage
				where pse.OutputSlots.AsEnumerable<ItemSlot>().Any((ItemSlot os) => Utils.Is<CashInstance>((object)os.ItemInstance, out result))
				orderby ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
				select pse;
		}

		public static void Remove(Packager employee)
		{
			_instances.Remove(employee);
		}

		private static void CleanupNullEmployees()
		{
			List<Packager> list = _instances.Keys.Where((Packager e) => (Object)(object)e == (Object)null).ToList();
			foreach (Packager item in list)
			{
				_instances.Remove(item);
			}
		}
	}
	public enum ELaunderEmployeeState
	{
		Idle,
		RetrieveCash,
		DepositCash
	}
}

BusinessEmployment-Mono.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BusinessEmployment;
using BusinessEmployment.Behaviours;
using BusinessEmployment.BetterSafe;
using BusinessEmployment.Helpers;
using BusinessEmployment.Persistence;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using S1API.Building;
using S1API.GameTime;
using S1API.Internal.Abstraction;
using S1API.Items;
using S1API.Lifecycle;
using S1API.Rendering;
using S1API.Saveables;
using S1API.Shops;
using S1API.Storage;
using S1API.Utils;
using ScheduleOne.DevUtilities;
using ScheduleOne.Dialogue;
using ScheduleOne.Employees;
using ScheduleOne.EntityFramework;
using ScheduleOne.ItemFramework;
using ScheduleOne.Money;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.Behaviour;
using ScheduleOne.ObjectScripts;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Property;
using ScheduleOne.Storage;
using ScheduleOne.UI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::BusinessEmployment.BusinessEmployment), "BusinessEmployment", "1.0.1", "k073l", null)]
[assembly: MelonColor(1, 255, 195, 86)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("BusinessEmployment-Mono")]
[assembly: AssemblyConfiguration("Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4a7a319981f82b5cd9ac41acb7a6c0eba51c6d19")]
[assembly: AssemblyProduct("BusinessEmployment-Mono")]
[assembly: AssemblyTitle("BusinessEmployment-Mono")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BusinessEmployment
{
	public static class BuildInfo
	{
		public const string Name = "BusinessEmployment";

		public const string Description = "Adds employees to Businesses. Automates laundering.";

		public const string Author = "k073l";

		public const string Version = "1.0.1";
	}
	public class BusinessEmployment : MelonMod
	{
		[CompilerGenerated]
		private sealed class <AddDelayed>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AddDelayed>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (SafeCreator.SafeAdded)
					{
						return false;
					}
					_logger.Msg("Adding safe to the shop");
					SafeCreator.AddToShop();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static Instance _logger;

		private static MelonPreferences_Category _category;

		internal static MelonPreferences_Entry<float> EmpCut;

		internal static MelonPreferences_Entry<float> SafeCost;

		internal static MelonPreferences_Entry<bool> EnableSafeAutoRestock;

		public override void OnInitializeMelon()
		{
			_logger = ((MelonBase)this).LoggerInstance;
			_logger.Msg("BusinessEmployment initialized");
			_category = MelonPreferences.CreateCategory("BusinessEmployment", "Business Employment Settings");
			EmpCut = _category.CreateEntry<float>("BusinessEmploymentEmployeeCut", 5f, "Employee Cut", "Additional payment for Business employees for restocking the Golden Safe. (% of the cash total)", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 100f), (string)null);
			SafeCost = _category.CreateEntry<float>("BusinessEmploymentGoldSafeCost", 5000f, "Golden Safe price", "Price of the Golden Safe item in the Boutique", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 1E+09f), (string)null);
			EnableSafeAutoRestock = _category.CreateEntry<bool>("BusinessEmploymentEnableSafeAutoRestock", true, "Enable Golden Safe Auto-Restock", "If enabled, businesses with employees will automatically restock their Golden Safes when you sleep.", false, false, (ValueValidator)null, (string)null);
			GameLifecycle.OnPreLoad += CreateSafe;
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (!(sceneName == "Menu"))
			{
				if (sceneName == "Main")
				{
					MelonCoroutines.Start(AddDelayed());
					TimeManager.OnSleepStart = (Action)Delegate.Combine(TimeManager.OnSleepStart, new Action(SafeMethods.RefillSafe));
				}
			}
			else
			{
				SafeCreator.SafeCreated = false;
				SafeCreator.SafeAdded = false;
			}
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			if (sceneName != "Main")
			{
				return;
			}
			try
			{
				TimeManager.OnSleepStart = (Action)Delegate.Remove(TimeManager.OnSleepStart, new Action(SafeMethods.RefillSafe));
			}
			catch (Exception)
			{
			}
		}

		private static void CreateSafe()
		{
			if (!SafeCreator.SafeCreated)
			{
				_logger.Msg("Creating safe");
				SafeCreator.CreateSafe();
			}
		}

		[IteratorStateMachine(typeof(<AddDelayed>d__9))]
		private static IEnumerator AddDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AddDelayed>d__9(0);
		}
	}
}
namespace BusinessEmployment.Persistence
{
	public class LaunderBehaviourSave : Saveable
	{
		[SaveableField("BusinessEmploymentLaunderBehaviourSave")]
		public List<LaunderBehaviourSaveData> SaveDatas = new List<LaunderBehaviourSaveData>();

		public static LaunderBehaviourSave Instance { get; private set; } = new LaunderBehaviourSave();


		public LaunderBehaviourSave()
		{
			Instance = this;
		}

		protected override void OnLoaded()
		{
			foreach (LaunderBehaviourSaveData saveData in SaveDatas)
			{
			}
		}
	}
	public record LaunderBehaviourSaveData
	{
		public string PropertyCode { get; set; }

		public float MoneyLeftToLaunder { get; set; }
	}
}
namespace BusinessEmployment.Patches
{
	[HarmonyPatch(typeof(Business))]
	internal class BusinessIdlePoints
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AddIdlePointAndEmployeeCapacity(Business __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				Melon<BusinessEmployment>.Logger.Error("Business instance is null");
				return;
			}
			Transform spawnPoint = ((Property)__instance).SpawnPoint;
			if ((Object)(object)spawnPoint == (Object)null)
			{
				Melon<BusinessEmployment>.Logger.Error("SpawnPoint for " + ((Property)__instance).PropertyName + " is null");
				return;
			}
			GameObject val = new GameObject("EmployeeIdlePoints");
			val.transform.SetParent(((Component)__instance).transform);
			Transform val2 = Object.Instantiate<Transform>(spawnPoint, spawnPoint.position, spawnPoint.rotation);
			((Component)val2).transform.SetParent(val.transform);
			List<Transform> list = new List<Transform> { val2 };
			((Property)__instance).EmployeeIdlePoints = list.ToArray();
			((Property)__instance).EmployeeCapacity = 1;
		}
	}
	[HarmonyPatch(typeof(DialogueController_Fixer))]
	internal class FixerDialogue
	{
		[HarmonyPatch("ModifyChoiceList")]
		[HarmonyPrefix]
		private static bool IncludeBusinesses(DialogueController_Fixer __instance, string dialogueLabel, ref List<DialogueChoiceData> existingChoices)
		{
			//IL_0094: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (dialogueLabel != "SELECT_LOCATION")
			{
				return true;
			}
			List<DialogueChoiceData> list = new List<DialogueChoiceData>();
			foreach (DialogueChoiceData existingChoice in existingChoices)
			{
				list.Add(existingChoice);
			}
			foreach (Property ownedProperty in Property.OwnedProperties)
			{
				if (ownedProperty.EmployeeCapacity > 0)
				{
					list.Add(new DialogueChoiceData
					{
						ChoiceText = ownedProperty.PropertyName,
						ChoiceLabel = ownedProperty.PropertyCode
					});
				}
			}
			existingChoices.Clear();
			foreach (DialogueChoiceData item in list)
			{
				existingChoices.Add(item);
			}
			MelonDebug.Msg("Sanity Check");
			foreach (DialogueChoiceData existingChoice2 in existingChoices)
			{
				MelonDebug.Msg(existingChoice2.ChoiceText + ": " + existingChoice2.ChoiceLabel);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(DialogueCanvas))]
	public static class DialoguePagingPatches
	{
		private const int ChoicesPerPage = 7;

		private static DialogueHandler _handler;

		private static DialogueNodeData _node;

		private static string _text;

		private static List<DialogueChoiceData> _fullChoices;

		private static int _pageIndex;

		private static int _pageCount;

		private static bool PagingActive => _fullChoices != null && _pageCount > 1;

		private static int ClampInt(int value, int min, int max)
		{
			if (value < min)
			{
				return min;
			}
			if (value > max)
			{
				return max;
			}
			return value;
		}

		[HarmonyPatch("DisplayDialogueNode")]
		[HarmonyPrefix]
		private static void DisplayDialogueNodePrefix(DialogueHandler diag, DialogueNodeData node, string dialogueText, ref List<DialogueChoiceData> choices)
		{
			try
			{
				if (choices == null || choices.Count <= 8)
				{
					ClearPagingIfNewNode(diag, node);
					return;
				}
				if ((Object)(object)_handler != (Object)(object)diag || _node != node)
				{
					_handler = diag;
					_node = node;
					_text = dialogueText;
					_pageIndex = 0;
					_fullChoices = new List<DialogueChoiceData>(choices);
					_pageCount = ComputePageCount(_fullChoices.Count);
				}
				else
				{
					_text = dialogueText;
					if (_fullChoices == null || _fullChoices.Count != choices.Count)
					{
						_fullChoices = new List<DialogueChoiceData>(choices);
						_pageCount = ComputePageCount(_fullChoices.Count);
						_pageIndex = ClampInt(_pageIndex, 0, Math.Max(0, _pageCount - 1));
					}
				}
				if (PagingActive)
				{
					choices = BuildPageChoices(_fullChoices, _pageIndex, _pageCount);
				}
			}
			catch (Exception arg)
			{
				Melon<BusinessEmployment>.Logger.Error($"Dialogue paging DisplayDialogueNodePrefix failed: {arg}");
			}
		}

		[HarmonyPatch("DisplayDialogueNode")]
		[HarmonyPostfix]
		private static void DisplayDialogueNodePostfix(DialogueHandler diag)
		{
			try
			{
				if (PagingActive && !((Object)(object)_handler != (Object)(object)diag))
				{
					diag.CurrentChoices = _fullChoices;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch("ChoiceSelected")]
		[HarmonyPrefix]
		private static bool ChoiceSelectedPrefix(DialogueCanvas __instance, ref int choiceIndex)
		{
			try
			{
				if (!PagingActive)
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)null)
				{
					return true;
				}
				if (_fullChoices == null || (Object)(object)_handler == (Object)null || _node == null || _text == null)
				{
					return true;
				}
				int count = _fullChoices.Count;
				int num = _pageIndex * 7;
				int val = Math.Max(0, count - num);
				int num2 = Math.Min(7, val);
				if (choiceIndex == num2)
				{
					_pageIndex = (_pageIndex + 1) % _pageCount;
					__instance.SkipNextRollout = true;
					__instance.DisplayDialogueNode(_handler, _node, _text, _fullChoices);
					return false;
				}
				if (choiceIndex < 0 || choiceIndex >= num2)
				{
					return true;
				}
				choiceIndex = num + choiceIndex;
				return true;
			}
			catch (Exception arg)
			{
				Melon<BusinessEmployment>.Logger.Error($"Dialogue paging ChoiceSelectedPrefix failed: {arg}");
				return true;
			}
		}

		[HarmonyPatch("EndDialogue")]
		[HarmonyPostfix]
		private static void EndDialoguePostfix()
		{
			ClearPaging();
		}

		[HarmonyPatch("IsChoiceValid")]
		[HarmonyPrefix]
		private static bool IsChoiceValidPrefix(int choiceIndex, ref string reason, ref bool __result)
		{
			try
			{
				if (!PagingActive)
				{
					return true;
				}
				if ((Object)(object)_handler == (Object)null || _fullChoices == null)
				{
					return true;
				}
				int count = _fullChoices.Count;
				int num = _pageIndex * 7;
				int val = Math.Max(0, count - num);
				int num2 = Math.Min(7, val);
				if (choiceIndex <= num2)
				{
					if (IsMoreIndex(choiceIndex))
					{
						reason = string.Empty;
						__result = true;
						return false;
					}
					if (choiceIndex < 0 || choiceIndex >= num2)
					{
						reason = string.Empty;
						__result = false;
						return false;
					}
					choiceIndex = num + choiceIndex;
				}
				List<DialogueChoiceData> currentChoices = _handler.CurrentChoices;
				if (currentChoices == null || choiceIndex < 0 || choiceIndex >= currentChoices.Count)
				{
					reason = string.Empty;
					__result = false;
					return false;
				}
				string text = currentChoices[choiceIndex]?.ChoiceLabel ?? string.Empty;
				if (string.IsNullOrWhiteSpace(text))
				{
					reason = string.Empty;
					__result = false;
					return false;
				}
				string text2 = default(string);
				bool flag = _handler.CheckChoice(text, ref text2);
				reason = text2;
				__result = flag;
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static bool IsMoreIndex(int choiceIndex)
		{
			if (!PagingActive)
			{
				return false;
			}
			if (_fullChoices == null)
			{
				return false;
			}
			int count = _fullChoices.Count;
			int num = _pageIndex * 7;
			int val = Math.Max(0, count - num);
			int num2 = Math.Min(7, val);
			return choiceIndex == num2;
		}

		private static void ClearPagingIfNewNode(DialogueHandler diag, DialogueNodeData node)
		{
			if ((Object)(object)_handler != (Object)(object)diag || _node != node)
			{
				ClearPaging();
			}
		}

		private static void ClearPaging()
		{
			_handler = null;
			_node = null;
			_text = null;
			_fullChoices = null;
			_pageIndex = 0;
			_pageCount = 0;
		}

		private static int ComputePageCount(int totalChoices)
		{
			if (totalChoices <= 8)
			{
				return 0;
			}
			return (totalChoices + 7 - 1) / 7;
		}

		private static List<DialogueChoiceData> BuildPageChoices(List<DialogueChoiceData> full, int pageIndex, int pageCount)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			List<DialogueChoiceData> list = new List<DialogueChoiceData>();
			int count = full.Count;
			int num = pageIndex * 7;
			int num2 = Math.Min(7, Math.Max(0, count - num));
			for (int i = 0; i < num2; i++)
			{
				DialogueChoiceData val = full[num + i];
				if (val != null)
				{
					list.Add(val);
				}
			}
			string choiceLabel = string.Empty;
			try
			{
				int num3 = (pageIndex + 1) % pageCount;
				int num4 = num3 * 7;
				if (num4 >= 0 && num4 < full.Count)
				{
					DialogueChoiceData val2 = full[num4];
					if (val2 != null && !string.IsNullOrWhiteSpace(val2.ChoiceLabel))
					{
						choiceLabel = val2.ChoiceLabel;
					}
				}
			}
			catch
			{
			}
			list.Add(new DialogueChoiceData
			{
				ChoiceLabel = choiceLabel,
				ChoiceText = $"More ({pageIndex + 1}/{pageCount})"
			});
			return list;
		}
	}
	[HarmonyPatch(typeof(Packager))]
	public class HandlerLaunderBehaviorInitialize
	{
		[HarmonyPatch("UpdateBehaviour")]
		[HarmonyPostfix]
		private static void AddLaunderBehaviour(Packager __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Employee)__instance).AssignedProperty == (Object)null) && Utils.Is<Business>(((Employee)__instance).AssignedProperty, out Business _) && ((Employee)__instance).CanWork() && !((Employee)__instance).Fired && !((Behaviour)__instance.PackagingBehaviour).Active && !((Behaviour)((Employee)__instance).MoveItemBehaviour).Active)
			{
				((Employee)__instance).MarkIsWorking();
				LaunderBehaviour.Tick(__instance);
			}
		}
	}
}
namespace BusinessEmployment.Helpers
{
	public static class MelonLoggerExtensions
	{
		public static void Debug(this Instance logger, string message, bool stacktrace = true)
		{
			MelonDebug.Msg(stacktrace ? ("[" + GetCallerInfo() + "] " + message) : message);
		}

		private static string GetCallerInfo()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 2; i < stackTrace.FrameCount; i++)
			{
				StackFrame frame = stackTrace.GetFrame(i);
				MethodBase method = frame.GetMethod();
				if (!(method?.DeclaringType == null))
				{
					return method.DeclaringType.FullName + "." + method.Name;
				}
			}
			return "unknown";
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}

		public static object ToNativeList<T>(this List<T> source)
		{
			return source ?? new List<T>();
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForCondition>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Func<bool> condition;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForCondition>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!condition())
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForNetwork>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForPlayer>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForPlayer>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly Instance Logger = new Instance("BusinessEmployment-Utils");

		public static T? FindObjectByName<T>(string objectName) where T : Object
		{
			try
			{
				T[] array = Resources.FindObjectsOfTypeAll<T>();
				foreach (T val in array)
				{
					if (!(((Object)val).name != objectName))
					{
						Logger.Debug("Found " + typeof(T).Name + " '" + objectName + "' directly in loaded objects");
						return val;
					}
				}
				return default(T);
			}
			catch (Exception ex)
			{
				Logger.Error("Error finding " + typeof(T).Name + " '" + objectName + "': " + ex.Message);
				return default(T);
			}
		}

		public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component
		{
			List<T> list = new List<T>();
			if ((Object)(object)obj == (Object)null)
			{
				return list;
			}
			T[] components = obj.GetComponents<T>();
			if (components.Length != 0)
			{
				list.AddRange(components);
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform child = obj.transform.GetChild(i);
				list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject));
			}
			return list;
		}

		public static bool Is<T>(object obj, out T? result) where T : class
		{
			if (obj is T val)
			{
				result = val;
				return true;
			}
			result = null;
			return false;
		}

		[IteratorStateMachine(typeof(<WaitForPlayer>d__4))]
		public static IEnumerator WaitForPlayer(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPlayer>d__4(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetwork>d__5))]
		public static IEnumerator WaitForNetwork(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetwork>d__5(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForCondition>d__6))]
		public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForCondition>d__6(0)
			{
				condition = condition,
				timeout = timeout,
				onTimeout = onTimeout,
				onFinish = onFinish
			};
		}

		public static string GetHierarchyPath(this Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "null";
			}
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T component = gameObject.GetComponent<T>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			component = gameObject.AddComponent<T>();
			Logger.Debug("Added component " + typeof(T).Name + " to GameObject " + ((Object)gameObject).name);
			return component;
		}

		public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			Renderer component = gameObject.GetComponent<Renderer>();
			if ((Object)(object)component == (Object)null)
			{
				Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component");
				return null;
			}
			Color valueOrDefault = color.GetValueOrDefault();
			if (!color.HasValue)
			{
				((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f);
				color = valueOrDefault;
			}
			Shader val = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val);
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 1f);
			}
			Color value = color.Value;
			if (value.a <= 0f)
			{
				value.a = 0.2f;
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", value);
			}
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.EnableKeyword("_EMISSION");
				val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f);
			}
			val2.SetInt("_ZWrite", 0);
			val2.renderQueue = 3000;
			Material material = component.material;
			component.material = val2;
			return material;
		}
	}
}
namespace BusinessEmployment.BetterSafe
{
	internal class FilterHelper
	{
		[CompilerGenerated]
		private sealed class <WaitSearchAdd>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float timeout;

			private float <startTime>5__1;

			private IEnumerable<StorageEntity> <betterSafes>5__2;

			private IEnumerator<StorageEntity> <>s__3;

			private StorageEntity <betterSafe>5__4;

			private List<ItemSlot>.Enumerator <>s__5;

			private ItemSlot <slot>5__6;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitSearchAdd>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<betterSafes>5__2 = null;
				<>s__3 = null;
				<betterSafe>5__4 = null;
				<>s__5 = default(List<ItemSlot>.Enumerator);
				<slot>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0286: Unknown result type (might be due to invalid IL or missing references)
				//IL_0290: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (filter_Cash == null)
					{
						filter_Cash = new ItemFilter_Cash();
					}
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					<betterSafes>5__2 = null;
					break;
				}
				if (Time.time - <startTime>5__1 <= timeout)
				{
					<betterSafes>5__2 = from bi in (from p in Property.Properties.AsEnumerable()
							select p.BuildableItems into items
							where items != null
							select items.AsEnumerable()).Aggregate((IEnumerable<BuildableItem> a, IEnumerable<BuildableItem> b) => a.Concat(b))
						select Utils.Is<PlaceableStorageEntity>(bi, out PlaceableStorageEntity result) ? result : null into r
						where (Object)(object)r != (Object)null
						select r into pse
						where ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
						select pse.StorageEntity;
					<>s__3 = <betterSafes>5__2.GetEnumerator();
					try
					{
						while (<>s__3.MoveNext())
						{
							<betterSafe>5__4 = <>s__3.Current;
							<>s__5 = <betterSafe>5__4.ItemSlots.GetEnumerator();
							try
							{
								while (<>s__5.MoveNext())
								{
									<slot>5__6 = <>s__5.Current;
									if (!<slot>5__6.HardFilters.AsEnumerable().Any((ItemFilter itFi) => ((object)itFi).GetType() == ((object)filter_Cash).GetType()))
									{
										<slot>5__6.AddFilter((ItemFilter)(object)filter_Cash);
										<slot>5__6 = null;
									}
								}
							}
							finally
							{
								((IDisposable)<>s__5).Dispose();
							}
							<>s__5 = default(List<ItemSlot>.Enumerator);
							<betterSafe>5__4 = null;
						}
					}
					finally
					{
						if (<>s__3 != null)
						{
							<>s__3.Dispose();
						}
					}
					<>s__3 = null;
					<>2__current = (object)new WaitForSecondsRealtime(0.5f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ItemFilter_Cash filter_Cash;

		private static Instance _logger = Melon<BusinessEmployment>.Logger;

		[IteratorStateMachine(typeof(<WaitSearchAdd>d__2))]
		internal static IEnumerator WaitSearchAdd(float timeout)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitSearchAdd>d__2(0)
			{
				timeout = timeout
			};
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ItemFilter_Cash : ItemFilter
	{
		public override bool DoesItemMatchFilter(ItemInstance item)
		{
			CashInstance result;
			return Utils.Is<CashInstance>(item, out result);
		}
	}
	public class SafeCreator
	{
		internal const string SAFE_ID = "gold_safe";

		private const string SAFE_NAME = "Golden Safe";

		internal const int SLOT_COUNT = 20;

		public static bool SafeCreated;

		public static bool SafeAdded;

		private static readonly Color GoldMetalColor = new Color(1f, 0.766f, 0.336f, 1f);

		public static void CreateSafe()
		{
			BuildableItemDefinition val = BuildableItemCreator.CloneFrom("safe").WithBasicInfo("gold_safe", "Golden Safe", "An upgraded version of the safe. Can hold only cash.").WithPricing(BusinessEmployment.SafeCost.Value, 0.8f)
				.WithIcon(LoadIcon())
				.Build();
			BuildEvents.OnBuildableItemInitialized += ItemBuilt;
			BuildEvents.OnGridItemCreated += ItemBuilt;
			BuildEvents.OnSurfaceItemCreated += ItemBuilt;
			StorageEvents.OnStorageCreated += StorageCreated;
			StorageEvents.OnStorageLoading += StorageLoaded;
			StorageEvents.OnStorageOpening += StorageOpened;
			SafeCreated = true;
		}

		public static void AddToShop()
		{
			ItemDefinition itemDefinition = ItemManager.GetItemDefinition("gold_safe");
			if (itemDefinition == (ItemDefinition)null)
			{
				Melon<BusinessEmployment>.Logger.Error("Error while adding safe to shop");
				return;
			}
			Shop shopByName = ShopManager.GetShopByName("Bleuball's Boutique");
			if (shopByName == null)
			{
				Melon<BusinessEmployment>.Logger.Error("Shop not found");
				return;
			}
			shopByName.AddItem(itemDefinition, (float?)null);
			SafeAdded = true;
		}

		private static void EnsureCapacity(StorageEntity storage)
		{
			if (storage != null)
			{
				if (!storage.SetSlotCount(20))
				{
					Melon<BusinessEmployment>.Logger.Error("Failed to add additional slots");
				}
				else
				{
					MelonCoroutines.Start(FilterHelper.WaitSearchAdd(10f));
				}
			}
		}

		private static void StorageCreated(StorageEventArgs args)
		{
			if (args != null && args.Storage != null && args.ItemId == "gold_safe")
			{
				args.Storage.Name = "Golden Safe";
				EnsureCapacity(args.Storage);
			}
		}

		private static void StorageOpened(StorageEventArgs args)
		{
			if (args != null)
			{
				StorageEntity storage = args.Storage;
				if (storage != null)
				{
					storage.SyncCustomNameToDisplayName();
				}
			}
		}

		private static void StorageLoaded(StorageLoadingEventArgs args)
		{
			if (args != null && ((StorageEventArgs)args).Storage != null && ((StorageEventArgs)args).ItemId == "gold_safe")
			{
				((StorageEventArgs)args).Storage.Name = "Golden Safe";
				EnsureCapacity(((StorageEventArgs)args).Storage);
			}
		}

		private static void ItemBuilt(BuildEventArgs args)
		{
			if (SafeCreated && args != null && args.ItemId == "gold_safe")
			{
				MaterialHelper.ReplaceMaterials(args.GameObject, (Func<Material, bool>)((Material mat) => ((Object)mat).name.ToLower().Contains("safe_body")), (Action<Material>)delegate(Material material)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					MaterialHelper.RemoveAllTextures(material);
					MaterialHelper.SetColor(material, "_BaseColor", GoldMetalColor);
					MaterialHelper.SetColor(material, "_Color", GoldMetalColor);
					MaterialHelper.SetFloat(material, "_Metallic", 0.85f);
					MaterialHelper.SetFloat(material, "_Smoothness", 0.65f);
					MaterialHelper.SetFloat(material, "_Glossiness", 0.65f);
				});
			}
		}

		private static Sprite LoadIcon()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			return ImageUtils.LoadImageFromResource(executingAssembly, "BusinessEmployment.assets.safe_icon.png", 100f, (FilterMode)1);
		}
	}
	public class SafeMethods
	{
		public static void RefillSafe()
		{
			if (!BusinessEmployment.EnableSafeAutoRestock.Value)
			{
				return;
			}
			PlaceableStorageEntity result3;
			IEnumerable<StorageEntity> enumerable = from bi in (from b in Business.OwnedBusinesses.AsEnumerable()
					where ((Property)b).Employees.Count > 0
					select b into p
					select ((Property)p).BuildableItems into items
					where items != null
					select items.AsEnumerable()).Aggregate((IEnumerable<BuildableItem> a, IEnumerable<BuildableItem> b) => a.Concat(b))
				select Utils.Is<PlaceableStorageEntity>(bi, out result3) ? result3 : null into r
				where (Object)(object)r != (Object)null
				select r into pse
				where ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
				select pse.StorageEntity;
			float value = BusinessEmployment.EmpCut.Value;
			float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance;
			int num = ((((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).StackLimit == 1) ? 1000 : ((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).StackLimit);
			float num2 = 0f;
			float num3 = 1f + value / 100f;
			foreach (StorageEntity item in enumerable)
			{
				foreach (ItemSlot itemSlot in item.ItemSlots)
				{
					float num4 = 0f;
					if (Utils.Is<CashInstance>(itemSlot.ItemInstance, out CashInstance result))
					{
						if (result != null)
						{
							float num5 = (float)num - result.Balance;
							num4 = num5;
						}
					}
					else
					{
						num4 = num;
					}
					float num6 = num2 + num4;
					float num7 = num6 * num3;
					if (num7 > cashBalance)
					{
						float num8 = cashBalance / num3;
						num4 = num8 - num2;
					}
					if (num4 > 0f)
					{
						if (Utils.Is<CashInstance>(((ItemInstance)NetworkSingleton<MoneyManager>.Instance.cashInstance).GetCopy(-1), out CashInstance result2))
						{
							if (result2 == null)
							{
								continue;
							}
							result2.Balance = num4;
							itemSlot.InsertItem((ItemInstance)(object)result2);
						}
						num2 += num4;
					}
					if (num2 * num3 >= cashBalance)
					{
						break;
					}
				}
				if (num2 * num3 >= cashBalance)
				{
					break;
				}
			}
			float num9 = num2 * (value / 100f);
			float num10 = num2 + num9;
			NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(0f - num10, true, false);
			Melon<BusinessEmployment>.Logger.Msg($"Refilled safes! Inserted: {num2}, Employee cut: {num9}, Total cost: {num10}");
		}
	}
}
namespace BusinessEmployment.Behaviours
{
	public class LaunderBehaviour
	{
		private static readonly Dictionary<Packager, LaunderBehaviour> _instances = new Dictionary<Packager, LaunderBehaviour>();

		private readonly Packager employee;

		private readonly Property property;

		private Business propertyAsBusiness;

		private ELaunderEmployeeState state = ELaunderEmployeeState.Idle;

		private PlaceableStorageEntity? currentSE;

		private LaunderingStation? station;

		public LaunderBehaviourSaveData SaveData;

		private LaunderBehaviour(Packager employee)
		{
			this.employee = employee;
			property = ((Employee)employee).AssignedProperty;
			if (Utils.Is<Business>(property, out Business result))
			{
				if ((Object)(object)result == (Object)null)
				{
					Melon<BusinessEmployment>.Logger.Error("Property cannot be cast to business!");
				}
				propertyAsBusiness = result;
			}
			else
			{
				Melon<BusinessEmployment>.Logger.Error("Property cannot be cast to business!");
			}
			string propertyCode = property.PropertyCode;
			IEnumerable<LaunderBehaviourSaveData> source = LaunderBehaviourSave.Instance.SaveDatas.Where((LaunderBehaviourSaveData s) => s.PropertyCode == propertyCode);
			if (source.Any())
			{
				SaveData = source.First();
				return;
			}
			SaveData = new LaunderBehaviourSaveData
			{
				PropertyCode = propertyCode,
				MoneyLeftToLaunder = 0f
			};
			LaunderBehaviourSave.Instance.SaveDatas.Add(SaveData);
		}

		private static LaunderBehaviour? GetOrCreate(Packager employee)
		{
			if ((Object)(object)employee == (Object)null)
			{
				return null;
			}
			CleanupNullEmployees();
			if (_instances.TryGetValue(employee, out LaunderBehaviour value))
			{
				return value;
			}
			value = new LaunderBehaviour(employee);
			_instances[employee] = value;
			return value;
		}

		public static void Tick(Packager employee)
		{
			GetOrCreate(employee)?.Tick();
		}

		private void Tick()
		{
			if (!IsValidState())
			{
				SetIdleAndWaitOutside();
				return;
			}
			if (state == ELaunderEmployeeState.Idle && (!((Employee)employee).CanWork() || propertyAsBusiness.currentLaunderTotal >= propertyAsBusiness.LaunderCapacity))
			{
				SetIdleAndWaitOutside();
				return;
			}
			ProcessCurrentState();
			if (Time.frameCount % 30 == 0)
			{
				MelonDebug.Msg($"Cash: {SaveData.MoneyLeftToLaunder}, state: {state}");
			}
		}

		private bool IsValidState()
		{
			return (Object)(object)propertyAsBusiness != (Object)null && (Object)(object)property != (Object)null && (Object)(object)employee != (Object)null;
		}

		private void SetIdleAndWaitOutside()
		{
			state = ELaunderEmployeeState.Idle;
			((Employee)employee).SubmitNoWorkReason("There's nothing for me to do right now.", "I need to have cash to launder or free laundering capacity.", 0);
			((Employee)employee).SetIdle(true);
			Packager obj = employee;
			if (obj != null)
			{
				((Employee)obj).SetWaitOutside(true);
			}
		}

		private void ProcessCurrentState()
		{
			switch (state)
			{
			case ELaunderEmployeeState.Idle:
				HandleIdleState();
				break;
			case ELaunderEmployeeState.RetrieveCash:
				HandleRetrieveCashState();
				break;
			case ELaunderEmployeeState.DepositCash:
				HandleDepositCashState();
				break;
			default:
				HandleIdleState();
				break;
			}
		}

		private void HandleIdleState()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (SaveData.MoneyLeftToLaunder > 0f && propertyAsBusiness.currentLaunderTotal < propertyAsBusiness.LaunderCapacity && EnsureLaunderingStationExists())
			{
				((Employee)employee).SetWaitOutside(false);
				MoveToLaunderingStation();
				return;
			}
			List<PlaceableStorageEntity> list = GetAllStoragesWithCash().ToList();
			if (!list.Any())
			{
				MelonDebug.Msg("No reachable storage with cash found");
				return;
			}
			foreach (PlaceableStorageEntity item in list)
			{
				Vector3? val = FindReachableAccessPoint(item);
				if (val.HasValue)
				{
					((Employee)employee).SetWaitOutside(false);
					currentSE = item;
					((Employee)employee).SetDestination(val.Value, true);
					state = ELaunderEmployeeState.RetrieveCash;
					break;
				}
			}
		}

		private Vector3? FindReachableAccessPoint(PlaceableStorageEntity storage)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (((storage != null) ? storage.AccessPoints : null) == null)
			{
				MelonDebug.Error("Storage accesspoints is null");
				return null;
			}
			Transform[] accessPoints = storage.AccessPoints;
			foreach (Transform val in accessPoints)
			{
				if (((NPC)employee).Movement.CanGetTo(val.position, 1f))
				{
					return val.position;
				}
			}
			MelonDebug.Error("Wasn't able to find a good position to move to");
			return null;
		}

		private void HandleRetrieveCashState()
		{
			if (((NPC)employee).Movement.IsMoving)
			{
				return;
			}
			if ((Object)(object)currentSE == (Object)null)
			{
				state = ELaunderEmployeeState.Idle;
				return;
			}
			CollectCashFromStorage();
			if (!EnsureLaunderingStationExists())
			{
				state = ELaunderEmployeeState.Idle;
			}
			else
			{
				MoveToLaunderingStation();
			}
		}

		private void CollectCashFromStorage()
		{
			PlaceableStorageEntity? obj = currentSE;
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				StorageEntity storageEntity = obj.StorageEntity;
				obj2 = ((storageEntity != null) ? storageEntity.ItemSlots : null);
			}
			if (obj2 == null)
			{
				MelonDebug.Error("Storage itemslots is null");
				return;
			}
			List<ItemSlot> itemSlots = currentSE.StorageEntity.ItemSlots;
			for (int i = 0; i < itemSlots.Count; i++)
			{
				if (Utils.Is<CashInstance>(itemSlots[i].ItemInstance, out CashInstance result))
				{
					currentSE.StorageEntity.SetSlotLocked((NetworkConnection)null, i, true, ((NetworkBehaviour)employee).NetworkObject, "Taking out items");
					if (result != null)
					{
						WithdrawForLaunder(propertyAsBusiness.LaunderCapacity, result);
					}
				}
				currentSE.StorageEntity.SetSlotLocked((NetworkConnection)null, i, false, ((NetworkBehaviour)employee).NetworkObject, "Taking out items");
				if (SaveData.MoneyLeftToLaunder >= propertyAsBusiness.LaunderCapacity)
				{
					break;
				}
			}
		}

		private bool EnsureLaunderingStationExists()
		{
			if ((Object)(object)station != (Object)null)
			{
				return true;
			}
			station = (from bi in property.BuildableItems.AsEnumerable()
				select Utils.Is<LaunderingStation>(bi, out LaunderingStation result) ? result : null).FirstOrDefault((Func<LaunderingStation, bool>)((LaunderingStation r) => (Object)(object)r != (Object)null));
			if ((Object)(object)station != (Object)null)
			{
				return true;
			}
			Melon<BusinessEmployment>.Logger.Error("Laundering station not found!");
			return false;
		}

		private void MoveToLaunderingStation()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_006c: 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)
			if (!((Object)(object)station == (Object)null))
			{
				Vector3 val;
				if (!((Object)(object)((BuildableItem)station).BoundingCollider != (Object)null))
				{
					val = ((Component)station).transform.position;
				}
				else
				{
					Bounds bounds = ((Collider)((BuildableItem)station).BoundingCollider).bounds;
					val = ((Bounds)(ref bounds)).ClosestPoint(((Component)employee).transform.position);
				}
				Vector3 val2 = val;
				Vector3 val3 = default(Vector3);
				((NPC)employee).Movement.GetClosestReachablePoint(val2, ref val3);
				((Employee)employee).SetDestination(val3, true);
				currentSE = null;
				state = ELaunderEmployeeState.DepositCash;
			}
		}

		private void HandleDepositCashState()
		{
			if (!((NPC)employee).Movement.IsMoving)
			{
				((NPC)employee).SetAnimationTrigger_Networked((NetworkConnection)null, "GrabItem");
				float num = propertyAsBusiness.LaunderCapacity - propertyAsBusiness.currentLaunderTotal;
				if (num > 0f)
				{
					float num2 = Math.Min(SaveData.MoneyLeftToLaunder, num);
					propertyAsBusiness.StartLaunderingOperation(num2, 0);
					SaveData.MoneyLeftToLaunder -= num2;
				}
				state = ELaunderEmployeeState.Idle;
			}
		}

		private void WithdrawForLaunder(float launderTarget, CashInstance cashInstance)
		{
			float num = launderTarget - SaveData.MoneyLeftToLaunder;
			if (!(num <= 0f) && !(cashInstance.Balance <= 0f))
			{
				float num2 = Math.Min(num, cashInstance.Balance);
				((NPC)employee).SetAnimationTrigger_Networked((NetworkConnection)null, "GrabItem");
				cashInstance.ChangeBalance(0f - num2);
				SaveData.MoneyLeftToLaunder += num2;
			}
		}

		public IEnumerable<PlaceableStorageEntity?> GetAllStoragesWithCash()
		{
			PlaceableStorageEntity result2;
			CashInstance result;
			return from bi in property.BuildableItems.AsEnumerable()
				select Utils.Is<PlaceableStorageEntity>(bi, out result2) ? result2 : null into r
				where (Object)(object)r != (Object)null
				select r into pse
				where (Object)(object)pse.StorageEntity != (Object)(object)((Employee)employee).GetHome().Storage
				where pse.OutputSlots.AsEnumerable().Any((ItemSlot os) => Utils.Is<CashInstance>(os.ItemInstance, out result))
				orderby ((BuildableItem)pse).SaveFolderName.Contains("gold_safe")
				select pse;
		}

		public static void Remove(Packager employee)
		{
			_instances.Remove(employee);
		}

		private static void CleanupNullEmployees()
		{
			List<Packager> list = _instances.Keys.Where((Packager e) => (Object)(object)e == (Object)null).ToList();
			foreach (Packager item in list)
			{
				_instances.Remove(item);
			}
		}
	}
	public enum ELaunderEmployeeState
	{
		Idle,
		RetrieveCash,
		DepositCash
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}