Decompiled source of OrganizedCrime v1.0.0

Mods/OrganizedCrime.dll

Decompiled a day ago
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using HarmonyLib;
using Il2Cpp;
using Il2CppFishNet;
using Il2CppFishNet.Connection;
using Il2CppFishNet.Managing;
using Il2CppFishNet.Managing.Client;
using Il2CppFishNet.Managing.Object;
using Il2CppFishNet.Managing.Server;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.Calling;
using Il2CppScheduleOne.Cartel;
using Il2CppScheduleOne.Core.Items.Framework;
using Il2CppScheduleOne.Delivery;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Doors;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.EntityFramework;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Interaction;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.Persistence.Datas;
using Il2CppScheduleOne.Persistence.Loaders;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Product.Packaging;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.ScriptableObjects;
using Il2CppScheduleOne.Storage;
using Il2CppScheduleOne.Tiles;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Management;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.Delivery;
using Il2CppScheduleOne.Vehicles;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using OrganizedCrime;
using OrganizedCrime.Model;
using OrganizedCrime.Persistence;
using OrganizedCrime.Runtime;
using S1API.Building;
using S1API.DeadDrops;
using S1API.Entities;
using S1API.GameTime;
using S1API.Items;
using S1API.Lifecycle;
using S1API.Messaging;
using S1API.Money;
using S1API.PhoneCalls;
using S1API.Products;
using S1API.Quests;
using S1API.Quests.Constants;
using S1API.Storages;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(OrganizedCrimeMod), "Organized Crime", "1.0.0", "MadJag Studios", null)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OrganizedCrime
{
	public sealed class OrganizedCrimeMod : MelonMod
	{
		private sealed class FishWarehousePersistenceReplayOperations : IFishWarehousePersistenceReplayOperations
		{
			private readonly RuntimePropertyHost _propertyHost;

			private readonly FishWarehouseRuntimeService _runtimeService;

			private readonly FishWarehousePersistenceService _persistenceService;

			private readonly FishWarehousePropertyCaptureService _captureService;

			private readonly Action<string> _log;

			private FishWarehousePropertyReplayHost? _objectReplay;

			private FishWarehouseEmployeeReplayHost? _employeeReplay;

			public bool IsRuntimeReady => _propertyHost.PersistenceRuntimeReady;

			public bool IsNavigationReady => _runtimeService.EmployeeNavigationReady;

			public FishWarehousePersistenceReplayOperations(RuntimePropertyHost propertyHost, FishWarehouseRuntimeService runtimeService, FishWarehousePersistenceService persistenceService, FishWarehousePropertyCaptureService captureService, Action<string> log)
			{
				_propertyHost = propertyHost;
				_runtimeService = runtimeService;
				_persistenceService = persistenceService;
				_captureService = captureService;
				_log = log;
			}

			public void ConfigureReplay(bool objectReplayRequired, int? employeeAgentTypeId)
			{
				_propertyHost.ConfigurePersistenceReplay(objectReplayRequired, employeeAgentTypeId);
			}

			public void RequestOwnedRestore()
			{
				_runtimeService.RequestLoadedOwnedRestore();
			}

			public void ResetRuntimeReferences()
			{
				_objectReplay = null;
				_employeeReplay = null;
			}

			public FishWarehouseReplayOperationResult ReplayObjects()
			{
				PropertyData capturedPropertyData = _captureService.CapturedPropertyData;
				Property currentProperty = _propertyHost.CurrentProperty;
				if (capturedPropertyData == null || currentProperty == null)
				{
					return FishWarehouseReplayOperationResult.Failed("captured PropertyData or runtime Property was unavailable.");
				}
				if (_objectReplay == null)
				{
					if (!FishWarehouseNativePropertyReplayAdapter.TryCreateDescriptors(capturedPropertyData, out IReadOnlyList<FishWarehouseSavedObjectDescriptor> descriptors, out string failureReason))
					{
						return FishWarehouseReplayOperationResult.Failed(failureReason ?? "object replay descriptors were unavailable.");
					}
					_objectReplay = new FishWarehousePropertyReplayHost(new FishWarehouseNativePropertyReplayAdapter(capturedPropertyData, currentProperty, _log), descriptors, null, _log);
				}
				FishWarehousePropertyReplayResult fishWarehousePropertyReplayResult = _objectReplay.Replay();
				if (fishWarehousePropertyReplayResult.State == FishWarehousePropertyReplayState.Failed)
				{
					return FishWarehouseReplayOperationResult.Failed(fishWarehousePropertyReplayResult.FailureReason ?? "native object replay failed.");
				}
				if (fishWarehousePropertyReplayResult.State != FishWarehousePropertyReplayState.Succeeded)
				{
					return FishWarehouseReplayOperationResult.Pending();
				}
				return FishWarehouseReplayOperationResult.Succeeded(fishWarehousePropertyReplayResult.ResolvedObjectCount);
			}

			public FishWarehouseReplayOperationResult MarkObjectsReplayed()
			{
				FishWarehousePropertyReplayHost? objectReplay = _objectReplay;
				if (objectReplay == null || objectReplay.Result.State != FishWarehousePropertyReplayState.Succeeded)
				{
					return FishWarehouseReplayOperationResult.Failed("native object replay was not complete before the runtime gate was marked.");
				}
				_runtimeService.MarkPersistenceObjectsReplayed();
				string[] savedHomeGuids = (from record in _captureService.CapturedEmployeeRecords
					select record.BedGuid into guid
					where !string.IsNullOrWhiteSpace(guid)
					select guid).ToArray();
				switch (_propertyHost.AssessRestoredEmployeeHome((IReadOnlyCollection<string>?)(object)savedHomeGuids))
				{
				case FishWarehouseEmployeeHomeAdoptionResult.MultipleFound:
					return FishWarehouseReplayOperationResult.Failed("multiple restored Fish Warehouse employee homes were found; authored fallback was not permitted.");
				case FishWarehouseEmployeeHomeAdoptionResult.Failed:
					return FishWarehouseReplayOperationResult.Failed("restored Fish Warehouse employee-home adoption failed.");
				case FishWarehouseEmployeeHomeAdoptionResult.Adopted:
					_runtimeService.MarkPersistenceEmployeeHomeRestored();
					break;
				default:
				{
					FishWarehouseSaveState? currentState = _persistenceService.CurrentState;
					if ((object)currentState != null && currentState.EmployeeHomePlaced && !_runtimeService.TryPlaceEmployeeHome())
					{
						return FishWarehouseReplayOperationResult.Failed("saved Fish Warehouse employee home was not restored and authored fallback placement failed.");
					}
					break;
				}
				}
				return FishWarehouseReplayOperationResult.Succeeded(_objectReplay.Result.ResolvedObjectCount);
			}

			public FishWarehouseReplayOperationResult ReplayEmployees()
			{
				PropertyData capturedPropertyData = _captureService.CapturedPropertyData;
				Property currentProperty = _propertyHost.CurrentProperty;
				if (capturedPropertyData == null || currentProperty == null)
				{
					return FishWarehouseReplayOperationResult.Failed("captured PropertyData or runtime Property was unavailable.");
				}
				if (_employeeReplay == null)
				{
					IReadOnlyList<FishWarehouseEmployeeReplayDescriptor> capturedEmployees = FishWarehousePropertyCaptureService.CreateEmployeeReplayDescriptors(_captureService.CapturedEmployeeRecords);
					if (!_propertyHost.TryCreateEmployeeReplayAdapter(capturedPropertyData, out IFishWarehouseNativeEmployeeReplayAdapter adapter, out string failureReason, _persistenceService.CurrentState?.Replay?.InventoryRestoredEmployeeGuids))
					{
						return FishWarehouseReplayOperationResult.Failed(failureReason ?? "employee replay adapter was unavailable.");
					}
					_employeeReplay = new FishWarehouseEmployeeReplayHost(adapter, capturedEmployees, _persistenceService.CurrentState?.UnsupportedEmployees ?? Array.Empty<FishWarehouseUnsupportedEmployeeRecord>(), null, _log);
				}
				FishWarehouseEmployeeReplayResult fishWarehouseEmployeeReplayResult = _employeeReplay.Replay(IsNavigationReady);
				if (fishWarehouseEmployeeReplayResult.State == FishWarehouseEmployeeReplayState.Pending)
				{
					return new FishWarehouseReplayOperationResult(FishWarehouseReplayOperationState.Pending, 0, null, fishWarehouseEmployeeReplayResult.InventoryRestoredEmployeeGuids);
				}
				if (fishWarehouseEmployeeReplayResult.State == FishWarehouseEmployeeReplayState.Failed || !fishWarehouseEmployeeReplayResult.CanAdvanceEmployeesReplayed)
				{
					return new FishWarehouseReplayOperationResult(FishWarehouseReplayOperationState.Failed, 0, fishWarehouseEmployeeReplayResult.FailureReason ?? fishWarehouseEmployeeReplayResult.PrimaryFailureReason ?? "supported employee replay did not complete.", fishWarehouseEmployeeReplayResult.InventoryRestoredEmployeeGuids);
				}
				if (!_persistenceService.TryMergeUnsupportedEmployees(fishWarehouseEmployeeReplayResult.UnsupportedEmployees))
				{
					return FishWarehouseReplayOperationResult.Failed("unsupported employee records could not be persisted.");
				}
				_log($"Fish Warehouse employee replay summary: {fishWarehouseEmployeeReplayResult.ReplayedEmployeeCount}/{fishWarehouseEmployeeReplayResult.SupportedCapturedEmployeeCount} supported employees replayed.");
				return new FishWarehouseReplayOperationResult(FishWarehouseReplayOperationState.Succeeded, fishWarehouseEmployeeReplayResult.ReplayedEmployeeCount, null, fishWarehouseEmployeeReplayResult.InventoryRestoredEmployeeGuids);
			}

			public FishWarehouseDeliveryRestoreFlushResult ReleaseDeliveries()
			{
				return FishWarehouseDeliveryRestorePatch.FlushIfReady();
			}
		}

		private FishWarehouseRuntimeService? _fishWarehouseRuntimeService;

		private RuntimePropertyHost? _runtimePropertyHost;

		private FishWarehousePersistenceService? _fishWarehousePersistenceService;

		private FishWarehousePropertyCaptureService? _fishWarehousePropertyCaptureService;

		private FishWarehousePersistenceReplayService? _fishWarehousePersistenceReplayService;

		private LocalPressureRuntimeComposition? _localPressureRuntime;

		private NativeLawResponseModComposition? _nativeLawResponseComposition;

		private NativeLawResponseController? _nativeLawResponseController;

		private PoliceCustodyEvidenceBridge? _policeCustodyEvidenceBridge;

		private SyndicateHqHostContextAdapter? _syndicateHqHostContext;

		private Release1StoryRuntimeService? _release1StoryRuntime;

		private Release1ProductionComposition? _release1ProductionComposition;

		private Release1ChiefComposition? _release1ChiefComposition;

		private SyndicateHqRuntimeComposition? _syndicateHqComposition;

		private SyndicateHqNativeStorageRuntime? _syndicateHqStorageRuntime;

		private IRelease1SmallCourtesyWorld? _release1SmallCourtesyWorld;

		private bool _initialized;

		private bool _ownerQaKeysEnabled;

		private bool _theEnvelopeCashGateDumpNext = true;

		private bool _theEnvelopeClosetCashGateDumpNext = true;

		private bool _keepTheLightsOffProductionGateDumpNext = true;

		private OrganizedCrimeTimingReceipts _timing = OrganizedCrimeTimingReceipts.Disabled;

		public override void OnInitializeMelon()
		{
			if (_initialized)
			{
				MelonLogger.Warning("[Organized Crime] duplicate initialization was ignored.");
				return;
			}
			_initialized = true;
			OrganizedCrimeLog.Warning = delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			};
			OrganizedCrimeLog.Receipt = delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			};
			MelonLogger.Msg("[Organized Crime] production runtime shell loaded.");
			_ownerQaKeysEnabled = OwnerQaKeysPreference.Read();
			_timing = new OrganizedCrimeTimingReceipts((Action<string>?)MelonLogger.Msg, TimingReceiptThresholdPreference.Read());
			if (_timing.IsEnabled)
			{
				MelonLogger.Msg($"[Organized Crime] Timing receipts report any phase at or above {_timing.ThresholdMs} ms.");
			}
			if (_ownerQaKeysEnabled)
			{
				MelonLogger.Msg("[Organized Crime] Owner QA keys are enabled by preference; F8 recognition and fish warehouse developer keys are live.");
			}
			SyndicateHqHostContextAdapter syndicateHqHostContextAdapter = (_syndicateHqHostContext = new SyndicateHqHostContextAdapter());
			_release1StoryRuntime = new Release1StoryRuntimeService(syndicateHqHostContextAdapter, CreateRelease1StoryRepository);
			Release1PresentationMode release1PresentationMode = Release1PresentationModePreference.Read();
			S1ApiRelease1NativePresentation native = ((release1PresentationMode == Release1PresentationMode.Native) ? new S1ApiRelease1NativePresentation(Release1QuestPersistencePolicyPreference.Read(), delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}) : null);
			SyndicateHqNativeStorageRuntime syndicateHqNativeStorageRuntime = (_syndicateHqStorageRuntime = new SyndicateHqNativeStorageRuntime(new SyndicateHqNativeStorageBoundary
			{
				Timing = _timing
			}, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}, OrganizedCrimeLog.Receipt));
			S1ApiRelease1SmallCourtesyWorld s1ApiRelease1SmallCourtesyWorld = (S1ApiRelease1SmallCourtesyWorld)(_release1SmallCourtesyWorld = new S1ApiRelease1SmallCourtesyWorld(syndicateHqHostContextAdapter, syndicateHqNativeStorageRuntime, null, ((MelonBase)this).HarmonyInstance));
			SyndicateHqDoorObserver hqObserver = null;
			_release1ProductionComposition = new Release1ProductionComposition(_release1StoryRuntime, new Release1PostBenziesUnlockReader(syndicateHqHostContextAdapter, new S1CartelStatusSource()), new S1ApiRelease1PhoneCallQueue(), s1ApiRelease1SmallCourtesyWorld, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}, null, null, null, release1PresentationMode, native, delegate
			{
				SyndicateHqDoorFingerprint syndicateHqDoorFingerprint = hqObserver?.CurrentFingerprint;
				return ((object)syndicateHqDoorFingerprint == null || !syndicateHqDoorFingerprint.Position.IsFinite) ? null : new Release1WorldPoint(syndicateHqDoorFingerprint.Position.X, syndicateHqDoorFingerprint.Position.Y, syndicateHqDoorFingerprint.Position.Z);
			});
			_release1StoryRuntime.Timing = _timing;
			_release1ProductionComposition.Timing = _timing;
			_release1ProductionComposition.KeepTheLightsOff.Service.Timing = _timing;
			_release1ProductionComposition.TheEnvelope.Service.Timing = _timing;
			if (!SyndicateHqStorageLoadPatch.Apply(((MelonBase)this).HarmonyInstance, syndicateHqNativeStorageRuntime, new SyndicateHqStorageLoadContextAdapter(), delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}, OrganizedCrimeLog.Receipt))
			{
				MelonLogger.Warning("[Organized Crime] Native Syndicate HQ storage will remain inert because its exact vanilla load prefix was unavailable.");
			}
			SyndicateHqRuntimeService hqRuntime = null;
			hqObserver = new SyndicateHqDoorObserver(delegate(SyndicateHqDoorFingerprint fingerprint, long generation)
			{
				hqRuntime?.HandleDoorInteraction(fingerprint, generation);
			}, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			})
			{
				Timing = _timing
			};
			SyndicateHqInteriorRuntime interior = new SyndicateHqInteriorRuntime(delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}, syndicateHqNativeStorageRuntime)
			{
				Timing = _timing
			};
			hqRuntime = new SyndicateHqRuntimeService(syndicateHqHostContextAdapter, new Release1StorySyndicateHqUnlockAuthority(syndicateHqHostContextAdapter, _release1StoryRuntime), hqObserver, interior, new SyndicateHqNativePlayerTransport(delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}), delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			});
			_syndicateHqComposition = new SyndicateHqRuntimeComposition(hqRuntime, delegate
			{
				_syndicateHqHostContext?.BeginLoad();
			});
			FishWarehouseManagementCanvasPatch.Apply(((MelonBase)this).HarmonyInstance);
			FishWarehouseNativeGridPlacementPatches.Apply(((MelonBase)this).HarmonyInstance);
			FishWarehouseDockOccupantRefreshPatch.Apply(((MelonBase)this).HarmonyInstance);
			RuntimePropertyHost propertyHost = new RuntimePropertyHost();
			_runtimePropertyHost = propertyHost;
			FishWarehouseDeliveryRestorePatch.Apply(((MelonBase)this).HarmonyInstance, () => propertyHost.CanRestoreDeliveries, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			_fishWarehouseRuntimeService = new FishWarehouseRuntimeService(propertyHost, RuntimePropertyReadiness.IsFishWarehouseReady, propertyHost.TryPlaceEmployeeHome, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			FishWarehousePropertySnapshotStore snapshotStore = new FishWarehousePropertySnapshotStore();
			FishWarehousePropertyCaptureService captureService = null;
			FishWarehouseReplayLifecycle fishWarehouseReplayLifecycle = new FishWarehouseReplayLifecycle((FishWarehouseReplayCheckpoint checkpoint) => captureService?.GetRecoveryPrerequisites(checkpoint) ?? new FishWarehouseCaptureRecoveryPrerequisites(ByteProtectionSucceeded: false, InspectionSucceeded: false, TypedPayloadRetentionSucceeded: false, CheckpointPersistenceSucceeded: false));
			_fishWarehousePersistenceService = new FishWarehousePersistenceService(new FishWarehouseSaveStore(), GetActiveSaveFolder, () => _fishWarehouseRuntimeService?.CaptureSaveState() ?? FishWarehouseSaveState.UnownedState(), ApplyLoadedSaveState, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			}, snapshotStore, fishWarehouseReplayLifecycle);
			captureService = new FishWarehousePropertyCaptureService(snapshotStore, new FishWarehouseNativePropertySnapshotInspector(), _fishWarehousePersistenceService, fishWarehouseReplayLifecycle, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			_fishWarehousePropertyCaptureService = captureService;
			FishWarehouseRuntimeService runtimeService = _fishWarehouseRuntimeService;
			FishWarehousePersistenceService persistenceService = _fishWarehousePersistenceService;
			FishWarehousePersistenceReplayOperations replayOperations = new FishWarehousePersistenceReplayOperations(propertyHost, runtimeService, persistenceService, captureService, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			_fishWarehousePersistenceReplayService = new FishWarehousePersistenceReplayService(fishWarehouseReplayLifecycle, GetActiveSaveFolder, captureService.TryRecoverAtLoadComplete, persistenceService.HandleLoadComplete, () => persistenceService.CurrentState, replayOperations, persistenceService.TryPersistReplayCheckpoint, delegate
			{
				captureService.ResetRuntimeReferences();
				replayOperations.ResetRuntimeReferences();
				persistenceService.PrimeStateForLoad();
			}, FishWarehouseDeliveryRestorePatch.Reset, delegate
			{
				if (!runtimeService.PrepareForLoad())
				{
					MelonLogger.Warning("[Organized Crime] Fish Warehouse runtime Property could not be fully prepared for the next save load.");
				}
			}, null, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			FishWarehousePropertyLoadCapturePatch.Apply(((MelonBase)this).HarmonyInstance, IsAuthoritativeHost, GetActiveSaveFolder, captureService, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			});
			FishWarehouseNativePropertyWriteGuardPatch.Apply(((MelonBase)this).HarmonyInstance, IsAuthoritativeHost, () => captureService.IsDegraded);
			GameLifecycle.OnSaveComplete += HandleSaveComplete;
			GameLifecycle.OnSaveStart += HandleSaveStart;
			GameLifecycle.OnPreLoad += HandlePreLoad;
			GameLifecycle.OnLoadComplete += HandleLoadComplete;
			GameLifecycle.OnPreSceneChange += HandlePreSceneChange;
			_nativeLawResponseComposition = new NativeLawResponseModComposition(CreateLocalPressureRepository, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}, delegate(string message)
			{
				MelonLogger.Msg("[Organized Crime] " + message);
			}, OrganizedCrimeLog.Receipt);
			_nativeLawResponseController = _nativeLawResponseComposition.Controller;
			_localPressureRuntime = _nativeLawResponseComposition.LocalPressureRuntime;
			_policeCustodyEvidenceBridge = new PoliceCustodyEvidenceBridge(new CustodyEntryGate(), _localPressureRuntime.Service, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			});
			PoliceCustodyPatch.Apply(((MelonBase)this).HarmonyInstance, _policeCustodyEvidenceBridge, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			});
			S1ApiRelease1NativePresentation native2 = ((release1PresentationMode == Release1PresentationMode.Native) ? new S1ApiRelease1NativePresentation(Release1QuestPersistencePolicyPreference.Read(), "oc_release1_chief_campbell", () => (NPC)(object)new Release1ChiefCampbellNpc(), (NPC npc) => npc is Release1ChiefCampbellNpc, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			}) : null);
			LocalPressureRuntimeService localPressureService = _localPressureRuntime.Service;
			_release1ChiefComposition = new Release1ChiefComposition(_release1StoryRuntime, s1ApiRelease1SmallCourtesyWorld, _nativeLawResponseComposition.ChiefObserver, (string playerId) => (!localPressureService.TryGetState(playerId, out LocalPressureState state)) ? null : state, (string playerId) => localPressureService.TryApplyRecordWipe(playerId, localPressureService.SessionEpoch, localPressureService.LoadEpoch), delegate(out Guid sessionEpoch, out long loadEpoch)
			{
				sessionEpoch = localPressureService.SessionEpoch;
				loadEpoch = localPressureService.LoadEpoch;
				return localPressureService.Phase == LocalPressureRuntimePhase.Active;
			}, release1PresentationMode, native2, delegate(string message)
			{
				MelonLogger.Warning("[Organized Crime] " + message);
			});
		}

		public override void OnDeinitializeMelon()
		{
			Release1LockdownGatePatch.Reset();
			_syndicateHqStorageRuntime?.MarkTeardown();
			if (_syndicateHqComposition != null && !_syndicateHqComposition.TryDispose())
			{
				MelonLogger.Warning("[Organized Crime] Syndicate HQ deinitialization remains pending until exact listener cleanup succeeds.");
			}
			_syndicateHqComposition = null;
			SyndicateHqStorageLoadPatch.Reset();
			_syndicateHqStorageRuntime?.Dispose();
			_syndicateHqStorageRuntime = null;
			_release1ProductionComposition?.Dispose();
			_release1ProductionComposition = null;
			_release1ChiefComposition?.Dispose();
			_release1ChiefComposition = null;
			_release1SmallCourtesyWorld = null;
			_release1StoryRuntime?.Dispose();
			_release1StoryRuntime = null;
			_syndicateHqHostContext = null;
			PoliceCustodyPatch.Reset();
			_policeCustodyEvidenceBridge?.Dispose();
			_policeCustodyEvidenceBridge = null;
			_nativeLawResponseComposition?.Dispose();
			_nativeLawResponseComposition = null;
			_nativeLawResponseController = null;
			_localPressureRuntime = null;
			FishWarehouseManagementCanvasPatch.SetTargetProperty(null);
			FishWarehouseDeliveryRestorePatch.Reset();
			FishWarehousePropertyLoadCapturePatch.Reset();
			FishWarehouseNativePropertyWriteGuardPatch.Reset();
			GameLifecycle.OnSaveComplete -= HandleSaveComplete;
			GameLifecycle.OnSaveStart -= HandleSaveStart;
			GameLifecycle.OnPreLoad -= HandlePreLoad;
			GameLifecycle.OnLoadComplete -= HandleLoadComplete;
			GameLifecycle.OnPreSceneChange -= HandlePreSceneChange;
			_fishWarehousePersistenceReplayService = null;
			_fishWarehousePersistenceService = null;
			_fishWarehousePropertyCaptureService?.Reset();
			_fishWarehousePropertyCaptureService = null;
			_fishWarehouseRuntimeService = null;
			_runtimePropertyHost = null;
			_initialized = false;
		}

		public override void OnUpdate()
		{
			//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_056f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			_syndicateHqComposition?.Update();
			_release1ProductionComposition?.Update();
			_release1ChiefComposition?.Update();
			_localPressureRuntime?.Service.PumpReadiness();
			if (IsAuthoritativeHost())
			{
				_fishWarehouseRuntimeService?.Update();
				_fishWarehousePersistenceReplayService?.Update();
			}
			_runtimePropertyHost?.EnsureManagementWorldspaceUiContainerForOpenCanvas();
			if (!_ownerQaKeysEnabled)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)92))
			{
				_fishWarehouseRuntimeService?.ToggleDeveloperLifecycle();
			}
			if (Input.GetKeyDown((KeyCode)111))
			{
				_fishWarehouseRuntimeService?.TryUnlockDeveloperLifecycle();
			}
			if (Input.GetKeyDown((KeyCode)112))
			{
				_fishWarehouseRuntimeService?.TryPlaceEmployeeHome();
			}
			if (Input.GetKeyDown((KeyCode)289) && _syndicateHqHostContext != null && _release1StoryRuntime != null)
			{
				Release1StoryOwnerQaRecognitionResult release1StoryOwnerQaRecognitionResult = Release1StoryOwnerQaRecognitionHarness.TryRecognize(_syndicateHqHostContext, _release1StoryRuntime);
				MelonLogger.Msg($"[Organized Crime] OC-48 owner QA recognition: {release1StoryOwnerQaRecognitionResult.Status}: {release1StoryOwnerQaRecognitionResult.Message}");
			}
			if (Input.GetKeyDown((KeyCode)290) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult = Release1WrongAddressStagingHarness.TryStage(_release1SmallCourtesyWorld);
				MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: stage status {release1StagingHarnessResult.Status}");
				foreach (string line in release1StagingHarnessResult.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-52 staging proof: " + line);
				}
			}
			if (Input.GetKeyDown((KeyCode)291) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult2 = Release1WrongAddressStagingHarness.TryDump(_release1SmallCourtesyWorld);
				MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: dump status {release1StagingHarnessResult2.Status}");
				foreach (string line2 in release1StagingHarnessResult2.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-52 staging proof: " + line2);
				}
				try
				{
					List<WorldStorageEntity> all = WorldStorageEntity.All;
					int value = all?.Count ?? 0;
					MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: world storage entities: {value}");
					if (all != null)
					{
						Enumerator<WorldStorageEntity> enumerator2 = all.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							WorldStorageEntity current3 = enumerator2.Current;
							if ((Object)(object)current3 == (Object)null)
							{
								continue;
							}
							List<ItemSlot> itemSlots = ((StorageEntity)current3).ItemSlots;
							int value2 = itemSlots?.Count ?? 0;
							int num = 0;
							if (itemSlots != null)
							{
								Enumerator<ItemSlot> enumerator3 = itemSlots.GetEnumerator();
								while (enumerator3.MoveNext())
								{
									ItemSlot current4 = enumerator3.Current;
									if (current4 != null && current4.Quantity > 0)
									{
										num++;
									}
								}
							}
							MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: entity {current3.GUID} name {((Object)((Component)current3).gameObject).name} changed {current3.HasChanged} slots {value2} occupied {num}");
							if (itemSlots == null)
							{
								continue;
							}
							for (int i = 0; i < itemSlots.Count; i++)
							{
								ItemSlot val = itemSlots[i];
								if (val != null && val.Quantity > 0)
								{
									ItemInstance itemInstance = val.ItemInstance;
									string value3 = ((itemInstance == null) ? "null" : ((BaseItemInstance)itemInstance).ID);
									MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: entity {current3.GUID} slot {i} id {value3} quantity {val.Quantity}");
								}
							}
						}
					}
				}
				catch (Exception ex)
				{
					MelonLogger.Msg("[Organized Crime] OC-52 staging proof: world storage dump failed: " + ex.Message);
				}
				try
				{
					List<DeadDrop> deadDrops = DeadDrop.DeadDrops;
					int value4 = deadDrops?.Count ?? 0;
					MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: dead drops: {value4}");
					if (deadDrops != null)
					{
						Enumerator<DeadDrop> enumerator4 = deadDrops.GetEnumerator();
						while (enumerator4.MoveNext())
						{
							DeadDrop current5 = enumerator4.Current;
							if (!((Object)(object)current5 == (Object)null))
							{
								WorldStorageEntity storage = current5.Storage;
								if ((Object)(object)storage == (Object)null)
								{
									MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: drop {current5.DeadDropName} guid {current5.GUID} storage null");
								}
								else
								{
									MelonLogger.Msg($"[Organized Crime] OC-52 staging proof: drop {current5.DeadDropName} guid {current5.GUID} storage {storage.GUID} storageName {((Object)((Component)storage).gameObject).name}");
								}
							}
						}
					}
				}
				catch (Exception ex2)
				{
					MelonLogger.Msg("[Organized Crime] OC-52 staging proof: dead drop dump failed: " + ex2.Message);
				}
			}
			if (Input.GetKeyDown((KeyCode)292) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult3 = Release1RoomWithNoNameHoldRoomHarness.TryDump(_release1SmallCourtesyWorld);
				MelonLogger.Msg($"[Organized Crime] OC-57 hold room proof: dump status {release1StagingHarnessResult3.Status}");
				foreach (string line3 in release1StagingHarnessResult3.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-57 hold room proof: " + line3);
				}
			}
			if (Input.GetKeyDown((KeyCode)287) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult4 = Release1ShortNoticeQuantityHarness.TryDecrementByTwo(_release1SmallCourtesyWorld);
				MelonLogger.Msg($"[Organized Crime] OC-58 quantity proof: status {release1StagingHarnessResult4.Status}");
				foreach (string line4 in release1StagingHarnessResult4.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-58 quantity proof: " + line4);
				}
			}
			if (Input.GetKeyDown((KeyCode)282) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult5 = (_theEnvelopeCashGateDumpNext ? Release1TheEnvelopeCashGateHarness.TryDumpCashSlots(_release1SmallCourtesyWorld) : Release1TheEnvelopeCashGateHarness.TryDecrementFirstCashSlot(_release1SmallCourtesyWorld));
				string value5 = (_theEnvelopeCashGateDumpNext ? "dump" : "decrement");
				MelonLogger.Msg($"[Organized Crime] OC-60 cash gate proof ({value5}): status {release1StagingHarnessResult5.Status}");
				foreach (string line5 in release1StagingHarnessResult5.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-60 cash gate proof: " + line5);
				}
				_theEnvelopeCashGateDumpNext = !_theEnvelopeCashGateDumpNext;
			}
			if (Input.GetKeyDown((KeyCode)283) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult6 = (_theEnvelopeClosetCashGateDumpNext ? Release1TheEnvelopeClosetCashGateHarness.TryDumpClosetCashSlots(_release1SmallCourtesyWorld) : Release1TheEnvelopeClosetCashGateHarness.TryDecrementFirstClosetCashSlot(_release1SmallCourtesyWorld));
				string value6 = (_theEnvelopeClosetCashGateDumpNext ? "dump" : "decrement");
				MelonLogger.Msg($"[Organized Crime] OC-61 closet cash gate proof ({value6}): status {release1StagingHarnessResult6.Status}");
				foreach (string line6 in release1StagingHarnessResult6.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-61 closet cash gate proof: " + line6);
				}
				_theEnvelopeClosetCashGateDumpNext = !_theEnvelopeClosetCashGateDumpNext;
			}
			if (Input.GetKeyDown((KeyCode)278) && _release1SmallCourtesyWorld != null)
			{
				Release1StagingHarnessResult release1StagingHarnessResult7 = (_keepTheLightsOffProductionGateDumpNext ? Release1KeepTheLightsOffProductionGateHarness.TryDumpProductionActivity(_release1SmallCourtesyWorld) : Release1KeepTheLightsOffProductionGateHarness.TryCrossCheckUnpaidEmployees(_release1SmallCourtesyWorld));
				string value7 = (_keepTheLightsOffProductionGateDumpNext ? "dump" : "cross check");
				MelonLogger.Msg($"[Organized Crime] OC-65 production gate proof ({value7}): status {release1StagingHarnessResult7.Status}");
				foreach (string line7 in release1StagingHarnessResult7.Lines)
				{
					MelonLogger.Msg("[Organized Crime] OC-65 production gate proof: " + line7);
				}
				_keepTheLightsOffProductionGateDumpNext = !_keepTheLightsOffProductionGateDumpNext;
			}
			if (Input.GetKeyDown((KeyCode)279) && _release1SmallCourtesyWorld != null)
			{
				string reason;
				Release1SmallCourtesyWorldMutationStatus value8 = (Release1LockdownGatePatch.LockdownActive ? _release1SmallCourtesyWorld.TryReleaseLockdown(out reason) : _release1SmallCourtesyWorld.TryEngageLockdown(out reason));
				MelonLogger.Msg($"[Organized Crime] OC-73 lockdown gate: status {value8}");
				if (!string.IsNullOrEmpty(reason))
				{
					MelonLogger.Msg("[Organized Crime] OC-73 lockdown gate: " + reason);
				}
			}
			if (!Input.GetKeyDown((KeyCode)277))
			{
				return;
			}
			Release1StagingHarnessResult release1StagingHarnessResult8 = Release1NpcRegistryDumpHarness.TryDump();
			MelonLogger.Msg($"[Organized Crime] OC-56 npc registry: status {release1StagingHarnessResult8.Status}");
			foreach (string line8 in release1StagingHarnessResult8.Lines)
			{
				MelonLogger.Msg("[Organized Crime] OC-56 npc registry: " + line8);
			}
		}

		public override void OnGUI()
		{
			_syndicateHqComposition?.OnGUI();
			_release1ProductionComposition?.OnGUI();
		}

		private void HandleSaveComplete()
		{
			_timing.Measure("save-complete", delegate
			{
				FishWarehousePersistenceReplayService.RunIfAuthoritativeHost(IsAuthoritativeHost(), delegate
				{
					_timing.Measure("save-complete/story", delegate
					{
						Release1StoryLifecycleLogging.LogIfRejected("OnSaveComplete", _release1StoryRuntime?.OnSaveComplete());
					});
					_timing.Measure("save-complete/production", delegate
					{
						_release1ProductionComposition?.OnSaveComplete();
					});
					_timing.Measure("save-complete/chief", delegate
					{
						_release1ChiefComposition?.OnSaveComplete();
					});
					_timing.Measure("save-complete/hq", delegate
					{
						_syndicateHqComposition?.OnSaveComplete();
					});
					_timing.Measure("save-complete/fish-warehouse", delegate
					{
						_fishWarehousePersistenceService?.HandleSaveComplete();
					});
				});
			});
		}

		private void HandleSaveStart()
		{
			_timing.Measure("save-start", delegate
			{
				_timing.Measure("save-start/story", delegate
				{
					Release1StoryLifecycleLogging.LogIfRejected("OnSaveStart", _release1StoryRuntime?.OnSaveStart());
				});
				_timing.Measure("save-start/production", delegate
				{
					_release1ProductionComposition?.OnSaveStart();
				});
				_timing.Measure("save-start/chief", delegate
				{
					_release1ChiefComposition?.OnSaveStart();
				});
				_timing.Measure("save-start/hq", delegate
				{
					_syndicateHqComposition?.OnSaveStart();
				});
			});
		}

		private void HandlePreLoad()
		{
			_timing.Measure("pre-load", delegate
			{
				SyndicateHqStorageLoadPatch.BeginLoadCycle();
				_timing.Measure("pre-load/hq", delegate
				{
					_syndicateHqComposition?.OnPreLoad();
				});
				_timing.Measure("pre-load/production", delegate
				{
					_release1ProductionComposition?.OnPreLoad();
				});
				_timing.Measure("pre-load/chief", delegate
				{
					_release1ChiefComposition?.OnPreLoad();
				});
				_timing.Measure("pre-load/story", delegate
				{
					Release1StoryLifecycleLogging.LogIfRejected("OnPreLoad", _release1StoryRuntime?.OnPreLoad());
				});
				FishWarehousePersistenceReplayService.RunIfAuthoritativeHost(IsAuthoritativeHost(), delegate
				{
					_timing.Measure("pre-load/fish-warehouse", delegate
					{
						_fishWarehousePersistenceReplayService?.PrepareForLoad();
					});
				});
			});
		}

		private void HandleLoadComplete()
		{
			_timing.Measure("load-complete", delegate
			{
				bool hqLoadPrepared = true;
				_timing.Measure("load-complete/hq-prepare", delegate
				{
					hqLoadPrepared = _syndicateHqComposition?.PrepareLoadComplete() ?? true;
				});
				_timing.Measure("load-complete/story", delegate
				{
					Release1StoryLifecycleLogging.LogIfRejected("OnLoadComplete", _release1StoryRuntime?.OnLoadComplete());
				});
				_timing.Measure("load-complete/production", delegate
				{
					_release1ProductionComposition?.OnLoadComplete();
				});
				_timing.Measure("load-complete/chief", delegate
				{
					_release1ChiefComposition?.OnLoadComplete();
				});
				_timing.Measure("load-complete/hq-storage", delegate
				{
					SyndicateHqStorageLoadPatch.CompleteAfterVanillaLoad();
				});
				if (hqLoadPrepared)
				{
					_timing.Measure("load-complete/hq", delegate
					{
						_syndicateHqComposition?.OnLoadComplete();
					});
				}
				FishWarehousePersistenceReplayService.RunIfAuthoritativeHost(IsAuthoritativeHost(), delegate
				{
					_timing.Measure("load-complete/fish-warehouse", delegate
					{
						_fishWarehousePersistenceReplayService?.HandleLoadComplete();
					});
				});
			});
			if (!_ownerQaKeysEnabled || _release1SmallCourtesyWorld == null)
			{
				return;
			}
			try
			{
				foreach (string line in Release1WrongAddressStagingHarness.TryDump(_release1SmallCourtesyWorld).Lines)
				{
					if (line.StartsWith("dead drops read: ", StringComparison.Ordinal) || line.Contains(" quantity ", StringComparison.Ordinal))
					{
						MelonLogger.Msg("[Organized Crime] OC-52 staging proof at load: " + line);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Organized Crime] OC-52 staging proof at load failed: " + ex.Message);
			}
		}

		private void HandlePreSceneChange()
		{
			_timing.Measure("pre-scene-change", delegate
			{
				_timing.Measure("pre-scene-change/production", delegate
				{
					_release1ProductionComposition?.OnPreSceneChange();
				});
				_timing.Measure("pre-scene-change/hq", delegate
				{
					_syndicateHqComposition?.OnPreSceneChange();
				});
			});
		}

		private static string? GetActiveSaveFolder()
		{
			try
			{
				LoadManager instance = Singleton<LoadManager>.Instance;
				return (instance != null) ? instance.LoadedGameFolderPath : null;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Organized Crime] Could not resolve the active save folder: " + ex.Message);
				return null;
			}
		}

		private static ILocalPressureStateRepository? CreateLocalPressureRepository(string? activeSaveFolder)
		{
			if (!LocalPressureSavePath.TryCreate(activeSaveFolder, out LocalPressureSavePath path, out LocalPressureSavePathResult _))
			{
				return null;
			}
			return new LocalPressureStateStoreRepository(new LocalPressureStateStore(path));
		}

		private static IRelease1StoryRepository CreateRelease1StoryRepository(string activeSaveFolder)
		{
			if (!Release1StorySavePath.TryCreate(activeSaveFolder, out Release1StorySavePath path, out Release1StorySavePathResult result))
			{
				throw new InvalidOperationException(result.Message);
			}
			return new Release1StoryStateStoreRepository(new Release1StoryStateStore(path));
		}

		private void ApplyLoadedSaveState(FishWarehouseSaveState state)
		{
			_fishWarehouseRuntimeService?.ApplyLoadedSaveState(state);
		}

		private static bool IsAuthoritativeHost()
		{
			try
			{
				ServerManager serverManager = InstanceFinder.ServerManager;
				return serverManager != null && serverManager.OneServerStarted();
			}
			catch
			{
				return false;
			}
		}
	}
}
namespace OrganizedCrime.Runtime
{
	public sealed class FishWarehouseBuildSurfaceHost
	{
		private const float GridPlaneOffset = 0.02f;

