Decompiled source of HireableDeliveryDriver v1.0.0

Mods/HireableDeliveryDriver.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using FishNet;
using FishNet.Connection;
using HireableDeliveryDriver;
using MelonLoader;
using Microsoft.CodeAnalysis;
using ScheduleOne.Delivery;
using ScheduleOne.DevUtilities;
using ScheduleOne.GameTime;
using ScheduleOne.ItemFramework;
using ScheduleOne.Map;
using ScheduleOne.Money;
using ScheduleOne.Property;
using ScheduleOne.Storage;
using ScheduleOne.UI.Shop;
using ScheduleOne.Vehicles;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(DeliveryDriverMod), "Hireable Delivery Driver", "1.0.0", "You", null)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HireableDeliveryDriver")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5b8bfea65b08fe9810ef21cd116fad8f5be354cf")]
[assembly: AssemblyProduct("HireableDeliveryDriver")]
[assembly: AssemblyTitle("HireableDeliveryDriver")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HireableDeliveryDriver
{
	public sealed class DeliveryDriverMod : MelonMod
	{
		private const KeyCode OPEN_UI_KEY = 290;

		private const float CHECK_INTERVAL_SECONDS = 2f;

		public const float SIGNING_FEE = 500f;

		public const float DAILY_WAGE = 100f;

		private const int DEFAULT_FILL_THRESHOLD = 80;

		private const int TRAVEL_TIME_MINUTES = 5;

		private const int EMPTY_DELAY_MINUTES = 2;

		private DeliveryDriverManager _driverManager;

		private float _nextCheckTime;

		private bool _uiOpen;

		private Rect _windowRect = new Rect(100f, 100f, 600f, 500f);

		private Vector2 _scrollPosition;

		private CursorLockMode _previousCursorLockState;

		private bool _previousCursorVisible;

		private int _selectedSourcePropertyIndex;

		private int _selectedSourceDockIndex;

		private int _selectedDestPropertyIndex;

		private int _selectedDestDockIndex;

		private int _fillThreshold = 80;

		private List<Property> _cachedProperties;

		private string _deliveryVehicleCode;

		private bool _vehicleCodeSearched;

		public override void OnInitializeMelon()
		{
			_driverManager = new DeliveryDriverManager();
			_nextCheckTime = 0f;
			MelonLogger.Msg("[DeliveryDriver] Loaded. Press F9 to open delivery route management.");
		}

		public override void OnUpdate()
		{
			if (Input.GetKeyDown((KeyCode)290))
			{
				ToggleUI();
			}
			if (Time.unscaledTime >= _nextCheckTime)
			{
				_nextCheckTime = Time.unscaledTime + 2f;
				ProcessDeliveryRoutes();
			}
		}

		private void ToggleUI()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			_uiOpen = !_uiOpen;
			if (_uiOpen)
			{
				_previousCursorLockState = Cursor.lockState;
				_previousCursorVisible = Cursor.visible;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				RefreshPropertyCache();
			}
			else
			{
				Cursor.lockState = _previousCursorLockState;
				Cursor.visible = _previousCursorVisible;
			}
		}

		public override void OnGUI()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (_uiOpen)
			{
				GUI.skin.window.fontSize = 14;
				GUI.skin.label.fontSize = 13;
				GUI.skin.button.fontSize = 13;
				_windowRect = GUI.Window(98765, _windowRect, new WindowFunction(DrawWindow), "Delivery Driver Management (F9 to close)");
			}
		}

		private void DrawWindow(int windowId)
		{
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Active Drivers: {_driverManager.Drivers.Count}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.Label($"Daily Cost: ${_driverManager.GetTotalDailyWage():F0}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			float num = 0f;
			if (NetworkSingleton<MoneyManager>.InstanceExists)
			{
				num = NetworkSingleton<MoneyManager>.Instance.cashBalance;
			}
			GUILayout.Label($"Your Cash: ${num:F0}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			GUILayout.Label("--- Hire New Driver ---", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Signing Fee: ${500f:F0}  |  Daily Wage: ${100f:F0}", Array.Empty<GUILayoutOption>());
			bool enabled = num >= 500f;
			GUI.enabled = enabled;
			if (GUILayout.Button("Hire Driver", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }) && NetworkSingleton<MoneyManager>.InstanceExists)
			{
				NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(-500f, true, false);
				_driverManager.HireDriver();
				MelonLogger.Msg("[DeliveryDriver] Hired new driver!");
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.Space(15f);
			DrawNewRouteSection();
			GUILayout.Space(15f);
			GUILayout.Label("--- Active Delivery Routes ---", Array.Empty<GUILayoutOption>());
			_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) });
			if (_driverManager.Routes.Count == 0)
			{
				GUILayout.Label("No active routes. Create one above.", Array.Empty<GUILayoutOption>());
			}
			else
			{
				for (int i = 0; i < _driverManager.Routes.Count; i++)
				{
					DrawRouteEntry(_driverManager.Routes[i], i);
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(10f);
			GUILayout.Label($"--- Idle Drivers ({_driverManager.GetIdleDriverCount()}) ---", Array.Empty<GUILayoutOption>());
			foreach (DeliveryDriver item in _driverManager.Drivers.Where((DeliveryDriver d) => d.AssignedRoute == null))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("  " + item.Name + " - Idle", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
				if (GUILayout.Button("Fire", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					_driverManager.FireDriver(item);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
		}

		private void DrawNewRouteSection()
		{
			GUILayout.Label("--- Create New Route ---", Array.Empty<GUILayoutOption>());
			if (_cachedProperties == null || _cachedProperties.Count == 0)
			{
				GUILayout.Label("No properties available. Own some properties first!", Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Refresh", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
				{
					RefreshPropertyCache();
				}
				return;
			}
			string[] array = _cachedProperties.Select((Property p) => p.PropertyName).ToArray();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Source Property:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			_selectedSourcePropertyIndex = Mathf.Clamp(_selectedSourcePropertyIndex, 0, array.Length - 1);
			if (GUILayout.Button("< " + array[_selectedSourcePropertyIndex] + " >", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
			{
				_selectedSourcePropertyIndex = (_selectedSourcePropertyIndex + 1) % array.Length;
				_selectedSourceDockIndex = 0;
			}
			Property val = _cachedProperties[_selectedSourcePropertyIndex];
			int loadingDockCount = val.LoadingDockCount;
			GUILayout.Label("Dock:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			if (loadingDockCount > 0)
			{
				_selectedSourceDockIndex = Mathf.Clamp(_selectedSourceDockIndex, 0, loadingDockCount - 1);
				if (GUILayout.Button($"< {_selectedSourceDockIndex + 1} >", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					_selectedSourceDockIndex = (_selectedSourceDockIndex + 1) % loadingDockCount;
				}
			}
			else
			{
				GUILayout.Label("None", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Dest Property:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			_selectedDestPropertyIndex = Mathf.Clamp(_selectedDestPropertyIndex, 0, array.Length - 1);
			if (GUILayout.Button("< " + array[_selectedDestPropertyIndex] + " >", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
			{
				_selectedDestPropertyIndex = (_selectedDestPropertyIndex + 1) % array.Length;
				_selectedDestDockIndex = 0;
			}
			Property val2 = _cachedProperties[_selectedDestPropertyIndex];
			int loadingDockCount2 = val2.LoadingDockCount;
			GUILayout.Label("Dock:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			if (loadingDockCount2 > 0)
			{
				_selectedDestDockIndex = Mathf.Clamp(_selectedDestDockIndex, 0, loadingDockCount2 - 1);
				if (GUILayout.Button($"< {_selectedDestDockIndex + 1} >", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					_selectedDestDockIndex = (_selectedDestDockIndex + 1) % loadingDockCount2;
				}
			}
			else
			{
				GUILayout.Label("None", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Fill Threshold:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			_fillThreshold = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)_fillThreshold, 10f, 100f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) }));
			GUILayout.Label($"{_fillThreshold}%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag2 = (GUI.enabled = loadingDockCount > 0 && loadingDockCount2 > 0 && (_selectedSourcePropertyIndex != _selectedDestPropertyIndex || _selectedSourceDockIndex != _selectedDestDockIndex) && _driverManager.GetIdleDriverCount() > 0);
			if (GUILayout.Button("Create Route & Assign Driver", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }))
			{
				CreateRoute(val, val2);
			}
			GUI.enabled = true;
			if (!flag2)
			{
				if (_driverManager.GetIdleDriverCount() == 0)
				{
					GUILayout.Label("(Need idle driver)", Array.Empty<GUILayoutOption>());
				}
				else if (loadingDockCount == 0 || loadingDockCount2 == 0)
				{
					GUILayout.Label("(Properties need loading docks)", Array.Empty<GUILayoutOption>());
				}
				else
				{
					GUILayout.Label("(Source and dest must differ)", Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.EndHorizontal();
		}

		private void CreateRoute(Property sourceProperty, Property destProperty)
		{
			DeliveryRoute deliveryRoute = new DeliveryRoute
			{
				SourcePropertyCode = sourceProperty.PropertyCode,
				SourceDockIndex = _selectedSourceDockIndex,
				DestinationPropertyCode = destProperty.PropertyCode,
				DestinationDockIndex = _selectedDestDockIndex,
				FillThresholdPercent = _fillThreshold
			};
			DeliveryDriver deliveryDriver = _driverManager.Drivers.FirstOrDefault((DeliveryDriver d) => d.AssignedRoute == null);
			if (deliveryDriver != null)
			{
				deliveryRoute.AssignedDriverId = deliveryDriver.Id;
				deliveryDriver.AssignedRoute = deliveryRoute;
				_driverManager.Routes.Add(deliveryRoute);
				SpawnVanAtSource(deliveryRoute);
				MelonLogger.Msg($"[DeliveryDriver] Created route: {sourceProperty.PropertyName} Dock {_selectedSourceDockIndex + 1} -> {destProperty.PropertyName} Dock {_selectedDestDockIndex + 1}");
			}
		}

		private void DrawRouteEntry(DeliveryRoute route, int index)
		{
			PropertyManager instance = Singleton<PropertyManager>.Instance;
			Property val = ((instance != null) ? instance.GetProperty(route.SourcePropertyCode) : null);
			PropertyManager instance2 = Singleton<PropertyManager>.Instance;
			Property val2 = ((instance2 != null) ? instance2.GetProperty(route.DestinationPropertyCode) : null);
			string text = ((val != null) ? val.PropertyName : null) ?? route.SourcePropertyCode;
			string text2 = ((val2 != null) ? val2.PropertyName : null) ?? route.DestinationPropertyCode;
			DeliveryDriver deliveryDriver = _driverManager.Drivers.FirstOrDefault((DeliveryDriver d) => d.Id == route.AssignedDriverId);
			string text3 = deliveryDriver?.Name ?? "Unassigned";
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"{index + 1}. {text} #{route.SourceDockIndex + 1} -> {text2} #{route.DestinationDockIndex + 1}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
			GUILayout.Label("[" + text3 + "]", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			GUILayout.Label($"{route.FillThresholdPercent}%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			GUILayout.Label(route.Status.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			if (GUILayout.Button("X", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) }))
			{
				RemoveRoute(route, deliveryDriver, index);
			}
			GUILayout.EndHorizontal();
		}

		private void RemoveRoute(DeliveryRoute route, DeliveryDriver driver, int index)
		{
			if ((Object)(object)route.ActiveVehicle != (Object)null)
			{
				DeactivateVan(route);
				try
				{
					Object.Destroy((Object)(object)((Component)route.ActiveVehicle).gameObject);
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("[DeliveryDriver] Error destroying vehicle: " + ex.Message);
				}
				route.ActiveVehicle = null;
			}
			if (driver != null)
			{
				driver.AssignedRoute = null;
			}
			_driverManager.Routes.RemoveAt(index);
			MelonLogger.Msg($"[DeliveryDriver] Removed route {index + 1}");
		}

		private void RefreshPropertyCache()
		{
			_cachedProperties = new List<Property>();
			if (Property.OwnedProperties != null)
			{
				foreach (Property ownedProperty in Property.OwnedProperties)
				{
					if ((Object)(object)ownedProperty != (Object)null && ownedProperty.LoadingDockCount > 0)
					{
						_cachedProperties.Add(ownedProperty);
					}
				}
			}
			MelonLogger.Msg($"[DeliveryDriver] Found {_cachedProperties.Count} properties with loading docks");
		}

		private string GetDeliveryVehicleCode()
		{
			if (!string.IsNullOrEmpty(_deliveryVehicleCode))
			{
				return _deliveryVehicleCode;
			}
			if (_vehicleCodeSearched)
			{
				return null;
			}
			_vehicleCodeSearched = true;
			if (ShopInterface.AllShops != null)
			{
				foreach (ShopInterface allShop in ShopInterface.AllShops)
				{
					object obj;
					if (allShop == null)
					{
						obj = null;
					}
					else
					{
						DeliveryVehicle deliveryVehicle = allShop.DeliveryVehicle;
						obj = ((deliveryVehicle != null) ? deliveryVehicle.Vehicle : null);
					}
					if ((Object)obj != (Object)null)
					{
						_deliveryVehicleCode = allShop.DeliveryVehicle.Vehicle.VehicleCode;
						MelonLogger.Msg("[DeliveryDriver] Found delivery vehicle code from " + allShop.ShopName + ": " + _deliveryVehicleCode);
						return _deliveryVehicleCode;
					}
				}
			}
			if (NetworkSingleton<VehicleManager>.InstanceExists)
			{
				VehicleManager instance = NetworkSingleton<VehicleManager>.Instance;
				foreach (LandVehicle vehiclePrefab in instance.VehiclePrefabs)
				{
					if ((Object)(object)vehiclePrefab != (Object)null)
					{
						string text = vehiclePrefab.VehicleCode.ToLower();
						if (text.Contains("van") || text.Contains("cargo") || text.Contains("delivery"))
						{
							_deliveryVehicleCode = vehiclePrefab.VehicleCode;
							MelonLogger.Msg("[DeliveryDriver] Found van vehicle code from prefabs: " + _deliveryVehicleCode);
							return _deliveryVehicleCode;
						}
					}
				}
				if (instance.VehiclePrefabs.Count > 0 && (Object)(object)instance.VehiclePrefabs[0] != (Object)null)
				{
					_deliveryVehicleCode = instance.VehiclePrefabs[0].VehicleCode;
					MelonLogger.Warning("[DeliveryDriver] Using fallback vehicle code: " + _deliveryVehicleCode);
					return _deliveryVehicleCode;
				}
			}
			MelonLogger.Error("[DeliveryDriver] Could not find any vehicle code!");
			return null;
		}

		private void SpawnVanAtSource(DeliveryRoute route)
		{
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Expected O, but got Unknown
			MelonLogger.Msg("[DeliveryDriver] Attempting to spawn van for route...");
			string deliveryVehicleCode = GetDeliveryVehicleCode();
			if (string.IsNullOrEmpty(deliveryVehicleCode))
			{
				MelonLogger.Error("[DeliveryDriver] Cannot spawn van - no vehicle code available!");
				route.Status = RouteStatus.Error;
				return;
			}
			PropertyManager instance = Singleton<PropertyManager>.Instance;
			Property val = ((instance != null) ? instance.GetProperty(route.SourcePropertyCode) : null);
			if ((Object)(object)val == (Object)null)
			{
				MelonLogger.Error("[DeliveryDriver] Cannot find source property: " + route.SourcePropertyCode);
				route.Status = RouteStatus.Error;
				return;
			}
			if (route.SourceDockIndex >= val.LoadingDockCount)
			{
				MelonLogger.Error($"[DeliveryDriver] Invalid source dock index: {route.SourceDockIndex}");
				route.Status = RouteStatus.Error;
				return;
			}
			LoadingDock val2 = val.LoadingDocks[route.SourceDockIndex];
			if ((Object)(object)val2 == (Object)null)
			{
				MelonLogger.Error("[DeliveryDriver] Source dock is null!");
				route.Status = RouteStatus.Error;
				return;
			}
			if (val2.IsInUse)
			{
				MelonLogger.Warning($"[DeliveryDriver] Source dock {route.SourceDockIndex + 1} is in use, waiting...");
				route.Status = RouteStatus.WaitingForDock;
				return;
			}
			ParkingLot parking = val2.Parking;
			if ((Object)(object)parking == (Object)null)
			{
				MelonLogger.Error("[DeliveryDriver] Source dock has no parking lot!");
				route.Status = RouteStatus.Error;
				return;
			}
			if (parking.ParkingSpots == null || parking.ParkingSpots.Count == 0)
			{
				MelonLogger.Error("[DeliveryDriver] Parking lot has no spots!");
				route.Status = RouteStatus.Error;
				return;
			}
			ParkingSpot val3 = parking.ParkingSpots[0];
			Vector3 position = ((Component)val3).transform.position;
			Quaternion rotation = ((Component)val3).transform.rotation;
			MelonLogger.Msg($"[DeliveryDriver] Spawn position: {position}, Rotation: {((Quaternion)(ref rotation)).eulerAngles}");
			if (!NetworkSingleton<VehicleManager>.InstanceExists)
			{
				MelonLogger.Error("[DeliveryDriver] VehicleManager not available!");
				route.Status = RouteStatus.Error;
				return;
			}
			VehicleManager instance2 = NetworkSingleton<VehicleManager>.Instance;
			LandVehicle val4 = null;
			try
			{
				val4 = instance2.SpawnAndReturnVehicle(deliveryVehicleCode, position, rotation, false);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[DeliveryDriver] Exception spawning vehicle: " + ex.Message);
				route.Status = RouteStatus.Error;
				return;
			}
			if ((Object)(object)val4 == (Object)null)
			{
				MelonLogger.Error("[DeliveryDriver] SpawnAndReturnVehicle returned null for code: " + deliveryVehicleCode);
				route.Status = RouteStatus.Error;
				return;
			}
			MelonLogger.Msg("[DeliveryDriver] Successfully spawned vehicle: " + val4.VehicleName);
			val2.SetStaticOccupant(val4);
			try
			{
				val4.Park((NetworkConnection)null, new ParkData
				{
					lotGUID = parking.GUID,
					spotIndex = 0,
					alignment = val3.Alignment
				}, false);
			}
			catch (Exception ex2)
			{
				MelonLogger.Warning("[DeliveryDriver] Error parking vehicle: " + ex2.Message);
			}
			val4.SetVisible(true);
			if ((Object)(object)val4.Storage != (Object)null)
			{
				val4.Storage.AccessSettings = (EAccessSettings)2;
				MelonLogger.Msg($"[DeliveryDriver] Vehicle storage has {val4.Storage.ItemSlots.Count} slots");
			}
			else
			{
				MelonLogger.Warning("[DeliveryDriver] Vehicle has no storage!");
			}
			StorageDoorAnimation componentInChildren = ((Component)val4).GetComponentInChildren<StorageDoorAnimation>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.OverrideState(true);
				MelonLogger.Msg("[DeliveryDriver] Opened vehicle storage door");
			}
			route.ActiveVehicle = val4;
			route.CurrentDock = val2;
			route.Status = RouteStatus.LoadingAtSource;
			ConfigureDockForLoading(val2, val4);
			MelonLogger.Msg($"[DeliveryDriver] Van ready at {val.PropertyName} Dock {route.SourceDockIndex + 1}");
		}

		private void ConfigureDockForLoading(LoadingDock dock, LandVehicle vehicle)
		{
			if (!((Object)(object)dock == (Object)null) && !((Object)(object)vehicle?.Storage == (Object)null))
			{
				dock.InputSlots.Clear();
				dock.InputSlots.AddRange(vehicle.Storage.ItemSlots);
				dock.IsAcceptingItems = true;
				MelonLogger.Msg($"[DeliveryDriver] Configured dock for loading with {vehicle.Storage.ItemSlots.Count} input slots");
			}
		}

		private void ConfigureDockForUnloading(LoadingDock dock, LandVehicle vehicle)
		{
			if (!((Object)(object)dock == (Object)null) && !((Object)(object)vehicle?.Storage == (Object)null))
			{
				dock.OutputSlots.Clear();
				dock.OutputSlots.AddRange(vehicle.Storage.ItemSlots);
				MelonLogger.Msg($"[DeliveryDriver] Configured dock for unloading with {vehicle.Storage.ItemSlots.Count} output slots");
			}
		}

		private void ClearDockSlots(LoadingDock dock)
		{
			if (!((Object)(object)dock == (Object)null))
			{
				dock.InputSlots.Clear();
				dock.OutputSlots.Clear();
				dock.IsAcceptingItems = false;
			}
		}

		private void EnsureDockSlotsConfigured(LoadingDock dock, LandVehicle vehicle, bool isSourceDock)
		{
			if ((Object)(object)dock == (Object)null || (Object)(object)vehicle?.Storage == (Object)null)
			{
				return;
			}
			List<ItemSlot> itemSlots = vehicle.Storage.ItemSlots;
			if (isSourceDock)
			{
				if (dock.InputSlots.Count != itemSlots.Count || (dock.InputSlots.Count > 0 && dock.InputSlots[0] != itemSlots[0]))
				{
					dock.InputSlots.Clear();
					dock.InputSlots.AddRange(itemSlots);
					dock.IsAcceptingItems = true;
				}
			}
			else if (dock.OutputSlots.Count != itemSlots.Count || (dock.OutputSlots.Count > 0 && dock.OutputSlots[0] != itemSlots[0]))
			{
				dock.OutputSlots.Clear();
				dock.OutputSlots.AddRange(itemSlots);
			}
		}

		private void ActivateVanAtDock(DeliveryRoute route, LoadingDock dock, bool isSourceDock)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)route.ActiveVehicle == (Object)null || (Object)(object)dock == (Object)null)
			{
				MelonLogger.Error("[DeliveryDriver] Cannot activate van - vehicle or dock is null");
				return;
			}
			LandVehicle activeVehicle = route.ActiveVehicle;
			ParkingLot parking = dock.Parking;
			if ((Object)(object)parking == (Object)null || parking.ParkingSpots == null || parking.ParkingSpots.Count == 0)
			{
				MelonLogger.Error("[DeliveryDriver] Dock has no valid parking");
				return;
			}
			ParkingSpot val = parking.ParkingSpots[0];
			dock.SetStaticOccupant(activeVehicle);
			activeVehicle.Park((NetworkConnection)null, new ParkData
			{
				lotGUID = parking.GUID,
				spotIndex = 0,
				alignment = val.Alignment
			}, false);
			activeVehicle.SetVisible(true);
			if ((Object)(object)activeVehicle.Storage != (Object)null)
			{
				activeVehicle.Storage.AccessSettings = (EAccessSettings)2;
			}
			StorageDoorAnimation componentInChildren = ((Component)activeVehicle).GetComponentInChildren<StorageDoorAnimation>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.OverrideState(true);
			}
			route.CurrentDock = dock;
			if (isSourceDock)
			{
				ConfigureDockForLoading(dock, activeVehicle);
			}
			else
			{
				ConfigureDockForUnloading(dock, activeVehicle);
			}
		}

		private void DeactivateVan(DeliveryRoute route)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)route.ActiveVehicle == (Object)null)
			{
				return;
			}
			LandVehicle activeVehicle = route.ActiveVehicle;
			try
			{
				activeVehicle.ExitPark(false);
				activeVehicle.SetVisible(false);
				activeVehicle.SetTransform(new Vector3(0f, -100f, 0f), Quaternion.identity);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[DeliveryDriver] Error deactivating vehicle: " + ex.Message);
			}
			if ((Object)(object)route.CurrentDock != (Object)null)
			{
				ClearDockSlots(route.CurrentDock);
				route.CurrentDock.SetStaticOccupant((LandVehicle)null);
				if ((Object)(object)route.CurrentDock.VehicleDetector != (Object)null)
				{
					route.CurrentDock.VehicleDetector.Clear();
				}
				route.CurrentDock = null;
			}
		}

		private void ProcessDeliveryRoutes()
		{
			if (!InstanceFinder.IsServer)
			{
				return;
			}
			if (_driverManager.ShouldPayDailyWages())
			{
				PayDailyWages();
			}
			foreach (DeliveryRoute item in _driverManager.Routes.ToList())
			{
				if (item.Status != RouteStatus.Error)
				{
					ProcessRoute(item);
				}
			}
		}

		private void PayDailyWages()
		{
			if (NetworkSingleton<MoneyManager>.InstanceExists)
			{
				float totalDailyWage = _driverManager.GetTotalDailyWage();
				float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance;
				if (cashBalance >= totalDailyWage)
				{
					NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(0f - totalDailyWage, true, false);
					_driverManager.MarkWagesPaid();
					MelonLogger.Msg($"[DeliveryDriver] Paid daily wages: ${totalDailyWage:F0}");
				}
				else
				{
					MelonLogger.Warning($"[DeliveryDriver] Cannot pay driver wages! Need ${totalDailyWage:F0}, have ${cashBalance:F0}");
				}
			}
		}

		private void ProcessRoute(DeliveryRoute route)
		{
			switch (route.Status)
			{
			case RouteStatus.WaitingForDock:
				SpawnVanAtSource(route);
				break;
			case RouteStatus.LoadingAtSource:
				ProcessLoadingAtSource(route);
				break;
			case RouteStatus.InTransit:
				ProcessInTransit(route);
				break;
			case RouteStatus.UnloadingAtDest:
				ProcessUnloadingAtDest(route);
				break;
			case RouteStatus.Returning:
				ProcessReturning(route);
				break;
			}
		}

		private void ProcessLoadingAtSource(DeliveryRoute route)
		{
			if ((Object)(object)route.ActiveVehicle == (Object)null)
			{
				MelonLogger.Warning("[DeliveryDriver] Vehicle lost during loading, respawning...");
				route.Status = RouteStatus.WaitingForDock;
				return;
			}
			StorageEntity storage = route.ActiveVehicle.Storage;
			if ((Object)(object)storage == (Object)null)
			{
				MelonLogger.Warning("[DeliveryDriver] Vehicle has no storage!");
				return;
			}
			if ((Object)(object)route.CurrentDock != (Object)null)
			{
				EnsureDockSlotsConfigured(route.CurrentDock, route.ActiveVehicle, isSourceDock: true);
			}
			int count = storage.ItemSlots.Count;
			int num = storage.ItemSlots.Count((ItemSlot s) => s.ItemInstance != null && s.Quantity > 0);
			if (count != 0)
			{
				float num2 = (float)num / (float)count * 100f;
				int fillThresholdPercent = route.FillThresholdPercent;
				bool flag = num2 >= (float)fillThresholdPercent;
				bool flag2 = num == count;
				if (flag || flag2)
				{
					MelonLogger.Msg($"[DeliveryDriver] Van departing from {route.SourcePropertyCode} with {num}/{count} slots filled ({num2:F0}%)");
					DeactivateVan(route);
					route.TransitStartTime = GetCurrentGameMinutes();
					route.Status = RouteStatus.InTransit;
				}
			}
		}

		private void ProcessInTransit(DeliveryRoute route)
		{
			int elapsedMinutes = GetElapsedMinutes(route.TransitStartTime);
			if (elapsedMinutes < 5)
			{
				return;
			}
			PropertyManager instance = Singleton<PropertyManager>.Instance;
			Property val = ((instance != null) ? instance.GetProperty(route.DestinationPropertyCode) : null);
			if ((Object)(object)val == (Object)null || route.DestinationDockIndex >= val.LoadingDockCount)
			{
				MelonLogger.Error("[DeliveryDriver] Invalid destination!");
				return;
			}
			LoadingDock val2 = val.LoadingDocks[route.DestinationDockIndex];
			if (!val2.IsInUse)
			{
				ActivateVanAtDock(route, val2, isSourceDock: false);
				route.Status = RouteStatus.UnloadingAtDest;
				route.EmptyCheckStartTime = -1;
				MelonLogger.Msg($"[DeliveryDriver] Van arrived at {val.PropertyName} Dock {route.DestinationDockIndex + 1}");
			}
		}

		private void ProcessUnloadingAtDest(DeliveryRoute route)
		{
			if ((Object)(object)route.ActiveVehicle == (Object)null)
			{
				MelonLogger.Warning("[DeliveryDriver] Vehicle lost during unloading!");
				route.Status = RouteStatus.WaitingForDock;
				return;
			}
			StorageEntity storage = route.ActiveVehicle.Storage;
			if ((Object)(object)storage == (Object)null)
			{
				return;
			}
			if ((Object)(object)route.CurrentDock != (Object)null)
			{
				EnsureDockSlotsConfigured(route.CurrentDock, route.ActiveVehicle, isSourceDock: false);
			}
			if (storage.ItemSlots.Count((ItemSlot s) => s.ItemInstance != null && s.Quantity > 0) == 0)
			{
				if (route.EmptyCheckStartTime < 0)
				{
					route.EmptyCheckStartTime = GetCurrentGameMinutes();
					return;
				}
				int elapsedMinutes = GetElapsedMinutes(route.EmptyCheckStartTime);
				if (elapsedMinutes >= 2)
				{
					MelonLogger.Msg("[DeliveryDriver] Van empty at destination, returning to source");
					DeactivateVan(route);
					route.TransitStartTime = GetCurrentGameMinutes();
					route.Status = RouteStatus.Returning;
				}
			}
			else
			{
				route.EmptyCheckStartTime = -1;
			}
		}

		private void ProcessReturning(DeliveryRoute route)
		{
			int elapsedMinutes = GetElapsedMinutes(route.TransitStartTime);
			if (elapsedMinutes < 5)
			{
				return;
			}
			PropertyManager instance = Singleton<PropertyManager>.Instance;
			Property val = ((instance != null) ? instance.GetProperty(route.SourcePropertyCode) : null);
			if ((Object)(object)val == (Object)null || route.SourceDockIndex >= val.LoadingDockCount)
			{
				MelonLogger.Error("[DeliveryDriver] Invalid source on return!");
				return;
			}
			LoadingDock val2 = val.LoadingDocks[route.SourceDockIndex];
			if (!val2.IsInUse)
			{
				ActivateVanAtDock(route, val2, isSourceDock: true);
				route.Status = RouteStatus.LoadingAtSource;
				MelonLogger.Msg($"[DeliveryDriver] Van returned to {val.PropertyName} Dock {route.SourceDockIndex + 1}");
			}
		}

		private int GetCurrentGameMinutes()
		{
			if (NetworkSingleton<TimeManager>.InstanceExists)
			{
				TimeManager instance = NetworkSingleton<TimeManager>.Instance;
				int num = instance.CurrentTime / 100;
				int num2 = instance.CurrentTime % 100;
				return instance.ElapsedDays * 24 * 60 + num * 60 + num2;
			}
			return 0;
		}

		private int GetElapsedMinutes(int startTime)
		{
			return GetCurrentGameMinutes() - startTime;
		}
	}
	public class DeliveryDriver
	{
		private static readonly string[] FirstNames = new string[15]
		{
			"Mike", "Dave", "Joe", "Tom", "Bill", "Sam", "Jack", "Pete", "Nick", "Steve",
			"Maria", "Lisa", "Kate", "Emma", "Anna"
		};

		private static readonly string[] LastNames = new string[10] { "Smith", "Jones", "Brown", "Wilson", "Taylor", "Clark", "Hall", "Lee", "King", "Wright" };

		public string Id { get; set; }

		public string Name { get; set; }

		public DeliveryRoute AssignedRoute { get; set; }

		public bool IsPaidToday { get; set; }

		public static DeliveryDriver CreateRandom()
		{
			Random random = new Random();
			return new DeliveryDriver
			{
				Id = Guid.NewGuid().ToString(),
				Name = FirstNames[random.Next(FirstNames.Length)] + " " + LastNames[random.Next(LastNames.Length)],
				IsPaidToday = true
			};
		}
	}
	public class DeliveryRoute
	{
		public string SourcePropertyCode { get; set; }

		public int SourceDockIndex { get; set; }

		public string DestinationPropertyCode { get; set; }

		public int DestinationDockIndex { get; set; }

		public int FillThresholdPercent { get; set; } = 80;


		public string AssignedDriverId { get; set; }

		public RouteStatus Status { get; set; } = RouteStatus.WaitingForDock;


		public int TransitStartTime { get; set; }

		public int EmptyCheckStartTime { get; set; } = -1;


		public LandVehicle ActiveVehicle { get; set; }

		public LoadingDock CurrentDock { get; set; }
	}
	public enum RouteStatus
	{
		WaitingForDock,
		LoadingAtSource,
		InTransit,
		UnloadingAtDest,
		Returning,
		Error
	}
	public class DeliveryDriverManager
	{
		private int _lastPayDay = -1;

		public List<DeliveryDriver> Drivers { get; } = new List<DeliveryDriver>();


		public List<DeliveryRoute> Routes { get; } = new List<DeliveryRoute>();


		public void HireDriver()
		{
			DeliveryDriver item = DeliveryDriver.CreateRandom();
			Drivers.Add(item);
		}

		public void FireDriver(DeliveryDriver driver)
		{
			if (driver.AssignedRoute != null)
			{
				Routes.Remove(driver.AssignedRoute);
			}
			Drivers.Remove(driver);
		}

		public int GetIdleDriverCount()
		{
			return Drivers.Count((DeliveryDriver d) => d.AssignedRoute == null);
		}

		public float GetTotalDailyWage()
		{
			return (float)Drivers.Count * 100f;
		}

		public bool ShouldPayDailyWages()
		{
			if (!NetworkSingleton<TimeManager>.InstanceExists)
			{
				return false;
			}
			TimeManager instance = NetworkSingleton<TimeManager>.Instance;
			int elapsedDays = instance.ElapsedDays;
			if (elapsedDays != _lastPayDay && instance.CurrentTime >= 600)
			{
				return true;
			}
			return false;
		}

		public void MarkWagesPaid()
		{
			if (NetworkSingleton<TimeManager>.InstanceExists)
			{
				_lastPayDay = NetworkSingleton<TimeManager>.Instance.ElapsedDays;
			}
			foreach (DeliveryDriver driver in Drivers)
			{
				driver.IsPaidToday = true;
			}
		}
	}
}