		private const BindingFlags MemberFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private GameObject? _gridProxy;

		private Grid? _grid;

		private BuildableItem? _employeeHome;

		private EmployeeHome? _employeeHomeComponent;

		public bool IsReady
		{
			get
			{
				if (_gridProxy != null)
				{
					return _grid != null;
				}
				return false;
			}
		}

		public string GridGuid { get; private set; } = string.Empty;

		public int TileCount { get; private set; }

		public EmployeeHome? CurrentEmployeeHome => _employeeHomeComponent;

		public bool TryAdoptRestoredEmployeeHome(Property parentProperty, BuildableItem buildable, EmployeeHome employeeHome, Action<string>? log = null)
		{
			if (_employeeHome != null)
			{
				if ((Object)(object)_employeeHome == (Object)(object)buildable)
				{
					return (Object)(object)_employeeHomeComponent == (Object)(object)employeeHome;
				}
				return false;
			}
			if (!IsReady || parentProperty == null || buildable == null || employeeHome == null)
			{
				log?.Invoke("Fish Warehouse restored employee-home adoption rejected because the native Grid, Property, BuildableItem, or EmployeeHome was unavailable.");
				return false;
			}
			try
			{
				if ((Object)(object)buildable.ParentProperty != (Object)(object)parentProperty || (Object)(object)((Component)employeeHome).GetComponent<BuildableItem>() != (Object)(object)buildable)
				{
					log?.Invoke("Fish Warehouse restored employee-home adoption rejected because the locker did not belong to the runtime Property.");
					return false;
				}
				_employeeHome = buildable;
				_employeeHomeComponent = employeeHome;
				return true;
			}
			catch (Exception ex)
			{
				log?.Invoke("Fish Warehouse restored employee-home adoption failed safely: " + ex.Message);
				return false;
			}
		}

		public bool TryPlaceEmployeeHome(Property parentProperty, FishWarehouseEmployeeHomeDefinition definition, Action<string>? log = null)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			if (_employeeHome != null)
			{
				return true;
			}
			if (!IsReady || parentProperty == null || (object)definition == null)
			{
				log?.Invoke("Fish Warehouse employee-home placement rejected because the native Grid or Property was unavailable.");
				return false;
			}
			BuildableItem val = null;
			try
			{
				if (!Guid.TryParse(definition.PlacementGuid, out var result) || result == Guid.Empty)
				{
					throw new InvalidOperationException("Employee-home placement GUID was invalid: " + definition.PlacementGuid);
				}
				GameObject obj = BuildManager.CreateGridItem((ItemManager.GetDefinition(definition.ItemId) ?? throw new InvalidOperationException("Vanilla buildable item was not found: " + definition.ItemId)).CreateInstance(1), _grid, new Vector2((float)definition.GridX, (float)definition.GridY), definition.Rotation, result.ToString());
				BuildableItem val2 = ((obj != null) ? obj.GetComponent<BuildableItem>() : null);
				val = val2;
				EmployeeHome val3 = ((obj != null) ? obj.GetComponent<EmployeeHome>() : null);
				if (val2 == null || val3 == null)
				{
					throw new InvalidOperationException("Vanilla locker did not produce both BuildableItem and EmployeeHome components.");
				}
				if ((Object)(object)val2.ParentProperty != (Object)(object)parentProperty)
				{
					Property parentProperty2 = val2.ParentProperty;
					throw new InvalidOperationException("Vanilla locker ParentProperty was not Fish Warehouse (actual=" + (((parentProperty2 != null) ? parentProperty2.PropertyCode : null) ?? "null") + ").");
				}
				if (!Guid.TryParse(((object)val2.GUID/*cast due to .constrained prefix*/).ToString(), out var result2) || result2 == Guid.Empty)
				{
					throw new InvalidOperationException($"Vanilla locker returned an invalid placement GUID: {val2.GUID}");
				}
				_employeeHome = val2;
				_employeeHomeComponent = val3;
				log?.Invoke($"Fish Warehouse employee locker placed (itemId={definition.ItemId}, guid={result2}, grid=({definition.GridX},{definition.GridY}), ParentProperty={parentProperty.PropertyCode}).");
				return true;
			}
			catch (Exception ex)
			{
				try
				{
					if (val != null)
					{
						val.Destroy_Server();
					}
				}
				catch
				{
				}
				log?.Invoke("Fish Warehouse employee locker placement failed safely: " + ex.Message);
				return false;
			}
		}

		public bool TryAttach(Property parentProperty, Transform anchor, string gridRootName, string gridGuid, Action<string>? log = null)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			if (IsReady)
			{
				return true;
			}
			if (parentProperty == null || anchor == null || string.IsNullOrWhiteSpace(gridRootName) || string.IsNullOrWhiteSpace(gridGuid))
			{
				return false;
			}
			GameObject val = null;
			GameObject val2 = null;
			Grid val3 = null;
			try
			{
				if (!Guid.TryParse(gridGuid, out var _))
				{
					throw new InvalidOperationException("Fish Warehouse build Grid GUID was invalid: " + gridGuid);
				}
				int tileCount;
				Grid val4 = FindLargestOwnedGrid(out tileCount);
				if (val4 == null || ((Component)val4).gameObject == null)
				{
					throw new InvalidOperationException("No owned native Grid template was available.");
				}
				if (GridAlreadyUsesGuid(gridGuid))
				{
					throw new InvalidOperationException("Fish Warehouse build Grid GUID was already present: " + gridGuid);
				}
				val = new GameObject(gridRootName + "_Staging");
				val.transform.SetParent(((Component)parentProperty).transform, false);
				val.SetActive(false);
				val2 = Object.Instantiate<GameObject>(((Component)val4).gameObject, val.transform, false);
				((Object)val2).name = gridRootName;
				val2.SetActive(false);
				Grid component = val2.GetComponent<Grid>();
				if (component == null)
				{
					throw new InvalidOperationException("Owned Grid template clone did not retain its Grid component.");
				}
				val3 = component;
				if (!TrySetMember(component, "_guid", gridGuid) || !TrySetMember(component, "_parentProperty", parentProperty))
				{
					throw new InvalidOperationException("Could not prepare the Grid GUID and ParentProperty before Awake.");
				}
				Il2CppArrayBase<Tile> componentsInChildren = val2.GetComponentsInChildren<Tile>(true);
				if (componentsInChildren.Length == 0)
				{
					throw new InvalidOperationException("Owned Grid template clone contained no Tile components.");
				}
				PrepareTiles(component, Il2CppArrayBase<Tile>.op_Implicit(componentsInChildren));
				PositionGrid(val2.transform, ((Component)parentProperty).transform, Il2CppArrayBase<Tile>.op_Implicit(componentsInChildren));
				int rejectedTileCount;
				Tile[] array = BuildMeasuredTileSet(val2.transform, ((Component)parentProperty).transform, component, Il2CppArrayBase<Tile>.op_Implicit(componentsInChildren), Grid.TileSize, out rejectedTileCount);
				if (array.Length == 0)
				{
					throw new InvalidOperationException("The measured Fish Warehouse footprint retained no native Grid cells.");
				}
				FishWarehouseEmployeeHomeDefinition employeeHomeDefinition = FishWarehouseEmployeeHomeDefinition.Default;
				if (!array.Any((Tile tile) => tile.x == employeeHomeDefinition.GridX && tile.y == employeeHomeDefinition.GridY))
				{
					throw new InvalidOperationException($"The measured Fish Warehouse footprint excluded the restored employee-home cell ({employeeHomeDefinition.GridX},{employeeHomeDefinition.GridY}).");
				}
				DisableNonTileColliders(val2);
				AddBuildHoverCollider(val2.transform, array, Grid.TileSize);
				val2.SetActive(true);
				RebuildNativeTopology(component, array);
				Tile val5 = ((IEnumerable<Tile>)array).FirstOrDefault((Func<Tile, bool>)((Tile tile) => tile != null && tile.x == 0 && tile.y == 0));
				if (val5 == null || ((Component)val5).transform == null)
				{
					throw new InvalidOperationException("The rebuilt Fish Warehouse Grid lost its existing (0,0) reference cell.");
				}
				FishWarehouseNativeGridPlacementPatches.Register(component, ((Component)component).transform.InverseTransformPoint(((Component)val5).transform.position), Grid.TileSize);
				RegisterPropertyGrid(parentProperty, component);
				string text = ((object)component.GUID/*cast due to .constrained prefix*/).ToString();
				if (!text.Equals(gridGuid, StringComparison.OrdinalIgnoreCase) || (Object)(object)component.ParentProperty != (Object)(object)parentProperty)
				{
					throw new InvalidOperationException($"Grid identity validation failed (actualGuid={text}, expectedGuid={gridGuid}, parent={((component.ParentProperty == null) ? "null" : component.ParentProperty.PropertyCode)}).");
				}
				_gridProxy = val2;
				_grid = component;
				GridGuid = text;
				TileCount = array.Length;
				val2 = null;
				Object.DestroyImmediate((Object)(object)val);
				val = null;
				Physics.SyncTransforms();
				log?.Invoke($"Fish Warehouse native build Grid enabled (guid={GridGuid}, tiles={TileCount}, sourceTiles={tileCount}, rejectedTiles={rejectedTileCount}, ParentProperty={parentProperty.PropertyCode}).");
				return true;
			}
			catch (Exception ex)
			{
				log?.Invoke("Fish Warehouse native build Grid attachment failed safely: " + ex.Message);
				if (val3 != null)
				{
					try
					{
						FishWarehouseNativeGridPlacementPatches.Unregister(val3);
						parentProperty.Grids?.Remove(val3);
					}
					catch
					{
					}
				}
				if (val2 != null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
				if (val != null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				return false;
			}
		}

		public void Dispose()
		{
			if (_employeeHome != null)
			{
				try
				{
					_employeeHome.Destroy_Server();
				}
				catch
				{
				}
			}
			_employeeHome = null;
			_employeeHomeComponent = null;
			if (_gridProxy != null)
			{
				try
				{
					FishWarehouseNativeGridPlacementPatches.Unregister(_grid);
					if (_grid != null && _grid.ParentProperty != null && _grid.ParentProperty.Grids != null)
					{
						_grid.ParentProperty.Grids.Remove(_grid);
					}
				}
				catch
				{
				}
				try
				{
					Object.DestroyImmediate((Object)(object)_gridProxy);
				}
				catch
				{
				}
			}
			_gridProxy = null;
			_grid = null;
			GridGuid = string.Empty;
			TileCount = 0;
		}

		private static Grid? FindLargestOwnedGrid(out int tileCount)
		{
			tileCount = 0;
			Grid result = null;
			Il2CppArrayBase<Grid> val = Object.FindObjectsOfType<Grid>(true);
			for (int i = 0; i < val.Length; i++)
			{
				Grid val2 = val[i];
				Property val3 = ((val2 != null) ? val2.ParentProperty : null);
				if (val2 != null && ((Component)val2).gameObject != null && val3 != null && val3.IsOwned)
				{
					int length = ((Component)val2).GetComponentsInChildren<Tile>(true).Length;
					if (length > tileCount)
					{
						result = val2;
						tileCount = length;
					}
				}
			}
			return result;
		}

		private static bool GridAlreadyUsesGuid(string gridGuid)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Il2CppArrayBase<Grid> val = Object.FindObjectsOfType<Grid>(true);
			for (int i = 0; i < val.Length; i++)
			{
				if (val[i] != null && ((object)val[i].GUID/*cast due to .constrained prefix*/).ToString().Equals(gridGuid, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static void PrepareTiles(Grid ownerGrid, Tile[] tiles)
		{
			foreach (Tile val in tiles)
			{
				if (val != null && ((Component)val).gameObject != null)
				{
					val.OwnerGrid = ownerGrid;
					ClearMember(val, "BuildableOccupants");
					ClearMember(val, "OccupantTiles");
					Renderer component = ((Component)val).GetComponent<Renderer>();
					if (component != null)
					{
						component.enabled = false;
					}
				}
			}
		}

		private static void PositionGrid(Transform grid, Transform propertyRoot, Tile[] tiles)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(Vector3.zero, Vector3.zero);
			bool flag = false;
			foreach (Tile val2 in tiles)
			{
				if (val2 != null && ((Component)val2).transform != null)
				{
					Vector3 val3 = grid.InverseTransformPoint(((Component)val2).transform.position);
					if (!flag)
					{
						((Bounds)(ref val))..ctor(val3, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val3);
					}
				}
			}
			grid.SetParent(propertyRoot, false);
			grid.localRotation = Quaternion.identity;
			grid.localPosition = new Vector3(0f - ((Bounds)(ref val)).center.x, 0.02f - ((Bounds)(ref val)).center.y, 0f - ((Bounds)(ref val)).center.z);
		}

		private static void DisableNonTileColliders(GameObject root)
		{
			Il2CppArrayBase<Collider> componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Collider val = componentsInChildren[i];
				if (val != null && ((Component)val).GetComponent<Tile>() == null)
				{
					val.enabled = false;
				}
			}
		}

		private static void RebuildNativeTopology(Grid grid, Tile[] tiles)
		{
			grid.Tiles.Clear();
			grid.CoordinateTilePairs.Clear();
			foreach (Tile val in tiles)
			{
				if (val != null)
				{
					val.OwnerGrid = grid;
					grid.RegisterTile(val);
				}
			}
			if (!Invoke(GetMember(grid, "_coordinateToTile"), "Clear") || !Invoke(grid, "ProcessCoordinateDataPairs") || !Invoke(grid, "SetGridSize"))
			{
				throw new InvalidOperationException("Native Grid coordinate topology could not be rebuilt.");
			}
			if (grid.Tiles.Count != tiles.Length)
			{
				throw new InvalidOperationException($"Native Grid tile registration mismatch (actual={grid.Tiles.Count}, expected={tiles.Length}).");
			}
		}

		private static object? GetMember(object target, string name)
		{
			Type type = target.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if ((object)property != null)
			{
				return property.GetValue(target);
			}
			return type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target);
		}

		private static bool TrySetMember(object target, string name, object value)
		{
			try
			{
				Type type = target.GetType();
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)property != null && property.CanWrite)
				{
					property.SetValue(target, value);
					return true;
				}
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if ((object)field == null)
				{
					return false;
				}
				field.SetValue(target, value);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool ClearMember(object target, string name)
		{
			object member = GetMember(target, name);
			if (member != null)
			{
				return Invoke(member, "Clear");
			}
			return false;
		}

		private static bool Invoke(object? target, string name)
		{
			if (target == null)
			{
				return false;
			}
			try
			{
				MethodInfo method = target.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if ((object)method == null)
				{
					return false;
				}
				method.Invoke(target, null);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static void AddBuildHoverCollider(Transform gridRoot, Tile[] tiles, float gridCellSize)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (gridRoot == null)
			{
				throw new ArgumentNullException("gridRoot");
			}
			if (tiles == null || tiles.Length == 0)
			{
				throw new ArgumentException("The measured Grid had no retained cells for its hover collider.", "tiles");
			}
			if (!float.IsFinite(gridCellSize) || gridCellSize <= 0f)
			{
				throw new ArgumentOutOfRangeException("gridCellSize");
			}
			bool flag = false;
			Bounds val = default(Bounds);
			foreach (Tile val2 in tiles)
			{
				if (val2 != null && ((Component)val2).transform != null)
				{
					Vector3 val3 = gridRoot.InverseTransformPoint(((Component)val2).transform.position);
					if (!flag)
					{
						((Bounds)(ref val))..ctor(val3, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val3);
					}
				}
			}
			if (!flag)
			{
				throw new InvalidOperationException("The measured Grid had no valid retained tile transforms.");
			}
			GameObject val4 = new GameObject("OC_FishWarehouse_BuildGridCollider");
			val4.transform.SetParent(gridRoot, false);
			val4.layer = 7;
			val4.transform.localPosition = ((Bounds)(ref val)).center;
			val4.transform.localRotation = Quaternion.identity;
			val4.transform.localScale = Vector3.one;
			BoxCollider obj = val4.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = false;
			obj.center = Vector3.zero;
			obj.size = new Vector3(((Bounds)(ref val)).size.x + gridCellSize, 0.2f, ((Bounds)(ref val)).size.z + gridCellSize);
		}

		private static void RegisterPropertyGrid(Property parentProperty, Grid grid)
		{
			List<Grid> grids = parentProperty.Grids;
			if (grids == null)
			{
				throw new InvalidOperationException("Fish Warehouse Property did not expose its native Grid list.");
			}
			if (!grids.Contains(grid))
			{
				grids.Add(grid);
			}
		}

		private static Tile[] BuildMeasuredTileSet(Transform gridRoot, Transform propertyRoot, Grid ownerGrid, Tile[] tiles, float gridCellSize, out int rejectedTileCount)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			if (gridRoot == null)
			{
				throw new ArgumentNullException("gridRoot");
			}
			if (propertyRoot == null)
			{
				throw new ArgumentNullException("propertyRoot");
			}
			if (ownerGrid == null)
			{
				throw new ArgumentNullException("ownerGrid");
			}
			if (tiles == null || tiles.Length == 0)
			{
				throw new ArgumentException("The source Grid did not contain any Tile components.", "tiles");
			}
			FishWarehouseBuildableFootprintDefinition fishWarehouseBuildableFootprintDefinition = FishWarehouseBuildableFootprintDefinition.CreateMeasured(gridCellSize);
			Tile val = ((IEnumerable<Tile>)tiles).FirstOrDefault((Func<Tile, bool>)((Tile tile) => tile != null && ((Component)tile).transform != null && tile.x == 0 && tile.y == 0));
			if (val == null || ((Component)val).transform == null)
			{
				throw new InvalidOperationException("The source Grid did not contain the existing (0,0) reference cell.");
			}
			Vector3 val2 = propertyRoot.InverseTransformPoint(((Component)val).transform.position);
			IReadOnlyList<FishWarehouseGridCellCoordinate> allowedCellCoordinates = fishWarehouseBuildableFootprintDefinition.GetAllowedCellCoordinates(val.x, val.y, val2.x, val2.z);
			if (allowedCellCoordinates.Count == 0)
			{
				throw new InvalidOperationException("The measured Fish Warehouse footprint produced no native cell coordinates.");
			}
			Dictionary<(int, int), Tile> dictionary = new Dictionary<(int, int), Tile>();
			Vector3 val4 = default(Vector3);
			foreach (Tile val3 in tiles)
			{
				if (val3 != null && ((Component)val3).transform != null && ((Component)val3).gameObject != null)
				{
					if (!dictionary.TryAdd((val3.x, val3.y), val3))
					{
						throw new InvalidOperationException($"The source Grid contained duplicate native cell ({val3.x},{val3.y}).");
					}
					((Vector3)(ref val4))..ctor(val2.x + (float)(val3.x - val.x) * gridCellSize, val2.y, val2.z + (float)(val3.y - val.y) * gridCellSize);
					if (Vector3.Distance(propertyRoot.InverseTransformPoint(((Component)val3).transform.position), val4) > 0.02f)
					{
						throw new InvalidOperationException($"The source Grid coordinate spacing was not representable from the (0,0) cell ({val3.x},{val3.y}).");
					}
				}
			}
			List<Tile> list = new List<Tile>(allowedCellCoordinates.Count);
			HashSet<(int, int)> hashSet = new HashSet<(int, int)>();
			for (int num2 = 0; num2 < allowedCellCoordinates.Count; num2++)
			{
				FishWarehouseGridCellCoordinate coordinate = allowedCellCoordinates[num2];
				if (!hashSet.Add((coordinate.X, coordinate.Y)))
				{
					throw new InvalidOperationException($"The measured footprint produced duplicate native cell ({coordinate.X},{coordinate.Y}).");
				}
				if (dictionary.TryGetValue((coordinate.X, coordinate.Y), out var value))
				{
					list.Add(value);
					continue;
				}
				Tile item = CreateGeneratedTile(val, gridRoot, ownerGrid, coordinate, val2, gridCellSize);
				list.Add(item);
			}
			rejectedTileCount = 0;
			foreach (Tile val5 in tiles)
			{
				if (val5 != null && ((Component)val5).transform != null && ((Component)val5).gameObject != null && !hashSet.Contains((val5.x, val5.y)))
				{
					((Component)val5).gameObject.SetActive(false);
					rejectedTileCount++;
				}
			}
			return list.ToArray();
		}

		private static Tile CreateGeneratedTile(Tile reference, Transform gridRoot, Grid ownerGrid, FishWarehouseGridCellCoordinate coordinate, Vector3 referenceLocal, float gridCellSize)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(((Component)reference).gameObject, gridRoot, false);
			((Object)obj).name = $"Grid [{coordinate.X},{coordinate.Y}]";
			obj.SetActive(false);
			Tile component = obj.GetComponent<Tile>();
			if (component == null || ((Component)component).transform == null)
			{
				throw new InvalidOperationException($"Generated native Grid cell ({coordinate.X},{coordinate.Y}) did not retain its Tile component.");
			}
			Vector3 localPosition = gridRoot.InverseTransformPoint(gridRoot.parent.TransformPoint(referenceLocal));
			localPosition.x += (float)(coordinate.X - reference.x) * gridCellSize;
			localPosition.z += (float)(coordinate.Y - reference.y) * gridCellSize;
			((Component)component).transform.localPosition = localPosition;
			component.InitializePropertyTile(coordinate.X, coordinate.Y, reference.AvailableOffset, ownerGrid);
			component.OwnerGrid = ownerGrid;
			ClearMember(component, "BuildableOccupants");
			ClearMember(component, "OccupantTiles");
			Renderer component2 = ((Component)component).GetComponent<Renderer>();
			if (component2 != null)
			{
				component2.enabled = false;
			}
			obj.SetActive(true);
			return component;
		}
	}
	public enum FishWarehouseContinuousNavigationState
	{
		Inactive,
		Settling,
		Ready,
		Failed
	}
	public interface IFishWarehouseContinuousNavigationActions
	{
		bool TryPreflightGeometry();

		bool TryActivateRoom();

		bool TryOpenGarage();

		string GetBuildableAndConfigurableSignature();

		FishWarehouseNativeNavigationBuildResult TryBuildNavigation();

		bool ValidateNavigation();

		bool RemoveNavigation();

		void RestoreGarage();

		void DisposeRoom();
	}
	public sealed class FishWarehouseContinuousNavigationCoordinator
	{
		public const float StableSettleSeconds = 0.5f;

		public const float SettleTimeoutSeconds = 5f;

		private readonly IFishWarehouseContinuousNavigationActions _actions;

		private string? _lastSignature;

		private float _startedAt;

		private float _signatureStableSince;

		private bool _rollbackRequired;

		private bool _rolledBack;

		private bool _hasPostStartTick;

		public FishWarehouseContinuousNavigationState State { get; private set; }

		public bool HasPendingCleanup
		{
			get
			{
				if (_rollbackRequired)
				{
					return !_rolledBack;
				}
				return false;
			}
		}

		public FishWarehouseContinuousNavigationCoordinator(IFishWarehouseContinuousNavigationActions actions)
		{
			_actions = actions ?? throw new ArgumentNullException("actions");
		}

		public void Start(float now)
		{
			if (State == FishWarehouseContinuousNavigationState.Inactive)
			{
				ResetRun(now);
				if (!_actions.TryPreflightGeometry())
				{
					State = FishWarehouseContinuousNavigationState.Failed;
					return;
				}
				if (!_actions.TryActivateRoom() || !_actions.TryOpenGarage())
				{
					FailAfterMutation();
					return;
				}
				_rollbackRequired = true;
				_lastSignature = _actions.GetBuildableAndConfigurableSignature();
				_signatureStableSince = now;
				State = FishWarehouseContinuousNavigationState.Settling;
			}
		}

		public void Tick(float now)
		{
			if (State != FishWarehouseContinuousNavigationState.Settling)
			{
				return;
			}
			if (!_hasPostStartTick)
			{
				_hasPostStartTick = true;
				if (now - _startedAt > 5f)
				{
					_startedAt = now;
					_signatureStableSince = now;
				}
			}
			if (now - _startedAt >= 5f)
			{
				FailAfterMutation();
				return;
			}
			string buildableAndConfigurableSignature = _actions.GetBuildableAndConfigurableSignature();
			if (!string.Equals(buildableAndConfigurableSignature, _lastSignature, StringComparison.Ordinal))
			{
				_lastSignature = buildableAndConfigurableSignature;
				_signatureStableSince = now;
			}
			else
			{
				if (now - _signatureStableSince < 0.5f)
				{
					return;
				}
				switch (_actions.TryBuildNavigation())
				{
				case FishWarehouseNativeNavigationBuildResult.Pending:
					break;
				case FishWarehouseNativeNavigationBuildResult.Succeeded:
					if (_actions.ValidateNavigation())
					{
						State = FishWarehouseContinuousNavigationState.Ready;
						break;
					}
					goto default;
				default:
					FailAfterMutation();
					break;
				}
			}
		}

		public bool Stop()
		{
			if (!_rollbackRequired)
			{
				return true;
			}
			if (!Rollback())
			{
				return false;
			}
			if (State != FishWarehouseContinuousNavigationState.Failed)
			{
				State = FishWarehouseContinuousNavigationState.Inactive;
			}
			return true;
		}

		private void FailAfterMutation()
		{
			_rollbackRequired = true;
			Rollback();
			State = FishWarehouseContinuousNavigationState.Failed;
		}

		private void ResetRun(float now)
		{
			_lastSignature = null;
			_startedAt = now;
			_signatureStableSince = now;
			_rollbackRequired = false;
			_rolledBack = false;
			_hasPostStartTick = false;
		}

		private bool Rollback()
		{
			if (_rolledBack)
			{
				return true;
			}
			if (!_actions.RemoveNavigation())
			{
				return false;
			}
			_actions.RestoreGarage();
			_actions.DisposeRoom();
			_rolledBack = true;
			return true;
		}
	}
	public enum FishWarehouseDeliveryActionKind
	{
		Dispatch,
		Status,
		StatusDisplay
	}
	public sealed record FishWarehousePendingDelivery<TDelivery>(string DeliveryId, TDelivery Delivery, FishWarehouseDeliveryActionKind ActionKind = FishWarehouseDeliveryActionKind.Dispatch) where TDelivery : class;
	public sealed class FishWarehouseDeliveryRestoreGate<TDelivery> where TDelivery : class
	{
		private readonly record struct DeliveryActionKey(string DeliveryId, FishWarehouseDeliveryActionKind ActionKind);

		private readonly string _targetPropertyCode;

		private readonly Dictionary<DeliveryActionKey, TDelivery> _pending = new Dictionary<DeliveryActionKey, TDelivery>();

		private readonly Dictionary<DeliveryActionKey, long> _sequence = new Dictionary<DeliveryActionKey, long>();

		private readonly HashSet<DeliveryActionKey> _attempted = new HashSet<DeliveryActionKey>();

		private readonly HashSet<DeliveryActionKey> _replayed = new HashSet<DeliveryActionKey>();

		private long _nextSequence;

		public int PendingCount => _pending.Count;

		public FishWarehouseDeliveryRestoreGate(string targetPropertyCode)
		{
			_targetPropertyCode = targetPropertyCode;
		}

		public bool ShouldSuppress(TDelivery delivery, string destinationCode, string deliveryId, FishWarehouseDeliveryActionKind actionKind, bool targetReady, bool isLoading)
		{
			if (!string.Equals(destinationCode, _targetPropertyCode, StringComparison.Ordinal))
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(deliveryId))
			{
				throw new ArgumentException("Fish Warehouse delivery identity is required.", "deliveryId");
			}
			DeliveryActionKey deliveryActionKey = new DeliveryActionKey(deliveryId, actionKind);
			if (actionKind != FishWarehouseDeliveryActionKind.Status && _replayed.Contains(deliveryActionKey))
			{
				return true;
			}
			if (!ShouldDefer(actionKind, targetReady, isLoading))
			{
				return false;
			}
			if (_pending.TryAdd(deliveryActionKey, delivery))
			{
				_sequence[deliveryActionKey] = _nextSequence++;
			}
			return true;
		}

		public bool ShouldSuppress(TDelivery delivery, string destinationCode, string deliveryId, bool targetReady, bool isRestoreContext)
		{
			if (!isRestoreContext)
			{
				return false;
			}
			return ShouldSuppress(delivery, destinationCode, deliveryId, FishWarehouseDeliveryActionKind.Dispatch, targetReady, isLoading: false);
		}

		public IReadOnlyList<FishWarehousePendingDelivery<TDelivery>> BeginReadyReplay(bool targetReady)
		{
			if (!targetReady)
			{
				return Array.Empty<FishWarehousePendingDelivery<TDelivery>>();
			}
			return (from entry in _pending
				where _attempted.Add(entry.Key)
				orderby ActionOrder(entry.Key.ActionKind), _sequence[entry.Key]
				select new FishWarehousePendingDelivery<TDelivery>(entry.Key.DeliveryId, entry.Value, entry.Key.ActionKind)).ToArray();
		}

		public void MarkReplayed(string deliveryId, FishWarehouseDeliveryActionKind actionKind)
		{
			DeliveryActionKey deliveryActionKey = new DeliveryActionKey(deliveryId, actionKind);
			_pending.Remove(deliveryActionKey);
			_sequence.Remove(deliveryActionKey);
			_attempted.Remove(deliveryActionKey);
			_replayed.Add(deliveryActionKey);
		}

		public void MarkReplayed(string deliveryId)
		{
			MarkReplayed(deliveryId, FishWarehouseDeliveryActionKind.Dispatch);
		}

		public bool HasPending(string deliveryId)
		{
			return _pending.Keys.Any((DeliveryActionKey key) => string.Equals(key.DeliveryId, deliveryId, StringComparison.Ordinal));
		}

		public bool HasPending(string deliveryId, FishWarehouseDeliveryActionKind actionKind)
		{
			return _pending.ContainsKey(new DeliveryActionKey(deliveryId, actionKind));
		}

		public bool IsReplayed(string deliveryId, FishWarehouseDeliveryActionKind actionKind)
		{
			return _replayed.Contains(new DeliveryActionKey(deliveryId, actionKind));
		}

		public void Reset()
		{
			_pending.Clear();
			_sequence.Clear();
			_attempted.Clear();
			_replayed.Clear();
			_nextSequence = 0L;
		}

		private static bool ShouldDefer(FishWarehouseDeliveryActionKind actionKind, bool targetReady, bool isLoading)
		{
			return actionKind switch
			{
				FishWarehouseDeliveryActionKind.Dispatch => !targetReady, 
				FishWarehouseDeliveryActionKind.Status => isLoading && !targetReady, 
				FishWarehouseDeliveryActionKind.StatusDisplay => isLoading && !targetReady, 
				_ => throw new ArgumentOutOfRangeException("actionKind", actionKind, null), 
			};
		}

		private static int ActionOrder(FishWarehouseDeliveryActionKind actionKind)
		{
			return actionKind switch
			{
				FishWarehouseDeliveryActionKind.Dispatch => 0, 
				FishWarehouseDeliveryActionKind.Status => 1, 
				FishWarehouseDeliveryActionKind.StatusDisplay => 2, 
				_ => throw new ArgumentOutOfRangeException("actionKind", actionKind, null), 
			};
		}
	}
	public sealed record FishWarehouseDeliveryRestoreFlushResult(int PendingCount, string? Failure)
	{
		public string? FailureReason => Failure;
	}
	internal static class FishWarehouseDeliveryRestorePatch
	{
		private abstract record PendingDeliveryPayload;

		private sealed record PendingDispatch(DeliveryManager Manager, DeliveryInstance Delivery) : PendingDeliveryPayload();

		private sealed record PendingStatus(DeliveryInstance Delivery, EDeliveryStatus Status) : PendingDeliveryPayload()
		{
			[CompilerGenerated]
			public void Deconstruct(out DeliveryInstance Delivery, out EDeliveryStatus Status)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Expected I4, but got Unknown
				Delivery = this.Delivery;
				Status = (EDeliveryStatus)(int)this.Status;
			}
		}

		private sealed record PendingStatusDisplay(DeliveryApp App, DeliveryInstance Delivery) : PendingDeliveryPayload();

		private static readonly FishWarehouseDeliveryRestoreGate<PendingDeliveryPayload> Gate = new FishWarehouseDeliveryRestoreGate<PendingDeliveryPayload>("oc_fishwarehouse");

		private static Func<bool> _isReady = () => false;

		private static Action<string> _log = delegate
		{
		};

		private static bool _replaying;

		private static string? _statusReplayDeliveryId;

		private static bool _nestedStatusDisplayObserved;

		private static bool _replayFailureReported;

		public static FishWarehouseDeliveryRestoreFlushResult LastFlushResult { get; private set; } = new FishWarehouseDeliveryRestoreFlushResult(0, null);

		public static void Apply(Harmony harmony, Func<bool> isReady, Action<string>? log = null)
		{
			_isReady = isReady;
			_log = log ?? ((Action<string>)delegate
			{
			});
			MethodInfo methodInfo = AccessTools.Method(typeof(DeliveryManager), "SendDelivery", new Type[1] { typeof(DeliveryInstance) }, (Type[])null) ?? throw new MissingMethodException(typeof(DeliveryManager).FullName, "SendDelivery");
			MethodInfo methodInfo2 = AccessTools.Method(typeof(DeliveryInstance), "SetStatus", new Type[1] { typeof(EDeliveryStatus) }, (Type[])null) ?? throw new MissingMethodException(typeof(DeliveryInstance).FullName, "SetStatus");
			MethodInfo methodInfo3 = AccessTools.Method(typeof(DeliveryApp), "CreateDeliveryStatusDisplay", new Type[1] { typeof(DeliveryInstance) }, (Type[])null) ?? throw new MissingMethodException(typeof(DeliveryApp).FullName, "CreateDeliveryStatusDisplay");
			harmony.Patch((MethodBase)methodInfo, HarmonyMethod("DispatchPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo2, HarmonyMethod("StatusPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo3, HarmonyMethod("StatusDisplayPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static HarmonyMethod HarmonyMethod(string methodName)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			return new HarmonyMethod(AccessTools.Method(typeof(FishWarehouseDeliveryRestorePatch), methodName, (Type[])null, (Type[])null) ?? throw new MissingMethodException(typeof(FishWarehouseDeliveryRestorePatch).FullName, methodName));
		}

		private static bool DispatchPrefix(DeliveryManager __instance, DeliveryInstance __0)
		{
			if (_replaying || __0 == null)
			{
				return true;
			}
			return ApplyGate(new PendingDispatch(__instance, __0), __0, FishWarehouseDeliveryActionKind.Dispatch, IsLoading());
		}

		private static bool StatusPrefix(DeliveryInstance __instance, EDeliveryStatus __0)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (_replaying || __instance == null)
			{
				return true;
			}
			return ApplyGate(new PendingStatus(__instance, __0), __instance, FishWarehouseDeliveryActionKind.Status, IsLoading());
		}

		private static bool StatusDisplayPrefix(DeliveryApp __instance, DeliveryInstance __0)
		{
			if (__0 == null)
			{
				return true;
			}
			if (_replaying)
			{
				if (string.Equals(_statusReplayDeliveryId, __0.DeliveryID, StringComparison.Ordinal) && Gate.HasPending(__0.DeliveryID ?? string.Empty, FishWarehouseDeliveryActionKind.StatusDisplay))
				{
					_nestedStatusDisplayObserved = true;
				}
				return true;
			}
			return ApplyGate(new PendingStatusDisplay(__instance, __0), __0, FishWarehouseDeliveryActionKind.StatusDisplay, IsLoading());
		}

		private static bool ApplyGate(PendingDeliveryPayload payload, DeliveryInstance delivery, FishWarehouseDeliveryActionKind actionKind, bool isLoading)
		{
			try
			{
				string text = delivery.DeliveryID ?? string.Empty;
				bool num = Gate.ShouldSuppress(payload, delivery.DestinationCode ?? string.Empty, text, actionKind, _isReady(), isLoading);
				if (num)
				{
					_log($"Fish Warehouse delivery action deferred (delivery={text}, action={actionKind}).");
				}
				return !num;
			}
			catch (Exception ex)
			{
				_log("Fish Warehouse saved-delivery gate failed safely; vanilla action will continue: " + ex.Message);
				return true;
			}
		}

		internal static void ReplayUntilFailure<TDelivery>(IEnumerable<FishWarehousePendingDelivery<TDelivery>> pendingActions, Action<FishWarehousePendingDelivery<TDelivery>> replay, Action<FishWarehousePendingDelivery<TDelivery>, Exception> onFailure) where TDelivery : class
		{
			foreach (FishWarehousePendingDelivery<TDelivery> pendingAction in pendingActions)
			{
				try
				{
					replay(pendingAction);
				}
				catch (Exception arg)
				{
					onFailure(pendingAction, arg);
					break;
				}
			}
		}

		public static FishWarehouseDeliveryRestoreFlushResult FlushIfReady()
		{
			IReadOnlyList<FishWarehousePendingDelivery<PendingDeliveryPayload>> ready = Gate.BeginReadyReplay(_isReady());
			string failure = null;
			ReplayUntilFailure(ready.Where((FishWarehousePendingDelivery<PendingDeliveryPayload> pending) => !Gate.IsReplayed(pending.DeliveryId, pending.ActionKind)), delegate(FishWarehousePendingDelivery<PendingDeliveryPayload> pending)
			{
				try
				{
					_replaying = true;
					Replay(pending, ready);
				}
				finally
				{
					_statusReplayDeliveryId = null;
					_nestedStatusDisplayObserved = false;
					_replaying = false;
				}
			}, delegate(FishWarehousePendingDelivery<PendingDeliveryPayload> pending, Exception ex)
			{
				if (failure == null)
				{
					failure = $"delivery={pending.DeliveryId}, action={pending.ActionKind}: {ex.Message}";
				}
				if (!_replayFailureReported)
				{
					_replayFailureReported = true;
					_log("Fish Warehouse saved delivery action remains pending after replay failure (" + failure + ").");
				}
			});
			return StoreFlushResult(new FishWarehouseDeliveryRestoreFlushResult(Gate.PendingCount, failure));
		}

		private static void Replay(FishWarehousePendingDelivery<PendingDeliveryPayload> pending, IReadOnlyList<FishWarehousePendingDelivery<PendingDeliveryPayload>> ready)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			switch (pending.ActionKind)
			{
			case FishWarehouseDeliveryActionKind.Dispatch:
			{
				PendingDispatch pendingDispatch = (PendingDispatch)pending.Delivery;
				pendingDispatch.Manager.SendDelivery(pendingDispatch.Delivery);
				Gate.MarkReplayed(pending.DeliveryId, pending.ActionKind);
				_log("Fish Warehouse delivery action replayed (delivery=" + pending.DeliveryId + ", action=Dispatch).");
				break;
			}
			case FishWarehouseDeliveryActionKind.Status:
			{
				PendingStatus pendingStatus = (PendingStatus)pending.Delivery;
				_statusReplayDeliveryId = pending.DeliveryId;
				_nestedStatusDisplayObserved = false;
				pendingStatus.Delivery.SetStatus(pendingStatus.Status);
				Gate.MarkReplayed(pending.DeliveryId, pending.ActionKind);
				FishWarehousePendingDelivery<PendingDeliveryPayload> fishWarehousePendingDelivery = ready.FirstOrDefault((FishWarehousePendingDelivery<PendingDeliveryPayload> candidate) => candidate.DeliveryId == pending.DeliveryId && candidate.ActionKind == FishWarehouseDeliveryActionKind.StatusDisplay);
				if ((object)fishWarehousePendingDelivery != null && Gate.HasPending(pending.DeliveryId, FishWarehouseDeliveryActionKind.StatusDisplay))
				{
					if (_nestedStatusDisplayObserved)
					{
						Gate.MarkReplayed(pending.DeliveryId, FishWarehouseDeliveryActionKind.StatusDisplay);
						_log("Fish Warehouse delivery action replayed (delivery=" + pending.DeliveryId + ", action=StatusDisplay, mode=nested).");
					}
					else
					{
						ReplayStatusDisplay(fishWarehousePendingDelivery);
					}
				}
				_log("Fish Warehouse delivery action replayed (delivery=" + pending.DeliveryId + ", action=Status).");
				break;
			}
			case FishWarehouseDeliveryActionKind.StatusDisplay:
				ReplayStatusDisplay(pending);
				break;
			default:
				throw new ArgumentOutOfRangeException("ActionKind", pending.ActionKind, null);
			}
		}

		private static void ReplayStatusDisplay(FishWarehousePendingDelivery<PendingDeliveryPayload> pending)
		{
			PendingStatusDisplay pendingStatusDisplay = (PendingStatusDisplay)pending.Delivery;
			pendingStatusDisplay.App.CreateDeliveryStatusDisplay(pendingStatusDisplay.Delivery);
			Gate.MarkReplayed(pending.DeliveryId, pending.ActionKind);
			_log("Fish Warehouse delivery action replayed (delivery=" + pending.DeliveryId + ", action=StatusDisplay, mode=explicit).");
		}

		internal static FishWarehouseDeliveryRestoreFlushResult StoreFlushResult(FishWarehouseDeliveryRestoreFlushResult result)
		{
			if (result.Failure == null && LastFlushResult.Failure != null)
			{
				return LastFlushResult;
			}
			LastFlushResult = result;
			return result;
		}

		public static void Reset()
		{
			Gate.Reset();
			_isReady = () => false;
			_log = delegate
			{
			};
			_replaying = false;
			_statusReplayDeliveryId = null;
			_nestedStatusDisplayObserved = false;
			_replayFailureReported = false;
			LastFlushResult = new FishWarehouseDeliveryRestoreFlushResult(0, null);
		}

		private static bool IsLoading()
		{
			LoadManager instance = Singleton<LoadManager>.Instance;
			if (instance == null)
			{
				return false;
			}
			return instance.IsLoading;
		}
	}
	public sealed class FishWarehouseDockDeliveryBridgeHost
	{
		private readonly FishWarehouseDockDeliveryPopulationLatch _populationLatch = new FishWarehouseDockDeliveryPopulationLatch();

		public void Tick(Property property, bool hostAuthority, Action<string>? log = null)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			if (!hostAuthority || property == null || (Object)(object)property == (Object)null)
			{
				return;
			}
			try
			{
				DeliveryInstance val = ResolveActiveDelivery(property);
				if (val == null)
				{
					_populationLatch.ObserveActiveDelivery(null);
					return;
				}
				string text = SafeDeliveryId(val);
				_populationLatch.ObserveActiveDelivery(text);
				if (string.IsNullOrWhiteSpace(text) || _populationLatch.HasPopulated(text))
				{
					return;
				}
				LoadingDock val2 = SafeDock(val);
				if (val2 == null || HasOccupant(val2))
				{
					return;
				}
				TryRefresh(val2);
				if (HasOccupant(val2))
				{
					_populationLatch.MarkPopulated(text);
					log?.Invoke("[oc7-bridge] dock populated via native RefreshOccupant.");
				}
				else
				{
					if ((int)SafeStatus(val) != 2)
					{
						return;
					}
					LandVehicle val3 = SafeVan(val);
					if (val3 != null && !((Object)(object)val3 == (Object)null))
					{
						val2.SetOccupant(val3);
						if (HasOccupant(val2))
						{
							_populationLatch.MarkPopulated(text);
							log?.Invoke("[oc7-bridge] dock populated via direct SetOccupant (arrived delivery van).");
						}
					}
				}
			}
			catch
			{
			}
		}

		private static DeliveryInstance? ResolveActiveDelivery(Property property)
		{
			try
			{
				if (!NetworkSingleton<DeliveryManager>.InstanceExists)
				{
					return null;
				}
				DeliveryInstance delivery = NetworkSingleton<DeliveryManager>.Instance.GetDelivery(property);
				return (delivery != null && delivery != null) ? delivery : null;
			}
			catch
			{
				return null;
			}
		}

		private static LoadingDock? SafeDock(DeliveryInstance delivery)
		{
			try
			{
				LoadingDock loadingDock = delivery.LoadingDock;
				return (loadingDock != null && (Object)(object)loadingDock != (Object)null) ? loadingDock : null;
			}
			catch
			{
				return null;
			}
		}

		private static string SafeDeliveryId(DeliveryInstance delivery)
		{
			try
			{
				return delivery.DeliveryID ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		private static LandVehicle? SafeVan(DeliveryInstance delivery)
		{
			try
			{
				DeliveryVehicle activeVehicle = delivery.ActiveVehicle;
				if (activeVehicle == null || (Object)(object)activeVehicle == (Object)null)
				{
					return null;
				}
				LandVehicle vehicle = activeVehicle.Vehicle;
				return (vehicle != null && (Object)(object)vehicle != (Object)null) ? vehicle : null;
			}
			catch
			{
				return null;
			}
		}

		private static EDeliveryStatus SafeStatus(DeliveryInstance delivery)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return delivery.Status;
			}
			catch
			{
				return (EDeliveryStatus)0;
			}
		}

		private static bool HasOccupant(LoadingDock dock)
		{
			try
			{
				LandVehicle dynamicOccupant = dock.DynamicOccupant;
				return dynamicOccupant != null && (Object)(object)dynamicOccupant != (Object)null;
			}
			catch
			{
				return true;
			}
		}

		private static void TryRefresh(LoadingDock dock)
		{
			try
			{
				dock.RefreshOccupant();
			}
			catch
			{
			}
		}
	}
	public sealed class FishWarehouseDockDeliveryPopulationLatch
	{
		private string? _populatedDeliveryId;

		public bool HasPopulated(string deliveryId)
		{
			if (!string.IsNullOrWhiteSpace(deliveryId))
			{
				return string.Equals(_populatedDeliveryId, deliveryId, StringComparison.Ordinal);
			}
			return false;
		}

		public void MarkPopulated(string deliveryId)
		{
			if (!string.IsNullOrWhiteSpace(deliveryId))
			{
				_populatedDeliveryId = deliveryId;
			}
		}

		public void ObserveActiveDelivery(string? deliveryId)
		{
			if (!string.Equals(_populatedDeliveryId, deliveryId, StringComparison.Ordinal))
			{
				_populatedDeliveryId = null;
			}
		}

		public void Reset()
		{
			_populatedDeliveryId = null;
		}
	}
	internal static class FishWarehouseDockOccupantRefreshPatch
	{
		public static void Apply(Harmony harmony)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(LoadingDock), "SetOccupant", new Type[1] { typeof(LandVehicle) }, (Type[])null);
			if ((object)methodInfo == null)
			{
				throw new MissingMethodException(typeof(LoadingDock).FullName, "SetOccupant");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(FishWarehouseDockOccupantRefreshPatch), "Prefix", (Type[])null, (Type[])null);
			if ((object)methodInfo2 == null)
			{
				throw new MissingMethodException(typeof(FishWarehouseDockOccupantRefreshPatch).FullName, "Prefix");
			}
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool Prefix(LoadingDock __instance, LandVehicle? __0)
		{
			try
			{
				if (__0 != null && (Object)(object)__0 != (Object)null)
				{
					return true;
				}
				return !FishWarehouseDockOccupantRefreshPolicy.ShouldSuppressOccupantClear(IsFishWarehouseDock(__instance), HasDynamicOccupant(__instance), HasOutputItems(__instance));
			}
			catch
			{
				return true;
			}
		}

		private static bool IsFishWarehouseDock(LoadingDock dock)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			string guid = ((object)dock.GUID/*cast due to .constrained prefix*/).ToString();
			return FishWarehouseLoadingDockDefinition.Docks.Any((FishWarehouseDockDefinition definition) => string.Equals(definition.DockGuid, guid, StringComparison.OrdinalIgnoreCase));
		}

		private static bool HasDynamicOccupant(LoadingDock dock)
		{
			LandVehicle dynamicOccupant = dock.DynamicOccupant;
			if (dynamicOccupant != null)
			{
				return (Object)(object)dynamicOccupant != (Object)null;
			}
			return false;
		}

		private static bool HasOutputItems(LoadingDock dock)
		{
			Enumerator<ItemSlot> enumerator = dock.OutputSlots.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ItemSlot current = enumerator.Current;
				if (current.ItemInstance != null && current.ItemInstance != null && current.Quantity > 0)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class FishWarehouseDockOccupantRefreshPolicy
	{
		public static bool ShouldSuppressOccupantClear(bool isFishWarehouseDock, bool hasDynamicOccupant, bool hasOutputItems)
		{
			return isFishWarehouseDock && hasDynamicOccupant && hasOutputItems;
		}
	}
	public sealed class FishWarehouseEmployeeInfrastructureHost
	{
		private GameObject? _root;

		public bool IsReady => _root != null;

		public bool TryAttach(Property property, Action<string>? log = null)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (IsReady)
			{
				return true;
			}
			if (property == null)
			{
				return false;
			}
			GameObject val = null;
			try
			{
				if (!FishWarehouseEmployeeInfrastructureDefinition.HasValidLayout())
				{
					throw new InvalidOperationException("Fish Warehouse employee point definition failed its bounds/capacity contract.");
				}
				val = new GameObject("OC_FishWarehouse_EmployeeInfrastructure");
				val.transform.SetParent(((Component)property).transform, false);
				Transform val2 = CreatePoint(val.transform, FishWarehouseEmployeeInfrastructureDefinition.NpcSpawnPoint);
				Il2CppReferenceArray<Transform> val3 = new Il2CppReferenceArray<Transform>(10L);
				for (int i = 0; i < FishWarehouseEmployeeInfrastructureDefinition.IdlePoints.Count; i++)
				{
					((Il2CppArrayBase<Transform>)(object)val3)[i] = CreatePoint(val.transform, FishWarehouseEmployeeInfrastructureDefinition.IdlePoints[i]);
				}
				property.EmployeeCapacity = 10;
				property.NPCSpawnPoint = val2;
				property.EmployeeIdlePoints = val3;
				if (property.EmployeeCapacity != 10 || (Object)(object)property.NPCSpawnPoint != (Object)(object)val2 || property.EmployeeIdlePoints == null || ((Il2CppArrayBase<Transform>)(object)property.EmployeeIdlePoints).Length != 10)
				{
					throw new InvalidOperationException("Fish Warehouse Property did not retain employee infrastructure references.");
				}
				_root = val;
				val = null;
				log?.Invoke($"Fish Warehouse employee infrastructure enabled (capacity={property.EmployeeCapacity}, idlePoints={((Il2CppArrayBase<Transform>)(object)property.EmployeeIdlePoints).Length}, npcSpawn={((Object)property.NPCSpawnPoint).name}).");
				return true;
			}
			catch (Exception ex)
			{
				if (val != null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				log?.Invoke("Fish Warehouse employee infrastructure failed safely: " + ex.Message);
				return false;
			}
		}

		public void Dispose()
		{
			if (_root != null)
			{
				Object.DestroyImmediate((Object)(object)_root);
			}
			_root = null;
		}

		private static Transform CreatePoint(Transform parent, FishWarehouseEmployeePointDefinition definition)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = new GameObject(definition.Name).transform;
			transform.SetParent(parent, false);
			transform.localPosition = new Vector3(definition.X, definition.Y, definition.Z);
			transform.localRotation = Quaternion.identity;
			return transform;
		}
	}
	public enum FishWarehouseEmployeeReplayState
	{
		Pending,
		Succeeded,
		Failed
	}
	public sealed record FishWarehouseEmployeeReplayResult(FishWarehouseEmployeeReplayState State, int CapturedEmployeeCount, int SupportedCapturedEmployeeCount, int ReplayedEmployeeCount, IReadOnlyList<FishWarehouseUnsupportedEmployeeRecord> UnsupportedEmployees, bool CanAdvanceEmployeesReplayed, string? PrimaryFailureReason, string? FailureReason, IReadOnlyList<string>? InventoryRestoredEmployeeGuids = null);
	public sealed class FishWarehouseEmployeeReplayHost
	{
		private enum ReplayStage
		{
			NotStarted,
			PrimaryVerification,
			FallbackVerification
		}

		private sealed class Entry
		{
			public FishWarehouseEmployeeReplayDescriptor Descriptor { get; }

			public FishWarehouseEmployeeReplayExpectedState? Expected { get; set; }

			public ReplayStage Stage { get; set; }

			public bool GuidWasRegistered { get; set; }

			public bool FallbackAttempted { get; set; }

			public bool IsReplayed { get; set; }

			public bool IsUnsupported { get; set; }

			public float PrimaryStartedAt { get; set; }

			public float FallbackStartedAt { get; set; }

			public string? PrimaryFailureReason { get; set; }

			public string? LastVerificationReason { get; set; }

			public Entry(FishWarehouseEmployeeReplayDescriptor descriptor)
			{
				Descriptor = descriptor;
			}
		}

		public const float ConfigurationVerificationTimeoutSeconds = 3f;

		private readonly IFishWarehouseNativeEmployeeReplayAdapter _adapter;

		private readonly IReadOnlyList<Entry> _entries;

		private readonly Dictionary<string, FishWarehouseUnsupportedEmployeeRecord> _unsupportedByGuid;

		private readonly Func<float> _realtimeSinceStartup;

		private readonly Action<string> _log;

		public FishWarehouseEmployeeReplayResult Result { get; private set; }

		public FishWarehouseEmployeeReplayHost(IFishWarehouseNativeEmployeeReplayAdapter adapter, IReadOnlyList<FishWarehouseEmployeeReplayDescriptor> capturedEmployees, IReadOnlyList<FishWarehouseUnsupportedEmployeeRecord> existingUnsupportedEmployees, Func<float>? realtimeSinceStartup = null, Action<string>? log = null)
		{
			_adapter = adapter ?? throw new ArgumentNullException("adapter");
			_entries = (capturedEmployees ?? throw new ArgumentNullException("capturedEmployees")).Select((FishWarehouseEmployeeReplayDescriptor descriptor) => new Entry(descriptor)).ToArray();
			_unsupportedByGuid = new Dictionary<string, FishWarehouseUns