Decompiled source of EasyDeliveryCoLanCoop v0.2.181

BepInEx/plugins/EasyDeliveryCoLanCoop/EasyDeliveryCoLanCoop.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EasyDeliveryCoLanCoop")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+20c9b459894249c8547bf5b0f1887329b537a26b")]
[assembly: AssemblyProduct("EasyDeliveryCoLanCoop")]
[assembly: AssemblyTitle("EasyDeliveryCoLanCoop")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EasyDeliveryCoLanCoop
{
	internal static class CarVisualClone
	{
		internal static GameObject? TryCreateCarPrefab(Transform carRoot)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)carRoot == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject val = new GameObject("EasyDeliveryCoLanCoop.CarPrefab." + ((Object)carRoot).name);
				((Object)val).hideFlags = (HideFlags)52;
				val.transform.localScale = carRoot.lossyScale;
				CopyAudioSource(carRoot, val.transform);
				for (int i = 0; i < carRoot.childCount; i++)
				{
					CopyRecursive(carRoot.GetChild(i), val.transform);
				}
				val.SetActive(false);
				return val;
			}
			catch
			{
				return null;
			}
		}

		private static void CopyRecursive(Transform src, Transform dstParent)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (ShouldSkip(src))
			{
				return;
			}
			GameObject val = new GameObject(((Object)src).name);
			((Object)val).hideFlags = (HideFlags)52;
			val.transform.SetParent(dstParent, false);
			val.transform.localPosition = src.localPosition;
			val.transform.localRotation = src.localRotation;
			val.transform.localScale = src.localScale;
			MeshFilter component = ((Component)src).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)src).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				val.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
			}
			if ((Object)(object)component2 != (Object)null)
			{
				MeshRenderer val2 = val.AddComponent<MeshRenderer>();
				Material[] sharedMaterials = ((Renderer)component2).sharedMaterials;
				Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
				for (int i = 0; i < sharedMaterials.Length; i++)
				{
					object obj = array;
					int num = i;
					obj = (object)(((Object)(object)sharedMaterials[i] != (Object)null) ? new Material(sharedMaterials[i]) : ((Material)null));
					((object[])obj)[num] = obj;
				}
				((Renderer)val2).sharedMaterials = array;
				((Renderer)val2).shadowCastingMode = ((Renderer)component2).shadowCastingMode;
				((Renderer)val2).receiveShadows = ((Renderer)component2).receiveShadows;
				((Renderer)val2).lightProbeUsage = ((Renderer)component2).lightProbeUsage;
				((Renderer)val2).reflectionProbeUsage = ((Renderer)component2).reflectionProbeUsage;
			}
			CopyAudioSource(src, val.transform);
			for (int j = 0; j < src.childCount; j++)
			{
				CopyRecursive(src.GetChild(j), val.transform);
			}
		}

		private static void CopyAudioSource(Transform src, Transform dst)
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)src == (Object)null || (Object)(object)dst == (Object)null)
			{
				return;
			}
			AudioSource component = ((Component)src).GetComponent<AudioSource>();
			if (!((Object)(object)component == (Object)null))
			{
				AudioSource val = ((Component)dst).GetComponent<AudioSource>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)dst).gameObject.AddComponent<AudioSource>();
				}
				val.clip = component.clip;
				val.outputAudioMixerGroup = component.outputAudioMixerGroup;
				val.mute = component.mute;
				val.bypassEffects = component.bypassEffects;
				val.bypassListenerEffects = component.bypassListenerEffects;
				val.bypassReverbZones = component.bypassReverbZones;
				val.playOnAwake = false;
				val.loop = component.loop;
				val.priority = component.priority;
				val.volume = component.volume;
				val.pitch = component.pitch;
				val.panStereo = component.panStereo;
				val.spatialBlend = component.spatialBlend;
				val.reverbZoneMix = component.reverbZoneMix;
				val.dopplerLevel = component.dopplerLevel;
				val.spread = component.spread;
				val.rolloffMode = component.rolloffMode;
				val.minDistance = component.minDistance;
				val.maxDistance = component.maxDistance;
				((Behaviour)val).enabled = ((Behaviour)component).enabled;
			}
		}

		private static bool ShouldSkip(Transform t)
		{
			string name = ((Object)t).name;
			if (!string.IsNullOrEmpty(name))
			{
				string text = name.ToLowerInvariant();
				if (text.Contains("wheelcollider") || text.Contains("collider") || text.Contains("trigger") || text.Contains("hitbox"))
				{
					return true;
				}
				if (text.Contains("debug") || text.Contains("gizmo"))
				{
					return true;
				}
				if (text == "sphere" || text.EndsWith("sphere"))
				{
					return true;
				}
			}
			if ((Object)(object)((Component)t).GetComponent<Collider>() != (Object)null && (Object)(object)((Component)t).GetComponent<AudioSource>() == (Object)null)
			{
				return true;
			}
			return false;
		}
	}
	internal static class ExternalAssetBundle
	{
		private static AssetBundle? _bundle;

		private static string? _loadedPath;

		private static float _nextRetryAt;

		private static bool _loggedLoadError;

		internal static GameObject? TryLoadGameObject(string assetName)
		{
			if (!Plugin.ExternalAssetsEnabled.Value)
			{
				return null;
			}
			if (string.IsNullOrWhiteSpace(assetName))
			{
				return null;
			}
			AssetBundle val = EnsureLoaded();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject val2 = val.LoadAsset<GameObject>(assetName);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
				string fileName = Path.GetFileName(assetName);
				if (!string.IsNullOrWhiteSpace(fileName) && !string.Equals(fileName, assetName, StringComparison.OrdinalIgnoreCase))
				{
					return val.LoadAsset<GameObject>(fileName);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ExternalAssetBundle: failed to load asset '" + assetName + "': " + ex.Message));
			}
			return null;
		}

		internal static GameObject? TryLoadGameObjectByBaseName(string baseName)
		{
			if (!Plugin.ExternalAssetsEnabled.Value)
			{
				return null;
			}
			if (string.IsNullOrWhiteSpace(baseName))
			{
				return null;
			}
			AssetBundle val = EnsureLoaded();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				baseName = Path.GetFileNameWithoutExtension(baseName).Trim();
				if (baseName.Length == 0)
				{
					return null;
				}
				string[] allAssetNames = val.GetAllAssetNames();
				if (allAssetNames == null || allAssetNames.Length == 0)
				{
					return null;
				}
				foreach (string text in allAssetNames)
				{
					if (!string.IsNullOrEmpty(text) && string.Equals(Path.GetFileNameWithoutExtension(text), baseName, StringComparison.OrdinalIgnoreCase))
					{
						GameObject val2 = val.LoadAsset<GameObject>(text);
						if ((Object)(object)val2 != (Object)null)
						{
							return val2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ExternalAssetBundle: TryLoadGameObjectByBaseName failed for '" + baseName + "': " + ex.Message));
			}
			return null;
		}

		internal static void InvalidateIfConfigChanged()
		{
			string text = ResolveBundlePath(Plugin.ExternalAssetsBundlePath.Value);
			if (string.IsNullOrWhiteSpace(text))
			{
				text = null;
			}
			if (!string.Equals(_loadedPath, text, StringComparison.OrdinalIgnoreCase))
			{
				Unload();
			}
		}

		private static AssetBundle? EnsureLoaded()
		{
			InvalidateIfConfigChanged();
			if ((Object)(object)_bundle != (Object)null)
			{
				return _bundle;
			}
			if (Time.unscaledTime < _nextRetryAt)
			{
				return null;
			}
			_nextRetryAt = Time.unscaledTime + 2f;
			string text = ResolveBundlePath(Plugin.ExternalAssetsBundlePath.Value);
			if (string.IsNullOrWhiteSpace(text))
			{
				return null;
			}
			try
			{
				if (!File.Exists(text))
				{
					if (!_loggedLoadError)
					{
						_loggedLoadError = true;
						Plugin.Log.LogWarning((object)("ExternalAssetBundle: bundle not found at '" + text + "'."));
					}
					return null;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text);
				if ((Object)(object)val == (Object)null)
				{
					if (!_loggedLoadError)
					{
						_loggedLoadError = true;
						Plugin.Log.LogWarning((object)("ExternalAssetBundle: failed to load bundle from '" + text + "'."));
					}
					return null;
				}
				_bundle = val;
				_loadedPath = text;
				_loggedLoadError = false;
				Plugin.Log.LogInfo((object)("ExternalAssetBundle: loaded '" + text + "'."));
				return _bundle;
			}
			catch (Exception ex)
			{
				if (!_loggedLoadError)
				{
					_loggedLoadError = true;
					Plugin.Log.LogWarning((object)("ExternalAssetBundle: exception loading bundle: " + ex.Message));
				}
				return null;
			}
		}

		private static void Unload()
		{
			try
			{
				if ((Object)(object)_bundle != (Object)null)
				{
					_bundle.Unload(false);
				}
			}
			catch
			{
			}
			_bundle = null;
			_loadedPath = null;
			_loggedLoadError = false;
		}

		private static string? ResolveBundlePath(string? raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return null;
			}
			raw = raw.Trim();
			string text = TryResolve(raw);
			if (File.Exists(text))
			{
				return text;
			}
			if (!raw.EndsWith(".bundle", StringComparison.OrdinalIgnoreCase))
			{
				string text2 = TryResolve(raw + ".bundle");
				if (File.Exists(text2))
				{
					return text2;
				}
			}
			return text;
			static string TryResolve(string candidate)
			{
				if (Path.IsPathRooted(candidate))
				{
					return candidate;
				}
				string text3 = Path.Combine(Paths.BepInExRootPath, candidate);
				if (File.Exists(text3))
				{
					return text3;
				}
				string text4 = Path.Combine(Paths.PluginPath, candidate);
				if (File.Exists(text4))
				{
					return text4;
				}
				return Path.Combine(Paths.GameRootPath, candidate);
			}
		}
	}
	internal static class ExternalMods
	{
		internal static bool IsCustomTruckShopLoaded()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (string.Equals(assembly.GetName().Name, "CustomTruckShop", StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}
	}
	internal static class GameAccess
	{
		private static readonly BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly string[] CarHornKeywords = new string[6] { "horn", "honk", "beep", "klaxon", "claxon", "signal" };

		private static readonly string[] CarSkidKeywords = new string[10] { "skid", "drift", "tire", "screech", "slide", "brake", "squeak", "scrape", "friction", "slip" };

		private static readonly string[] CarCrashKeywords = new string[11]
		{
			"crash", "impact", "hit", "collision", "bump", "metal", "smash", "thud", "clunk", "bang",
			"bonk"
		};

		private static readonly string[] CarHornNoiseKeywords = new string[12]
		{
			"headlight", "light", "door", "engine", "motor", "idle", "rpm", "gear", "radio", "music",
			"wind", "road"
		};

		private static readonly Dictionary<int, bool> LocalCarSfxPlayingBySource = new Dictionary<int, bool>();

		private static readonly Dictionary<int, float> LocalCarSfxNextLoopEmitAt = new Dictionary<int, float>();

		private static readonly Dictionary<string, AudioClip> LoadedAudioClipByName = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase);

		internal const byte CarSfxHorn = 1;

		internal const byte CarSfxSkid = 2;

		internal const byte CarSfxCrash = 3;

		private static bool _jobApplyDisabled;

		private static string? _jobApplyDisabledReason;

		private static bool _loggedPlayerVisualRootFail;

		private static bool _loggedMenuButtonDump;

		private static bool _loggedUiToolkitButtonDump;

		internal static bool TryReadLocalPlayerPose(out Vector3 pos, out Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			pos = default(Vector3);
			rot = default(Quaternion);
			object? obj = TryFindObjectOfTypeByName("sCharacterController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val != null)
			{
				try
				{
					if (TryGetCombinedRendererBounds(val.transform, out var bounds))
					{
						pos = ((Bounds)(ref bounds)).center;
						rot = val.transform.rotation;
						return true;
					}
					pos = val.transform.position;
					rot = val.transform.rotation;
					return true;
				}
				catch
				{
				}
			}
			try
			{
				Camera val2 = Camera.main;
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = Object.FindObjectOfType<Camera>();
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				pos = ((Component)val2).transform.position;
				rot = ((Component)val2).transform.rotation;
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryReadLocalPlayerControllerPose(out Vector3 pos, out Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			pos = default(Vector3);
			rot = default(Quaternion);
			object? obj = TryFindObjectOfTypeByName("sCharacterController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val != null)
			{
				try
				{
					pos = val.transform.position;
					rot = val.transform.rotation;
					return true;
				}
				catch
				{
					return false;
				}
			}
			return TryReadLocalPlayerPose(out pos, out rot);
		}

		internal static bool TryApplyLocalPlayerControllerPose(Vector3 pos, Quaternion rot)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			object? obj = TryFindObjectOfTypeByName("sCharacterController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val == null)
			{
				return false;
			}
			try
			{
				val.transform.position = pos;
				val.transform.rotation = rot;
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryReadSaveId(out string saveId)
		{
			saveId = string.Empty;
			try
			{
				object obj = TryGetSaveSystemInstance();
				if (obj == null)
				{
					return false;
				}
				Type type = obj.GetType();
				string[] array = new string[8] { "saveSlot", "currentSlot", "slot", "saveName", "profileName", "currentProfile", "fileName", "saveFile" };
				foreach (string name in array)
				{
					FieldInfo field = type.GetField(name, Any);
					if (field != null)
					{
						object value = field.GetValue(obj);
						if (value != null)
						{
							saveId = value.ToString() ?? string.Empty;
							if (!string.IsNullOrWhiteSpace(saveId))
							{
								return true;
							}
						}
					}
					PropertyInfo property = type.GetProperty(name, Any);
					if (!(property != null))
					{
						continue;
					}
					object value2 = property.GetValue(obj, null);
					if (value2 != null)
					{
						saveId = value2.ToString() ?? string.Empty;
						if (!string.IsNullOrWhiteSpace(saveId))
						{
							return true;
						}
					}
				}
				Dictionary<string, string> dictionary = TryReadSaveSystemSnapshot();
				if (dictionary != null && dictionary.Count > 0)
				{
					foreach (KeyValuePair<string, string> item in dictionary)
					{
						string key = item.Key;
						if (string.IsNullOrEmpty(key))
						{
							continue;
						}
						string text = key.ToLowerInvariant();
						if (text.Contains("saveslot") || text.EndsWith("slot") || text.Contains("savename") || text.Contains("profilename") || text.Contains("savefile"))
						{
							string value3 = item.Value;
							if (!string.IsNullOrWhiteSpace(value3))
							{
								saveId = value3;
								return true;
							}
						}
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		internal static bool IsGameplayWorldLoaded()
		{
			try
			{
				if (TryFindObjectOfTypeByName("jobBoard") != null)
				{
					return true;
				}
				if (TryFindObjectOfTypeByName("sCarController") != null)
				{
					return true;
				}
				if (TryFindObjectOfTypeByName("sDeliveryManager") != null)
				{
					return true;
				}
				if (TryFindObjectOfTypeByName("sCityManager") != null)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool TryGetCombinedRendererBounds(Transform root, out Bounds bounds)
		{
			//IL_0001: 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)
			//IL_0094: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			try
			{
				Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
				if (componentsInChildren == null || componentsInChildren.Length == 0)
				{
					return false;
				}
				bool flag = false;
				Bounds val = default(Bounds);
				foreach (Renderer val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					string name = ((Object)((Component)val2).gameObject).name;
					if (string.IsNullOrEmpty(name) || !name.StartsWith("EasyDeliveryCoLanCoop.", StringComparison.Ordinal))
					{
						if (!flag)
						{
							val = val2.bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref val)).Encapsulate(val2.bounds);
						}
					}
				}
				if (!flag)
				{
					return false;
				}
				bounds = val;
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryFindLocalPlayerVisualRoot(out Transform visualRoot)
		{
			visualRoot = null;
			object? obj = TryFindObjectOfTypeByName("sCharacterController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val != null)
			{
				Transform val2 = FindBestVisualRoot(val.transform);
				if ((Object)(object)val2 != (Object)null)
				{
					visualRoot = val2;
					return true;
				}
			}
			try
			{
				GameObject val3 = GameObject.Find("guy") ?? GameObject.Find("Guy") ?? GameObject.Find("player") ?? GameObject.Find("Player");
				if ((Object)(object)val3 != (Object)null)
				{
					Transform val4 = FindBestVisualRoot(val3.transform);
					if ((Object)(object)val4 != (Object)null)
					{
						visualRoot = val4;
						return true;
					}
				}
			}
			catch
			{
			}
			if (!_loggedPlayerVisualRootFail)
			{
				_loggedPlayerVisualRootFail = true;
				Plugin.Log.LogWarning((object)"TryFindLocalPlayerVisualRoot failed; remote player may fall back to primitive visuals.");
			}
			return false;
		}

		internal static bool TryReadInCar(out bool inCar)
		{
			inCar = false;
			object obj = TryFindObjectOfTypeByName("sCarController");
			if (obj == null)
			{
				return false;
			}
			PropertyInfo property = obj.GetType().GetProperty("GuyActive", Any);
			if (property != null && property.PropertyType == typeof(bool))
			{
				try
				{
					inCar = (bool)property.GetValue(obj, null);
					return true;
				}
				catch
				{
					return false;
				}
			}
			FieldInfo field = obj.GetType().GetField("guyActive", Any);
			if (field != null && field.FieldType == typeof(bool))
			{
				try
				{
					inCar = (bool)field.GetValue(obj);
					return true;
				}
				catch
				{
					return false;
				}
			}
			return false;
		}

		internal static bool TryReadCarState(out Vector3 pos, out Quaternion rot, out Vector3 vel, out Vector3 angVel, out bool hasCar)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			pos = default(Vector3);
			rot = default(Quaternion);
			vel = default(Vector3);
			angVel = default(Vector3);
			hasCar = false;
			object obj = TryFindObjectOfTypeByName("sCarController");
			if (obj == null)
			{
				return false;
			}
			object? obj2 = obj.GetType().GetField("rb", Any)?.GetValue(obj);
			Rigidbody val = (Rigidbody)((obj2 is Rigidbody) ? obj2 : null);
			if (val != null)
			{
				hasCar = true;
				pos = val.position;
				rot = val.rotation;
				vel = val.velocity;
				angVel = val.angularVelocity;
				return true;
			}
			Component val2 = (Component)((obj is Component) ? obj : null);
			if (val2 != null)
			{
				hasCar = true;
				pos = val2.transform.position;
				rot = val2.transform.rotation;
				vel = Vector3.zero;
				angVel = Vector3.zero;
				return true;
			}
			return false;
		}

		internal static bool TryGetLocalCarSfxPulses(out List<(byte SfxId, string ClipName, string SourceName)> sfxEvents)
		{
			sfxEvents = new List<(byte, string, string)>(4);
			object obj = TryFindObjectOfTypeByName("sCarController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val == null)
			{
				return false;
			}
			bool flag = Plugin.IsHornOnlyCarSoundMode();
			bool flag2 = false;
			if (TryReadDirectLocalHornPulse(obj, out bool hornPressed, out string clipName, out string sourceName))
			{
				flag2 = hornPressed;
				if (hornPressed)
				{
					sfxEvents.Add((1, clipName, sourceName));
				}
				if (flag)
				{
					return hornPressed;
				}
			}
			bool flag3 = TryDetectCarSfxPulsesOnRoot(val.transform, sfxEvents);
			return flag2 || flag3;
		}

		private static bool TryReadDirectLocalHornPulse(object carController, out bool hornPressed, out string clipName, out string sourceName)
		{
			hornPressed = false;
			clipName = string.Empty;
			sourceName = string.Empty;
			try
			{
				if (carController == null)
				{
					return false;
				}
				Type type = carController.GetType();
				FieldInfo field = type.GetField("player", Any);
				if (field == null || !(field.GetValue(carController) is int num) || num < 0)
				{
					return false;
				}
				Type type2 = type.Assembly.GetType("sInputManager");
				if (type2 == null)
				{
					return false;
				}
				if (!(type2.GetField("players", Any)?.GetValue(null) is Array array) || num >= array.Length)
				{
					return false;
				}
				object value = array.GetValue(num);
				if (value == null)
				{
					return false;
				}
				FieldInfo field2 = value.GetType().GetField("hornPressed", Any);
				if (field2 == null)
				{
					return false;
				}
				object value2 = field2.GetValue(value);
				bool flag = default(bool);
				int num2;
				if (value2 is bool)
				{
					flag = (bool)value2;
					num2 = 1;
				}
				else
				{
					num2 = 0;
				}
				hornPressed = (byte)((uint)num2 & (flag ? 1u : 0u)) != 0;
				if (!hornPressed)
				{
					return true;
				}
				sourceName = "Headlights";
				TryResolveLocalHornClipMetadata(carController, ref clipName, ref sourceName);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static void TryResolveLocalHornClipMetadata(object carController, ref string clipName, ref string sourceName)
		{
			try
			{
				Component val = (Component)((carController is Component) ? carController : null);
				if (val == null)
				{
					return;
				}
				Type type = carController.GetType().Assembly.GetType("Headlights");
				if (type == null)
				{
					return;
				}
				Component componentInChildren = val.GetComponentInChildren(type, true);
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					object? obj = type.GetField("horn", Any)?.GetValue(componentInChildren);
					AudioClip val2 = (AudioClip)((obj is AudioClip) ? obj : null);
					if (val2 != null && (Object)(object)val2 != (Object)null && !string.IsNullOrWhiteSpace(((Object)val2).name))
					{
						clipName = ((Object)val2).name;
					}
					object? obj2 = type.GetField("source", Any)?.GetValue(componentInChildren);
					AudioSource val3 = (AudioSource)((obj2 is AudioSource) ? obj2 : null);
					if (val3 != null && (Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).gameObject != (Object)null)
					{
						sourceName = ((Object)((Component)val3).gameObject).name ?? sourceName;
					}
				}
			}
			catch
			{
			}
		}

		internal static bool TryPlayLikelyCarSfx(Transform root, byte sfxId, string? clipName = null, string? sourceName = null)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			try
			{
				if (sfxId == 1)
				{
					if (TryPlayHeadlightsHorn(root, clipName, sourceName))
					{
						return true;
					}
					string text = clipName ?? string.Empty;
					if (!string.IsNullOrWhiteSpace(text))
					{
						AudioClip val = ResolveLoadedAudioClipByName(text);
						if ((Object)(object)val != (Object)null)
						{
							return TryPlayClipOnRootEmitter(root, val);
						}
						return false;
					}
				}
				AudioSource[] componentsInChildren = ((Component)root).GetComponentsInChildren<AudioSource>(true);
				if (componentsInChildren == null || componentsInChildren.Length == 0)
				{
					return false;
				}
				string text2 = clipName ?? string.Empty;
				string value = sourceName ?? string.Empty;
				if (!string.IsNullOrWhiteSpace(text2))
				{
					foreach (AudioSource val2 in componentsInChildren)
					{
						if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.clip == (Object)null) && string.Equals(((Object)val2.clip).name, text2, StringComparison.OrdinalIgnoreCase))
						{
							return TryPlaySourcePulse(val2);
						}
					}
				}
				if (!string.IsNullOrWhiteSpace(value) && sfxId != 1)
				{
					foreach (AudioSource val3 in componentsInChildren)
					{
						if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).gameObject == (Object)null) && ((Object)((Component)val3).gameObject).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							return TryPlaySourcePulse(val3);
						}
					}
				}
				switch (sfxId)
				{
				case 0:
					return false;
				case 1:
					return false;
				default:
				{
					AudioSource val4 = null;
					int num = int.MinValue;
					foreach (AudioSource val5 in componentsInChildren)
					{
						if (!((Object)(object)val5 == (Object)null))
						{
							int num2 = ScoreLikelyCarSfxSource(val5, sfxId);
							if (num2 > num)
							{
								val4 = val5;
								num = num2;
							}
						}
					}
					if ((Object)(object)val4 == (Object)null || num <= 0)
					{
						return false;
					}
					return TryPlaySourcePulse(val4);
				}
				}
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryPlayCarSfxAudibleFallback(Transform root, byte sfxId, string? clipName = null, string? sourceName = null)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			try
			{
				if (sfxId == 1)
				{
					if (TryPlayHeadlightsHorn(root, clipName, sourceName))
					{
						return true;
					}
					string text = clipName ?? string.Empty;
					if (!string.IsNullOrWhiteSpace(text))
					{
						AudioClip val = ResolveLoadedAudioClipByName(text);
						if ((Object)(object)val != (Object)null)
						{
							return TryPlayClipOnRootEmitter(root, val);
						}
						return false;
					}
				}
				AudioSource[] componentsInChildren = ((Component)root).GetComponentsInChildren<AudioSource>(true);
				if (componentsInChildren == null || componentsInChildren.Length == 0)
				{
					return false;
				}
				AudioClip val2 = ResolveBestClipForSfx(componentsInChildren, sfxId, clipName, sourceName);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				AudioSource val3 = ((Component)root).GetComponent<AudioSource>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)root).gameObject.AddComponent<AudioSource>();
				}
				val3.playOnAwake = false;
				val3.loop = false;
				val3.spatialBlend = 1f;
				val3.volume = 0.95f;
				val3.pitch = 1f;
				val3.minDistance = 3f;
				val3.maxDistance = 22f;
				val3.Stop();
				val3.clip = val2;
				val3.PlayOneShot(val2);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static AudioClip? ResolveBestClipForSfx(AudioSource[] sources, byte sfxId, string? clipName, string? sourceName)
		{
			if (sources == null || sources.Length == 0)
			{
				return null;
			}
			string text = clipName ?? string.Empty;
			string value = sourceName ?? string.Empty;
			if (!string.IsNullOrWhiteSpace(text))
			{
				foreach (AudioSource val in sources)
				{
					if (!((Object)(object)((val != null) ? val.clip : null) == (Object)null) && string.Equals(((Object)val.clip).name, text, StringComparison.OrdinalIgnoreCase))
					{
						return val.clip;
					}
				}
			}
			if (!string.IsNullOrWhiteSpace(value))
			{
				foreach (AudioSource val2 in sources)
				{
					if (!((Object)(object)((val2 != null) ? val2.clip : null) == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null) && ((Object)((Component)val2).gameObject).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val2.clip;
					}
				}
			}
			AudioClip result = null;
			int num = int.MinValue;
			foreach (AudioSource val3 in sources)
			{
				if ((Object)(object)((val3 != null) ? val3.clip : null) == (Object)null)
				{
					continue;
				}
				int num2 = ScoreLikelyCarSfxSource(val3, sfxId);
				if (sfxId == 1)
				{
					if (!val3.loop)
					{
						num2 += 25;
					}
					if (val3.clip.length > 0.01f && val3.clip.length <= 2.5f)
					{
						num2 += 20;
					}
				}
				if (num2 > num)
				{
					num = num2;
					result = val3.clip;
				}
			}
			return result;
		}

		private static bool TryPlaySourcePulse(AudioSource src)
		{
			if ((Object)(object)src == (Object)null || (Object)(object)src.clip == (Object)null)
			{
				return false;
			}
			if (src.isPlaying)
			{
				src.Stop();
			}
			src.Play();
			return true;
		}

		private static bool TryPlayClipOnRootEmitter(Transform root, AudioClip clip)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)clip == (Object)null)
			{
				return false;
			}
			try
			{
				AudioSource val = ((Component)root).GetComponent<AudioSource>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)root).gameObject.AddComponent<AudioSource>();
				}
				val.playOnAwake = false;
				val.loop = false;
				val.spatialBlend = 1f;
				val.volume = 0.95f;
				val.pitch = 1f;
				val.minDistance = 3f;
				val.maxDistance = 22f;
				val.PlayOneShot(clip);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool TryPlayHeadlightsHorn(Transform root, string? preferredClipName = null, string? preferredSourceName = null)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			try
			{
				Type type = typeof(GameAccess).Assembly.GetType("Headlights");
				if (type == null)
				{
					return false;
				}
				Component componentInChildren = ((Component)root).GetComponentInChildren(type, true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					return false;
				}
				FieldInfo field = type.GetField("horn", Any);
				object? obj = type.GetField("source", Any)?.GetValue(componentInChildren);
				AudioSource val = (AudioSource)((obj is AudioSource) ? obj : null);
				if (val == null || (Object)(object)val == (Object)null)
				{
					return false;
				}
				AudioClip val2 = null;
				string text = preferredClipName ?? string.Empty;
				string value = preferredSourceName ?? string.Empty;
				if (!string.IsNullOrWhiteSpace(text))
				{
					val2 = ResolveLoadedAudioClipByName(text);
				}
				bool flag = !string.IsNullOrWhiteSpace(text);
				if ((Object)(object)val2 == (Object)null)
				{
					object? obj2 = field?.GetValue(componentInChildren);
					AudioClip val3 = (AudioClip)((obj2 is AudioClip) ? obj2 : null);
					if (val3 != null && (Object)(object)val3 != (Object)null)
					{
						val2 = val3;
					}
				}
				if (!string.IsNullOrWhiteSpace(text) && ((Object)(object)val2 == (Object)null || !string.Equals(((Object)val2).name, text, StringComparison.OrdinalIgnoreCase)))
				{
					AudioSource[] componentsInChildren = ((Component)root).GetComponentsInChildren<AudioSource>(true);
					foreach (AudioSource val4 in componentsInChildren)
					{
						if (!((Object)(object)((val4 != null) ? val4.clip : null) == (Object)null) && string.Equals(((Object)val4.clip).name, text, StringComparison.OrdinalIgnoreCase))
						{
							val2 = val4.clip;
							break;
						}
					}
				}
				if ((Object)(object)val2 == (Object)null && !string.IsNullOrWhiteSpace(value))
				{
					AudioSource[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<AudioSource>(true);
					foreach (AudioSource val5 in componentsInChildren2)
					{
						if (!((Object)(object)((val5 != null) ? val5.clip : null) == (Object)null) && !((Object)(object)((Component)val5).gameObject == (Object)null) && ((Object)((Component)val5).gameObject).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							val2 = val5.clip;
							break;
						}
					}
				}
				if (flag)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						return false;
					}
					if (!string.Equals(((Object)val2).name, text, StringComparison.OrdinalIgnoreCase))
					{
						return false;
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				val.PlayOneShot(val2);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static AudioClip? ResolveLoadedAudioClipByName(string clipName)
		{
			if (string.IsNullOrWhiteSpace(clipName))
			{
				return null;
			}
			if (LoadedAudioClipByName.TryGetValue(clipName, out AudioClip value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			try
			{
				AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>();
				foreach (AudioClip val in array)
				{
					if (!((Object)(object)val == (Object)null) && !string.IsNullOrWhiteSpace(((Object)val).name) && string.Equals(((Object)val).name, clipName, StringComparison.OrdinalIgnoreCase))
					{
						LoadedAudioClipByName[clipName] = val;
						return val;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static bool TryDetectCarSfxPulsesOnRoot(Transform root, List<(byte SfxId, string ClipName, string SourceName)> sfxEvents)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			try
			{
				bool result = false;
				HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				HashSet<int> hashSet2 = new HashSet<int>();
				AudioSource[] componentsInChildren = ((Component)root).GetComponentsInChildren<AudioSource>(true);
				float unscaledTime = Time.unscaledTime;
				foreach (AudioSource val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					string text = (((Object)(object)val.clip != (Object)null) ? (((Object)val.clip).name ?? string.Empty) : string.Empty);
					string text2 = (((Object)(object)((Component)val).gameObject != (Object)null) ? (((Object)((Component)val).gameObject).name ?? string.Empty) : string.Empty);
					byte b = ClassifyCarSfxSource(val);
					if (b == 0 && Plugin.IsHornOnlyCarSoundMode() && IsLikelyHornFallbackPulse(val, text, text2))
					{
						b = 1;
					}
					int instanceID = ((Object)val).GetInstanceID();
					hashSet2.Add(instanceID);
					bool isPlaying = val.isPlaying;
					bool value;
					bool flag = LocalCarSfxPlayingBySource.TryGetValue(instanceID, out value) && value;
					bool flag2 = false;
					if (isPlaying && val.loop && (!LocalCarSfxNextLoopEmitAt.TryGetValue(instanceID, out var value2) || unscaledTime >= value2))
					{
						flag2 = true;
					}
					if (isPlaying && (!flag || flag2))
					{
						byte b2 = b;
						if (b2 == 0)
						{
							LocalCarSfxPlayingBySource[instanceID] = isPlaying;
							continue;
						}
						result = true;
						if (val.loop)
						{
							LocalCarSfxNextLoopEmitAt[instanceID] = unscaledTime + 1.25f;
						}
						string item = $"{b2}|{text}|{text2}";
						if (hashSet.Add(item))
						{
							sfxEvents.Add((b2, text, text2));
						}
					}
					LocalCarSfxPlayingBySource[instanceID] = isPlaying;
				}
				if (LocalCarSfxPlayingBySource.Count > 0)
				{
					List<int> list = new List<int>();
					foreach (KeyValuePair<int, bool> item2 in LocalCarSfxPlayingBySource)
					{
						if (!hashSet2.Contains(item2.Key))
						{
							list.Add(item2.Key);
						}
					}
					for (int j = 0; j < list.Count; j++)
					{
						LocalCarSfxPlayingBySource.Remove(list[j]);
					}
					for (int k = 0; k < list.Count; k++)
					{
						LocalCarSfxNextLoopEmitAt.Remove(list[k]);
					}
				}
				return result;
			}
			catch
			{
				return false;
			}
		}

		private static byte ClassifyCarSfxSource(AudioSource src)
		{
			int num = ScoreLikelyCarSfxSource(src, 1);
			int num2 = ScoreLikelyCarSfxSource(src, 2);
			int num3 = ScoreLikelyCarSfxSource(src, 3);
			int num4 = Mathf.Max(num, Mathf.Max(num2, num3));
			if (num4 < 60)
			{
				return 0;
			}
			if (num4 == num)
			{
				return 1;
			}
			if (num4 == num2)
			{
				return 2;
			}
			return 3;
		}

		private static int ScoreLikelyCarSfxSource(AudioSource src, byte sfxId)
		{
			if ((Object)(object)src == (Object)null)
			{
				return 0;
			}
			int num = 0;
			string value = (((Object)(object)((Component)src).gameObject != (Object)null) ? ((Object)((Component)src).gameObject).name : string.Empty);
			string value2 = (((Object)(object)src.clip != (Object)null) ? ((Object)src.clip).name : string.Empty);
			switch (sfxId)
			{
			case 1:
				if (ContainsAnyKeyword(value, CarHornKeywords))
				{
					num += 100;
				}
				if (ContainsAnyKeyword(value2, CarHornKeywords))
				{
					num += 80;
				}
				if (src.loop)
				{
					num -= 30;
				}
				break;
			case 2:
				if (ContainsAnyKeyword(value, CarSkidKeywords))
				{
					num += 100;
				}
				if (ContainsAnyKeyword(value2, CarSkidKeywords))
				{
					num += 80;
				}
				break;
			case 3:
				if (ContainsAnyKeyword(value, CarCrashKeywords))
				{
					num += 100;
				}
				if (ContainsAnyKeyword(value2, CarCrashKeywords))
				{
					num += 80;
				}
				if (src.loop)
				{
					num -= 40;
				}
				break;
			}
			if (src.spatialBlend > 0.3f)
			{
				num += 10;
			}
			if ((Object)(object)src.clip != (Object)null)
			{
				num += 5;
			}
			return num;
		}

		private static bool ContainsAnyKeyword(string? value, IReadOnlyList<string> keywords)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			for (int i = 0; i < keywords.Count; i++)
			{
				string value2 = keywords[i];
				if (value.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsLikelyHornFallbackPulse(AudioSource src, string clipName, string sourceName)
		{
			if ((Object)(object)src == (Object)null)
			{
				return false;
			}
			if (src.loop)
			{
				return false;
			}
			if (ContainsAnyKeyword(clipName, CarHornKeywords) || ContainsAnyKeyword(sourceName, CarHornKeywords))
			{
				return true;
			}
			if (ContainsAnyKeyword(clipName, CarSkidKeywords) || ContainsAnyKeyword(sourceName, CarSkidKeywords))
			{
				return false;
			}
			if (ContainsAnyKeyword(clipName, CarCrashKeywords) || ContainsAnyKeyword(sourceName, CarCrashKeywords))
			{
				return false;
			}
			if (ContainsAnyKeyword(clipName, CarHornNoiseKeywords) || ContainsAnyKeyword(sourceName, CarHornNoiseKeywords))
			{
				return false;
			}
			AudioClip clip = src.clip;
			if ((Object)(object)clip == (Object)null)
			{
				return false;
			}
			float length = clip.length;
			if (length < 0.05f || length > 2.5f)
			{
				return false;
			}
			return src.volume >= 0.02f;
		}

		internal static bool TryReadHeldPayloadName(out string payloadName)
		{
			payloadName = string.Empty;
			object? obj = TryFindObjectOfTypeByName("sCharacterController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val == null)
			{
				return false;
			}
			try
			{
				Type type = ((object)val).GetType();
				Transform val2 = null;
				object? obj2 = type.GetField("pickupPoint", Any)?.GetValue(val);
				Transform val3 = (Transform)((obj2 is Transform) ? obj2 : null);
				if (val3 != null)
				{
					val2 = val3;
				}
				else
				{
					object? obj3 = type.GetProperty("pickupPoint", Any)?.GetValue(val, null);
					Transform val4 = (Transform)((obj3 is Transform) ? obj3 : null);
					if (val4 != null)
					{
						val2 = val4;
					}
				}
				if ((Object)(object)val2 != (Object)null)
				{
					for (int i = 0; i < val2.childCount; i++)
					{
						Transform child = val2.GetChild(i);
						if (!((Object)(object)child == (Object)null))
						{
							string text = NormalizePayloadName(((Object)child).name);
							if (IsPayloadName(text))
							{
								payloadName = text;
								return true;
							}
						}
					}
				}
				if (TryGetLikelyHeldObjectName(val, out string name))
				{
					name = NormalizePayloadName(name);
					if (IsPayloadName(name))
					{
						payloadName = name;
						return true;
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private static bool TryGetLikelyHeldObjectName(Component controller, out string name)
		{
			name = string.Empty;
			if ((Object)(object)controller == (Object)null)
			{
				return false;
			}
			try
			{
				Type type = ((object)controller).GetType();
				string[] array = new string[4] { "heldItem", "held", "payload", "currentPayload" };
				for (int i = 0; i < array.Length; i++)
				{
					if (TryGetUnityObjectName(type, controller, array[i], out name))
					{
						return true;
					}
				}
				FieldInfo[] fields = type.GetFields(Any);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo == null)
					{
						continue;
					}
					string name2 = fieldInfo.Name;
					if (!string.IsNullOrEmpty(name2))
					{
						string text = name2.ToLowerInvariant();
						if ((text.Contains("held") || text.Contains("payload")) && TryConvertUnityObjectToName(fieldInfo.GetValue(controller), out name))
						{
							return true;
						}
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private static bool TryGetUnityObjectName(Type type, object instance, string memberName, out string name)
		{
			name = string.Empty;
			try
			{
				FieldInfo field = type.GetField(memberName, Any);
				if (field != null)
				{
					return TryConvertUnityObjectToName(field.GetValue(instance), out name);
				}
				PropertyInfo property = type.GetProperty(memberName, Any);
				if (property != null)
				{
					return TryConvertUnityObjectToName(property.GetValue(instance, null), out name);
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool TryConvertUnityObjectToName(object? v, out string name)
		{
			name = string.Empty;
			if (v == null)
			{
				return false;
			}
			GameObject val = (GameObject)((v is GameObject) ? v : null);
			if (val == null)
			{
				Transform val2 = (Transform)((v is Transform) ? v : null);
				if (val2 == null)
				{
					Component val3 = (Component)((v is Component) ? v : null);
					if (val3 != null)
					{
						name = (((Object)(object)val3.gameObject != (Object)null) ? ((Object)val3.gameObject).name : ((Object)val3).name);
						return !string.IsNullOrEmpty(name);
					}
					return false;
				}
				name = ((Object)val2).name;
				return !string.IsNullOrEmpty(name);
			}
			name = ((Object)val).name;
			return !string.IsNullOrEmpty(name);
		}

		private static bool IsPayloadName(string? name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return false;
			}
			return name.TrimStart().StartsWith("PAYLOAD", StringComparison.OrdinalIgnoreCase);
		}

		private static string NormalizePayloadName(string? name)
		{
			if (name == null)
			{
				name = string.Empty;
			}
			name = name.Trim();
			if (name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				name = name.Substring(0, name.Length - "(Clone)".Length).Trim();
			}
			return name;
		}

		internal static bool TryFindPayloadVisualRoot(string payloadName, out Transform visualRoot)
		{
			visualRoot = null;
			payloadName = NormalizePayloadName(payloadName);
			if (string.IsNullOrWhiteSpace(payloadName))
			{
				return false;
			}
			try
			{
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				Transform val = null;
				int num = int.MinValue;
				foreach (GameObject val2 in array)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					string text = NormalizePayloadName(((Object)val2).name);
					if (text.StartsWith("PAYLOAD", StringComparison.OrdinalIgnoreCase))
					{
						int num2 = 0;
						if (string.Equals(text, payloadName, StringComparison.OrdinalIgnoreCase))
						{
							num2 += 200;
						}
						else if (text.IndexOf(payloadName, StringComparison.OrdinalIgnoreCase) >= 0 || payloadName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num2 += 80;
						}
						if (val2.GetComponentsInChildren<Renderer>(true).Length != 0)
						{
							num2 += 20;
						}
						if (val2.GetComponentsInChildren<Collider>(true).Length != 0)
						{
							num2 += 20;
						}
						if (val2.activeInHierarchy)
						{
							num2 += 5;
						}
						if (num2 > num)
						{
							val = val2.transform;
							num = num2;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					visualRoot = val;
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool TryFindLocalCarVisualRoot(out Transform visualRoot)
		{
			visualRoot = null;
			object? obj = TryFindObjectOfTypeByName("sCarController");
			Component val = (Component)((obj is Component) ? obj : null);
			if (val == null)
			{
				return false;
			}
			visualRoot = val.transform;
			return true;
		}

		private static Component? TryFindComponentByTypeName(Component root, string typeName)
		{
			try
			{
				Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
				foreach (Component val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null))
					{
						if (string.Equals(((object)val).GetType().Name, typeName, StringComparison.Ordinal))
						{
							return val;
						}
						if (string.Equals(((object)val).GetType().FullName, typeName, StringComparison.Ordinal))
						{
							return val;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static Transform LiftToReasonableScale(Transform candidate, Transform limitRoot)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Transform val = candidate;
			for (int i = 0; i < 12; i++)
			{
				Vector3 lossyScale = val.lossyScale;
				float num = (lossyScale.x + lossyScale.y + lossyScale.z) / 3f;
				if (num >= 0.35f && num <= 3f)
				{
					return val;
				}
				if ((Object)(object)val.parent == (Object)null)
				{
					return val;
				}
				if ((Object)(object)val == (Object)(object)limitRoot)
				{
					return val;
				}
				val = val.parent;
			}
			return val;
		}

		internal static bool TryApplyCarState(Vector3 pos, Quaternion rot, Vector3 vel, Vector3 angVel)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			object obj = TryFindObjectOfTypeByName("sCarController");
			if (obj == null)
			{
				return false;
			}
			object? obj2 = obj.GetType().GetField("rb", Any)?.GetValue(obj);
			Rigidbody val = (Rigidbody)((obj2 is Rigidbody) ? obj2 : null);
			if (val != null)
			{
				try
				{
					val.position = pos;
					val.rotation = rot;
					val.velocity = vel;
					val.angularVelocity = angVel;
				}
				catch
				{
				}
			}
			Component val2 = (Component)((obj is Component) ? obj : null);
			if (val2 != null)
			{
				val2.transform.position = pos;
				val2.transform.rotation = rot;
			}
			return true;
		}

		internal static IReadOnlyList<(string Name, Vector3 LocalPos, Quaternion LocalRot)>? TryReadCarCargo()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			object obj = TryFindObjectOfTypeByName("sCarController");
			if (obj == null)
			{
				return null;
			}
			object? obj2 = obj.GetType().GetField("payloadPivot", Any)?.GetValue(obj);
			Transform val = (Transform)((obj2 is Transform) ? obj2 : null);
			if (val == null)
			{
				return null;
			}
			List<(string, Vector3, Quaternion)> list = new List<(string, Vector3, Quaternion)>();
			for (int i = 0; i < val.childCount; i++)
			{
				Transform child = val.GetChild(i);
				list.Add((((Object)child).name, child.localPosition, child.localRotation));
			}
			return list;
		}

		internal static bool TryApplyCarCargo(IReadOnlyList<(string Name, Vector3 LocalPos, Quaternion LocalRot)> cargo)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			object obj = TryFindObjectOfTypeByName("sCarController");
			if (obj == null)
			{
				return false;
			}
			object? obj2 = obj.GetType().GetField("payloadPivot", Any)?.GetValue(obj);
			Transform val = (Transform)((obj2 is Transform) ? obj2 : null);
			if (val == null)
			{
				return false;
			}
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal);
			for (int i = 0; i < val.childCount; i++)
			{
				dictionary[((Object)val.GetChild(i)).name] = val.GetChild(i);
			}
			for (int j = 0; j < cargo.Count; j++)
			{
				Transform value = null;
				if (!string.IsNullOrEmpty(cargo[j].Name))
				{
					dictionary.TryGetValue(cargo[j].Name, out value);
				}
				if (value == null)
				{
					value = ((j < val.childCount) ? val.GetChild(j) : null);
				}
				if (!((Object)(object)value == (Object)null))
				{
					value.localPosition = cargo[j].LocalPos;
					value.localRotation = cargo[j].LocalRot;
				}
			}
			return true;
		}

		internal static IReadOnlyList<JobData>? TryReadJobBoardJobs()
		{
			object obj = TryFindObjectOfTypeByName("jobBoard");
			if (obj == null)
			{
				return null;
			}
			if (!(obj.GetType().GetField("jobs", Any)?.GetValue(obj) is IEnumerable enumerable))
			{
				return null;
			}
			List<JobData> list = new List<JobData>();
			foreach (object item2 in enumerable)
			{
				if (item2 != null)
				{
					Type type = item2.GetType();
					JobData item = new JobData
					{
						Name = type.GetField("name", Any)?.GetValue(item2)?.ToString(),
						From = type.GetField("from", Any)?.GetValue(item2)?.ToString(),
						To = type.GetField("to", Any)?.GetValue(item2)?.ToString(),
						StartingCityName = type.GetField("startingCityName", Any)?.GetValue(item2)?.ToString(),
						DestCityName = type.GetField("destCityName", Any)?.GetValue(item2)?.ToString(),
						DestinationIndex = ReadInt(type.GetField("destinationIndex", Any)?.GetValue(item2)),
						PayloadIndex = ReadInt(type.GetField("payloadIndex", Any)?.GetValue(item2)),
						Price = ReadFloat(type.GetField("price", Any)?.GetValue(item2)),
						Mass = ReadFloat(type.GetField("mass", Any)?.GetValue(item2)),
						TimeStart = ReadFloat(type.GetField("timeStart", Any)?.GetValue(item2)),
						IsChallenge = ReadBool(type.GetField("isChallenge", Any)?.GetValue(item2)),
						IsIntercity = ReadBool(type.GetField("isIntercity", Any)?.GetValue(item2)),
						Duration = ReadFloat(type.GetField("duration", Any)?.GetValue(item2)),
						Distance = ReadFloat(type.GetField("distance", Any)?.GetValue(item2))
					};
					list.Add(item);
				}
			}
			return list;
		}

		internal static bool TryApplyJobBoardJobs(IReadOnlyList<JobData> jobs)
		{
			if (_jobApplyDisabled)
			{
				return false;
			}
			object obj = TryFindObjectOfTypeByName("jobBoard");
			if (obj == null)
			{
				return false;
			}
			Type type = obj.GetType();
			Type type2 = type.GetNestedType("Job", Any) ?? FindTypeInAssemblyCSharp("jobBoard+Job") ?? FindTypeInAssemblyCSharp("Job");
			if (type2 == null)
			{
				return false;
			}
			IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type2));
			try
			{
				foreach (JobData job in jobs)
				{
					ConstructorInfo constructor = type2.GetConstructor(Any, null, Type.EmptyTypes, null);
					object obj2 = ((!(constructor != null)) ? FormatterServices.GetUninitializedObject(type2) : constructor.Invoke(Array.Empty<object>()));
					if (obj2 != null)
					{
						SetField(type2, obj2, "name", job.Name);
						SetField(type2, obj2, "from", job.From);
						SetField(type2, obj2, "to", job.To);
						SetField(type2, obj2, "startingCityName", job.StartingCityName);
						SetField(type2, obj2, "destCityName", job.DestCityName);
						SetField(type2, obj2, "destinationIndex", job.DestinationIndex);
						SetField(type2, obj2, "payloadIndex", job.PayloadIndex);
						SetField(type2, obj2, "price", job.Price);
						SetField(type2, obj2, "mass", job.Mass);
						SetField(type2, obj2, "timeStart", job.TimeStart);
						SetField(type2, obj2, "isChallenge", job.IsChallenge);
						SetField(type2, obj2, "isIntercity", job.IsIntercity);
						SetField(type2, obj2, "duration", job.Duration);
						SetField(type2, obj2, "distance", job.Distance);
						list.Add(obj2);
					}
				}
			}
			catch (Exception ex)
			{
				_jobApplyDisabled = true;
				_jobApplyDisabledReason = ex.GetType().Name;
				Plugin.Log.LogWarning((object)("Job sync disabled (cannot construct " + type2.FullName + "). Reason=" + _jobApplyDisabledReason));
				return false;
			}
			FieldInfo field = type.GetField("jobs", Any);
			if (field == null)
			{
				return false;
			}
			try
			{
				field.SetValue(obj, list);
				obj.GetType().GetMethod("UpdateJobCount", Any)?.Invoke(obj, Array.Empty<object>());
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static Dictionary<string, string?> TryReadSaveSystemSnapshot()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			object obj = TryGetSaveSystemInstance();
			if (obj == null)
			{
				return dictionary;
			}
			if (obj.GetType().GetField("data", Any)?.GetValue(obj) is IDictionary dictionary2)
			{
				foreach (DictionaryEntry item in dictionary2)
				{
					if (item.Key is string key)
					{
						dictionary[key] = item.Value?.ToString();
					}
				}
			}
			return dictionary;
		}

		internal static bool TryApplySaveKey(string key, string value)
		{
			object obj = TryGetSaveSystemInstance();
			if (obj == null)
			{
				return false;
			}
			MethodInfo method = obj.GetType().GetMethod("SetString", Any);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(obj, new object[2] { key, value });
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryDeleteSaveKey(string key)
		{
			object obj = TryGetSaveSystemInstance();
			if (obj == null)
			{
				return false;
			}
			MethodInfo method = obj.GetType().GetMethod("DeleteKey", Any);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(obj, new object[1] { key });
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryReadDayNightTime(out float time)
		{
			time = 0f;
			object obj = TryFindObjectOfTypeByName("sDayNightCycle");
			if (obj == null)
			{
				return false;
			}
			FieldInfo field = obj.GetType().GetField("time", Any);
			if (field == null)
			{
				return false;
			}
			if (field.GetValue(obj) is float num)
			{
				time = num;
				return true;
			}
			return false;
		}

		internal static bool TryApplyDayNightTime(float time)
		{
			object obj = TryFindObjectOfTypeByName("sDayNightCycle");
			if (obj == null)
			{
				return false;
			}
			FieldInfo field = obj.GetType().GetField("time", Any);
			if (field == null)
			{
				return false;
			}
			try
			{
				field.SetValue(obj, time);
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryReadHudMoney(out int money)
		{
			money = 0;
			object obj = TryFindObjectOfTypeByName("sHUD");
			if (obj == null)
			{
				return false;
			}
			FieldInfo field = obj.GetType().GetField("money", Any);
			if (field == null)
			{
				return false;
			}
			object value = field.GetValue(obj);
			if (value is int num)
			{
				money = num;
				return true;
			}
			if (value is float num2)
			{
				money = Mathf.RoundToInt(num2);
				return true;
			}
			return false;
		}

		internal static bool TryApplyHudMoney(int money)
		{
			object obj = TryFindObjectOfTypeByName("sHUD");
			if (obj == null)
			{
				return false;
			}
			FieldInfo field = obj.GetType().GetField("money", Any);
			if (field == null)
			{
				return false;
			}
			try
			{
				if (field.FieldType == typeof(int))
				{
					field.SetValue(obj, money);
					return true;
				}
				if (field.FieldType == typeof(float))
				{
					field.SetValue(obj, (float)money);
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static object? TryGetSaveSystemInstance()
		{
			Type type = FindTypeInAssemblyCSharp("sSaveSystem");
			if (type == null)
			{
				return null;
			}
			return type.GetField("instance", Any)?.GetValue(null);
		}

		private static object? TryFindObjectOfTypeByName(string typeName)
		{
			Type type = FindTypeInAssemblyCSharp(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				MethodInfo method = typeof(Object).GetMethod("FindObjectOfType", Any, null, new Type[1] { typeof(Type) }, null);
				if (method == null)
				{
					return null;
				}
				return method.Invoke(null, new object[1] { type });
			}
			catch
			{
				return null;
			}
		}

		internal static bool TryApplyPlayerPrefString(string key, string value)
		{
			try
			{
				if (string.IsNullOrEmpty(key))
				{
					return false;
				}
				PlayerPrefs.SetString(key, value ?? string.Empty);
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool TryDeletePlayerPref(string key)
		{
			try
			{
				if (string.IsNullOrEmpty(key))
				{
					return false;
				}
				PlayerPrefs.DeleteKey(key);
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static void TrySavePlayerPrefs()
		{
			try
			{
				PlayerPrefs.Save();
			}
			catch
			{
			}
		}

		internal static bool TryAutoEnterWorldFromMenu(string? preferredSaveId, out string reason)
		{
			reason = string.Empty;
			if (preferredSaveId == null)
			{
				preferredSaveId = string.Empty;
			}
			string slotNameHint = TryExtractSaveSlotName(preferredSaveId) ?? preferredSaveId;
			int? slotIndexHint = TryExtractSaveSlotIndex(preferredSaveId);
			if (TryClickUiToolkitButton(out string reason2))
			{
				reason = reason2;
				return true;
			}
			if (TryClickMenuButton(out string reason3))
			{
				reason = reason3;
				return true;
			}
			string[] array = new string[8] { "sMainMenu", "sMenu", "sMenuManager", "sSaveMenu", "sSaveSelect", "sSaveSelectMenu", "sSceneLoader", "sGameManager" };
			string[] array2 = new string[12]
			{
				"Continue", "ContinueGame", "OnContinue", "OnContinueButton", "Play", "OnPlay", "OnPlayButton", "StartGame", "Load", "LoadGame",
				"LoadSave", "LoadFromSave"
			};
			for (int i = 0; i < array.Length; i++)
			{
				object obj = TryFindObjectOfTypeByName(array[i]);
				if (obj == null)
				{
					continue;
				}
				Type type = obj.GetType();
				MethodInfo[] methods = type.GetMethods(Any);
				foreach (string b in array2)
				{
					foreach (MethodInfo methodInfo in methods)
					{
						if (methodInfo == null || !string.Equals(methodInfo.Name, b, StringComparison.OrdinalIgnoreCase))
						{
							continue;
						}
						try
						{
							if (methodInfo.GetParameters().Length != 0)
							{
								continue;
							}
							methodInfo.Invoke(obj, null);
							reason = "Invoked " + type.Name + "." + methodInfo.Name + "()";
							return true;
						}
						catch
						{
						}
					}
				}
			}
			if (TryInvokeLikelyMenuHandler(preferredSaveId, out string reason4))
			{
				reason = reason4;
				return true;
			}
			if (TryInvokeSubstringHeuristic(slotNameHint, slotIndexHint, out string reason5))
			{
				reason = reason5;
				return true;
			}
			reason = "No known menu/loader method found. UGUI=" + reason3 + ". UITK=" + reason2 + ". Scan=" + reason4;
			return false;
		}

		private static int? TryExtractSaveSlotIndex(string preferredSaveId)
		{
			if (string.IsNullOrEmpty(preferredSaveId))
			{
				return null;
			}
			try
			{
				Match match = Regex.Match(preferredSaveId, "file\\s*(\\d+)", RegexOptions.IgnoreCase);
				if (match.Success && match.Groups.Count > 1 && int.TryParse(match.Groups[1].Value, out var result))
				{
					return result;
				}
			}
			catch
			{
			}
			return null;
		}

		private static string? TryExtractSaveSlotName(string preferredSaveId)
		{
			int? num = TryExtractSaveSlotIndex(preferredSaveId);
			if (!num.HasValue)
			{
				return null;
			}
			return $"file{num.Value}";
		}

		private static bool TryClickMenuButton(out string reason)
		{
			reason = string.Empty;
			Type type = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					type = assembly.GetTypes().FirstOrDefault((Type t) => string.Equals(t.FullName, "UnityEngine.UI.Button", StringComparison.Ordinal));
					if (type != null)
					{
						break;
					}
				}
				catch
				{
				}
			}
			if (type == null)
			{
				reason = "UnityEngine.UI.Button type not found";
				return false;
			}
			Object[] array = TryResourcesFindObjectsOfTypeAll(type);
			if (array == null || array.Length == 0)
			{
				reason = "No UI buttons found";
				return false;
			}
			(Object, Component, string, int)? tuple = null;
			foreach (Object val in array)
			{
				if (val == (Object)null)
				{
					continue;
				}
				Component val2 = (Component)(object)((val is Component) ? val : null);
				if (val2 == null)
				{
					continue;
				}
				string text = string.Empty;
				try
				{
					text = TryGetButtonLabelText(val2) ?? string.Empty;
				}
				catch
				{
				}
				string text2 = ((((Object)(object)val2.gameObject != (Object)null) ? ((Object)val2.gameObject).name : string.Empty) + " " + text).ToLowerInvariant();
				if (text2.Length != 0)
				{
					int num = ScoreMenuAction(text2);
					if (num > 0 && (!tuple.HasValue || num > tuple.Value.Item4))
					{
						tuple = (val, val2, text, num);
					}
				}
			}
			if (tuple.HasValue)
			{
				try
				{
					Object item = tuple.Value.Item1;
					Component item2 = tuple.Value.Item2;
					string item3 = tuple.Value.Item3;
					object obj3 = ((object)item).GetType().GetProperty("onClick", Any)?.GetValue(item);
					if (obj3 != null)
					{
						MethodInfo method = obj3.GetType().GetMethod("Invoke", Any, null, Type.EmptyTypes, null);
						if (method != null)
						{
							method.Invoke(obj3, null);
							string arg = (((Object)(object)item2.gameObject != (Object)null) ? ((Object)item2.gameObject).name : "(null)");
							reason = $"Clicked UI Button '{arg}' label='{item3}' score={tuple.Value.Item4}";
							return true;
						}
					}
				}
				catch
				{
				}
			}
			if (!_loggedMenuButtonDump)
			{
				_loggedMenuButtonDump = true;
				try
				{
					List<string> list = new List<string>();
					for (int k = 0; k < array.Length; k++)
					{
						if (list.Count >= 12)
						{
							break;
						}
						Object obj5 = array[k];
						Component val3 = (Component)(object)((obj5 is Component) ? obj5 : null);
						if (val3 != null)
						{
							string text3 = (((Object)(object)val3.gameObject != (Object)null) ? ((Object)val3.gameObject).name : string.Empty);
							string text4 = string.Empty;
							try
							{
								text4 = TryGetButtonLabelText(val3) ?? string.Empty;
							}
							catch
							{
							}
							if (!string.IsNullOrWhiteSpace(text3) || !string.IsNullOrWhiteSpace(text4))
							{
								list.Add(text3 + ":'" + text4 + "'");
							}
						}
					}
					if (list.Count > 0)
					{
						reason = string.Format("No matching UI menu button found (total={0}). Samples: {1}", array.Length, string.Join(" | ", list));
					}
					else
					{
						reason = $"No matching UI menu button found (total={array.Length})";
					}
				}
				catch
				{
					reason = "No matching UI menu button found";
				}
			}
			else
			{
				reason = "No matching UI menu button found";
			}
			return false;
		}

		private static int ScoreMenuAction(string hay)
		{
			if (string.IsNullOrWhiteSpace(hay))
			{
				return 0;
			}
			if (hay.Contains("new") || hay.Contains("нов") || hay.Contains("с нуля") || hay.Contains("new game") || hay.Contains("новая"))
			{
				return 0;
			}
			if (hay.Contains("continue") || hay.Contains("продолж"))
			{
				return 120;
			}
			if (hay.Contains("resume"))
			{
				return 110;
			}
			if (hay.Contains("load") || hay.Contains("загруз"))
			{
				return 100;
			}
			if (hay.Contains("play") || hay.Contains("играть"))
			{
				return 90;
			}
			if (hay.Contains("start game") || hay.Contains("startgame"))
			{
				return 80;
			}
			if (hay.Contains("start") || hay.Contains("начать") || hay.Contains("старт"))
			{
				return 60;
			}
			return 0;
		}

		private static bool TryClickUiToolkitButton(out string reason)
		{
			reason = string.Empty;
			Type type = FindTypeAnyAssembly("UnityEngine.UIElements.UIDocument") ?? FindTypeAnyAssembly("UnityEngine.UIElements.UIDocumentBehaviour");
			Type type2 = FindTypeAnyAssembly("UnityEngine.UIElements.Button");
			if (type == null || type2 == null)
			{
				reason = "UI Toolkit types not found";
				return false;
			}
			Object[] array = TryResourcesFindObjectsOfTypeAll(type);
			if (array == null || array.Length == 0)
			{
				reason = "No UIDocument found";
				return false;
			}
			string[] keys = new string[13]
			{
				"continue", "resume", "play", "start game", "startgame", "load", "load game", "loadgame", "продолж", "играть",
				"начать", "старт", "загруз"
			};
			foreach (Object obj in array)
			{
				Component val = (Component)(object)((obj is Component) ? obj : null);
				if (val != null && !((Object)(object)val == (Object)null))
				{
					object obj2 = null;
					try
					{
						obj2 = ((object)val).GetType().GetProperty("rootVisualElement", Any)?.GetValue(val, null);
					}
					catch
					{
					}
					if (obj2 != null && TryFindAndClickUiToolkitButton(obj2, type2, keys, out string reason2))
					{
						reason = reason2;
						return true;
					}
				}
			}
			if (!_loggedUiToolkitButtonDump)
			{
				_loggedUiToolkitButtonDump = true;
				try
				{
					List<string> list = new List<string>();
					int totalButtons = 0;
					foreach (Object obj4 in array)
					{
						Component val2 = (Component)(object)((obj4 is Component) ? obj4 : null);
						if (val2 == null)
						{
							continue;
						}
						object obj5 = null;
						try
						{
							obj5 = ((object)val2).GetType().GetProperty("rootVisualElement", Any)?.GetValue(val2, null);
						}
						catch
						{
						}
						if (obj5 != null)
						{
							CollectUiToolkitButtonSamples(obj5, type2, list, ref totalButtons, 14);
							if (list.Count >= 14)
							{
								break;
							}
						}
					}
					if (totalButtons > 0)
					{
						reason = string.Format("No matching UI Toolkit button found (docs={0}, totalButtons~={1}). Samples: {2}", array.Length, totalButtons, string.Join(" | ", list));
					}
					else
					{
						reason = $"No matching UI Toolkit button found (docs={array.Length}, totalButtons~=0)";
					}
				}
				catch
				{
					reason = "No matching UI Toolkit button found";
				}
			}
			else
			{
				reason = "No matching UI Toolkit button found";
			}
			return false;
		}

		private static void CollectUiToolkitButtonSamples(object rootVisualElement, Type buttonType, List<string> samples, ref int totalButtons, int maxSamples)
		{
			Stack<object> stack = new Stack<object>();
			stack.Push(rootVisualElement);
			while (stack.Count > 0)
			{
				object obj = stack.Pop();
				if (obj == null)
				{
					continue;
				}
				Type type = obj.GetType();
				if (buttonType.IsAssignableFrom(type))
				{
					totalButtons++;
					if (samples.Count < maxSamples)
					{
						string text = TryGetStringProp(obj, "name") ?? string.Empty;
						string text2 = TryGetStringProp(obj, "text") ?? string.Empty;
						if (!string.IsNullOrWhiteSpace(text) || !string.IsNullOrWhiteSpace(text2))
						{
							samples.Add(text + ":'" + text2 + "'");
						}
					}
				}
				try
				{
					MethodInfo method = type.GetMethod("Children", Any, null, Type.EmptyTypes, null);
					if (!(method != null) || !(method.Invoke(obj, null) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							stack.Push(item);
						}
					}
				}
				catch
				{
				}
			}
		}

		private static bool TryFindAndClickUiToolkitButton(object rootVisualElement, Type buttonType, string[] keys, out string reason)
		{
			reason = string.Empty;
			Stack<object> stack = new Stack<object>();
			stack.Push(rootVisualElement);
			(object, string, string, int)? tuple = null;
			while (stack.Count > 0)
			{
				object obj = stack.Pop();
				if (obj == null)
				{
					continue;
				}
				Type type = obj.GetType();
				if (buttonType.IsAssignableFrom(type))
				{
					string text = TryGetStringProp(obj, "name") ?? string.Empty;
					string text2 = TryGetStringProp(obj, "text") ?? string.Empty;
					string text3 = (text + " " + text2).ToLowerInvariant();
					bool flag = false;
					for (int i = 0; i < keys.Length; i++)
					{
						if (text3.Contains(keys[i].ToLowerInvariant()))
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						int num = ScoreMenuAction(text3);
						if (num > 0 && (!tuple.HasValue || num > tuple.Value.Item4))
						{
							tuple = (obj, text, text2, num);
						}
					}
				}
				try
				{
					MethodInfo method = type.GetMethod("Children", Any, null, Type.EmptyTypes, null);
					if (!(method != null) || !(method.Invoke(obj, null) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							stack.Push(item);
						}
					}
				}
				catch
				{
				}
			}
			if (tuple.HasValue && TryInvokeUiToolkitButtonClick(tuple.Value.Item1))
			{
				reason = $"Clicked UI Toolkit Button name='{tuple.Value.Item2}' text='{tuple.Value.Item3}' score={tuple.Value.Item4}";
				return true;
			}
			return false;
		}

		private static bool TryInvokeUiToolkitButtonClick(object button)
		{
			try
			{
				Type type = button.GetType();
				MethodInfo method = type.GetMethod("Click", Any, null, Type.EmptyTypes, null);
				if (method != null)
				{
					method.Invoke(button, null);
					return true;
				}
				object obj = type.GetProperty("clickable", Any)?.GetValue(button, null);
				if (obj != null)
				{
					Type type2 = obj.GetType();
					MethodInfo method2 = type2.GetMethod("Invoke", Any, null, Type.EmptyTypes, null);
					if (method2 != null)
					{
						method2.Invoke(obj, null);
						return true;
					}
					MethodInfo method3 = type2.GetMethod("SimulateSingleClick", Any);
					if (method3 != null)
					{
						ParameterInfo[] parameters = method3.GetParameters();
						if (parameters.Length == 0)
						{
							method3.Invoke(obj, null);
							return true;
						}
						if (parameters.Length == 1)
						{
							method3.Invoke(obj, new object[1]);
							return true;
						}
					}
				}
				if ((type.GetField("clicked", Any) ?? type.GetField("<clicked>k__BackingField", Any))?.GetValue(button) is Delegate @delegate)
				{
					@delegate.DynamicInvoke();
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static string? TryGetStringProp(object o, string prop)
		{
			try
			{
				if (o.GetType().GetProperty(prop, Any)?.GetValue(o, null) is string result)
				{
					return result;
				}
			}
			catch
			{
			}
			return null;
		}

		private static Object[]? TryResourcesFindObjectsOfTypeAll(Type t)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			try
			{
				MethodInfo method = typeof(Resources).GetMethod("FindObjectsOfTypeAll", Any, null, new Type[1] { typeof(Type) }, null);
				if (method == null)
				{
					return null;
				}
				if (!(method.Invoke(null, new object[1] { t }) is Array array))
				{
					return null;
				}
				Object[] array2 = (Object[])(object)new Object[array.Length];
				for (int i = 0; i < array.Length; i++)
				{
					array2[i] = (Object)array.GetValue(i);
				}
				return array2;
			}
			catch
			{
				return null;
			}
		}

		private static string? TryGetButtonLabelText(Component button)
		{
			Type type = FindTypeAnyAssembly("UnityEngine.UI.Text") ?? FindTypeAnyAssembly("TMPro.TextMeshProUGUI");
			if (type == null)
			{
				return null;
			}
			try
			{
				Component[] componentsInChildren = button.GetComponentsInChildren<Component>(true);
				foreach (Component val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null) && type.IsInstanceOfType(val) && ((object)val).GetType().GetProperty("text", Any)?.GetValue(val) is string text && !string.IsNullOrWhiteSpace(text))
					{
						return text.Trim();
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static Type? FindTypeAnyAssembly(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(fullName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static bool TryInvokeLikelyMenuHandler(string preferredSaveId, out string reason)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			reason = string.Empty;
			TryExtractSaveSlotName(preferredSaveId);
			TryExtractSaveSlotIndex(preferredSaveId);
			Object[] array = TryResourcesFindObjectsOfTypeAll(typeof(MonoBehaviour));
			if (array == null || array.Length == 0)
			{
				reason = "No MonoBehaviours found";
				return false;
			}
			string[] array2 = new string[17]
			{
				"Continue", "ContinueGame", "OnContinue", "OnContinuePressed", "OnContinueButton", "Play", "OnPlay", "OnPlayPressed", "OnPlayButton", "StartGame",
				"OnStart", "OnStartPressed", "Load", "LoadGame", "LoadSave", "LoadFromSave", "LoadLast"
			};
			foreach (Object obj in array)
			{
				MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
				if (val == null || string.Equals(((object)val).GetType().Name, "ScreenSystem", StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				try
				{
					if (((Behaviour)val).isActiveAndEnabled && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
					{
						Scene scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).isLoaded)
						{
							goto IL_0151;
						}
					}
				}
				catch
				{
					goto IL_0151;
				}
				continue;
				IL_0151:
				string name = ((object)val).GetType().Name;
				string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : string.Empty);
				string text2 = (name + " " + text).ToLowerInvariant();
				if (!text2.Contains("menu") && !text2.Contains("main") && !text2.Contains("title") && !text2.Contains("save") && !text2.Contains("select") && !text2.Contains("loader") && !text2.Contains("scene") && !text2.Contains("start") && !text2.Contains("ui") && !text2.Contains("canvas") && !text2.Contains("front"))
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = ((object)val).GetType().GetMethods(Any);
				}
				catch
				{
					continue;
				}
				foreach (string b in array2)
				{
					foreach (MethodInfo methodInfo in methods)
					{
						if (methodInfo == null || !string.Equals(methodInfo.Name, b, StringComparison.OrdinalIgnoreCase))
						{
							continue;
						}
						ParameterInfo[] parameters = methodInfo.GetParameters();
						try
						{
							if (parameters.Length == 0)
							{
								methodInfo.Invoke(val, null);
								reason = "Invoked " + ((object)val).GetType().Name + "." + methodInfo.Name + "()";
								return true;
							}
							if (parameters.Length == 1)
							{
								Type parameterType = parameters[0].ParameterType;
								if (parameterType.FullName != null && parameterType.FullName.Contains("EventSystems", StringComparison.OrdinalIgnoreCase))
								{
									methodInfo.Invoke(val, new object[1]);
									reason = "Invoked " + ((object)val).GetType().Name + "." + methodInfo.Name + "(eventData:null)";
									return true;
								}
								if (parameterType == typeof(object) || typeof(Object).IsAssignableFrom(parameterType))
								{
									methodInfo.Invoke(val, new object[1]);
									reason = "Invoked " + ((object)val).GetType().Name + "." + methodInfo.Name + "(null)";
									return true;
								}
							}
						}
						catch
						{
						}
					}
				}
			}
			reason = "No likely menu handler found in scan";
			return false;
		}

		private static bool TryInvokeSubstringHeuristic(string slotNameHint, int? slotIndexHint, out string reason)
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			reason = string.Empty;
			Object[] array = TryResourcesFindObjectsOfTypeAll(typeof(MonoBehaviour));
			if (array == null || array.Length == 0)
			{
				reason = "No MonoBehaviours found (heuristic)";
				return false;
			}
			(string, int)[] array2 = new(string, int)[6]
			{
				("continue", 120),
				("resume", 110),
				("load", 100),
				("playsave", 95),
				("play", 90),
				("startgame", 85)
			};
			(MonoBehaviour, MethodInfo, int)? tuple = null;
			foreach (Object obj in array)
			{
				MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
				if (val == null || string.Equals(((object)val).GetType().Name, "ScreenSystem", StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				try
				{
					if (((Behaviour)val).isActiveAndEnabled && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
					{
						Scene scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).isLoaded)
						{
							goto IL_0136;
						}
					}
				}
				catch
				{
				}
				continue;
				IL_0136:
				string name = ((object)val).GetType().Name;
				string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : string.Empty);
				string text2 = (name + " " + text).ToLowerInvariant();
				if (!text2.Contains("menu") && !text2.Contains("ui") && !text2.Contains("canvas") && !text2.Contains("title") && !text2.Contains("front") && !text2.Contains("save") && !text2.Contains("select"))
				{
					continue;
				}
				MethodInfo[] methods;
				try
				{
					methods = ((object)val).GetType().GetMethods(Any);
				}
				catch
				{
					continue;
				}
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo == null || methodInfo.IsSpecialName || methodInfo.IsGenericMethod || methodInfo.ReturnType != typeof(void))
					{
						continue;
					}
					string name2 = methodInfo.Name;
					if (string.IsNullOrEmpty(name2) || string.Equals(name2, "Awake", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "Start", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "Update", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "FixedUpdate", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "LateUpdate", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "OnEnable", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "OnDisable", StringComparison.OrdinalIgnoreCase) || string.Equals(name2, "OnGUI", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					string text3 = name2.ToLowerInvariant();
					int num = 0;
					for (int k = 0; k < array2.Length; k++)
					{
						if (text3.Contains(array2[k].Item1))
						{
							num = Math.Max(num, array2[k].Item2);
							break;
						}
					}
					if (num == 0)
					{
						continue;
					}
					if (text2.Contains("mainmenu") || text2.Contains("savemenu") || text2.Contains("save") || text2.Contains("sceneloader"))
					{
						num += 15;
					}
					if (text3.StartsWith("on", StringComparison.Ordinal))
					{
						num += 5;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length > 1)
					{
						continue;
					}
					if (parameters.Length == 1)
					{
						Type parameterType = parameters[0].ParameterType;
						bool flag = parameterType == typeof(object) || typeof(Object).IsAssignableFrom(parameterType);
						if (!flag && parameterType.FullName != null)
						{
							flag = parameterType.FullName.Contains("EventSystems", StringComparison.OrdinalIgnoreCase);
						}
						if (!flag)
						{
							continue;
						}
					}
					if (!tuple.HasValue || num > tuple.Value.Item3)
					{
						tuple = (val, methodInfo, num);
					}
				}
			}
			if (!tuple.HasValue)
			{
				reason = "No heuristic candidate found";
				return false;
			}
			try
			{
				MonoBehaviour item = tuple.Value.Item1;
				MethodInfo item2 = tuple.Value.Item2;
				if (string.Equals(((object)item).GetType().Name, "ScreenSystem", StringComparison.OrdinalIgnoreCase) && item2.Name.IndexOf("resume", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					reason = "Skipped unsafe ScreenSystem.Resume heuristic";
					return false;
				}
				ParameterInfo[] parameters2 = item2.GetParameters();
				if (parameters2.Length == 0)
				{
					item2.Invoke(item, null);
					reason = $"Heuristic invoke {((object)item).GetType().Name}.{item2.Name}() score={tuple.Value.Item3}";
					return true;
				}
				Type parameterType2 = parameters2[0].ParameterType;
				if (parameterType2.FullName != null && parameterType2.FullName.Contains("EventSystems", StringComparison.OrdinalIgnoreCase))
				{
					item2.Invoke(item, new object[1]);
					reason = $"Heuristic invoke {((object)item).GetType().Name}.{item2.Name}(eventData:null) score={tuple.Value.Item3}";
					return true;
				}
				item2.Invoke(item, new object[1]);
				reason = $"Heuristic invoke {((object)item).GetType().Name}.{item2.Name}(null) score={tuple.Value.Item3}";
				return true;
			}
			catch
			{
				reason = "Heuristic invoke failed";
				return false;
			}
		}

		private static Type? FindTypeInAssemblyCSharp(string typeName)
		{
			string typeName2 = typeName;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (string.Equals(assembly.GetName().Name, "Assembly-CSharp", StringComparison.Ordinal))
				{
					return assembly.GetTypes().FirstOrDefault((Type t) => string.Equals(t.Name, typeName2, StringComparison.Ordinal) || string.Equals(t.FullName, typeName2, StringComparison.Ordinal));
				}
			}
			return null;
		}

		private static Transform? FindBestVisualRoot(Transform root)
		{
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				return null;
			}
			Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((Object)((Component)val).gameObject).name;
				if (!string.IsNullOrEmpty(name) && name.StartsWith("EasyDeliveryCoLanCoop.", StringComparison.Ordinal))
				{
					continue;
				}
				Transform val2 = ((Component)val).transform;
				if (!((Object)(object)val2 == (Object)(object)root))
				{
					while ((Object)(object)val2 != (Object)(object)root && (Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)root)
					{
						val2 = val2.parent;
					}
					if ((Object)(object)val2.parent == (Object)null)
					{
						val2 = root;
					}
				}
				if (!dictionary.TryGetValue(val2, out var value))
				{
					dictionary[val2] = 1;
				}
				else
				{
					dictionary[val2] = value + 1;
				}
			}
			Transform val3 = null;
			int num = 0;
			foreach (KeyValuePair<Transform, int> item in dictionary)
			{
				if (item.Value > num)
				{
					val3 = item.Key;
					num = item.Value;
				}
			}
			return val3 ?? root;
		}

		private static int ReadInt(object? v)
		{
			if (v is int)
			{
				return (int)v;
			}
			if (v is short)
			{
				return (short)v;
			}
			if (v is byte)
			{
				return (byte)v;
			}
			if (v is float num)
			{
				return Mathf.RoundToInt(num);
			}
			return 0;
		}

		private static float ReadFloat(object? v)
		{
			if (v is float)
			{
				return (float)v;
			}
			if (v is int num)
			{
				return num;
			}
			if (v is double num2)
			{
				return (float)num2;
			}
			return 0f;
		}

		private static bool ReadBool(object? v)
		{
			if (v is bool)
			{
				return (bool)v;
			}
			return false;
		}

		private static void SetField(Type t, object instance, string fieldName, object? value)
		{
			FieldInfo field = t.GetField(fieldName, Any);
			if (field == null)
			{
				return;
			}
			try
			{
				if (field.FieldType == typeof(string))
				{
					field.SetValue(instance, value?.ToString() ?? string.Empty);
				}
				else if (field.FieldType == typeof(int) && value is int num)
				{
					field.SetValue(instance, num);
				}
				else if (field.FieldType == typeof(float) && value is float num2)
				{
					field.SetValue(instance, num2);
				}
				else if (field.FieldType == typeof(bool) && value is bool)
				{
					bool flag = (bool)value;
					field.SetValue(instance, flag);
				}
			}
			catch
			{
			}
		}
	}
	internal static class MaterialUtil
	{
		private static Material? _cached;

		private static float _nextRescanAt;

		internal static Material? GetSceneMaterialFallback()
		{
			if ((Object)(object)_cached != (Object)null)
			{
				return _cached;
			}
			if (Time.unscaledTime < _nextRescanAt)
			{
				return null;
			}
			_nextRescanAt = Time.unscaledTime + 1f;
			if (GameAccess.TryFindLocalCarVisualRoot(out Transform visualRoot))
			{
				Material val = FindFirstMaterial(visualRoot);
				if ((Object)(object)val != (Object)null)
				{
					return _cached = val;
				}
			}
			if (GameAccess.TryFindLocalPlayerVisualRoot(out Transform visualRoot2))
			{
				Material val2 = FindFirstMaterial(visualRoot2);
				if ((Object)(object)val2 != (Object)null)
				{
					return _cached = val2;
				}
			}
			Renderer val3 = Object.FindObjectOfType<Renderer>();
			if ((Object)(object)val3 != (Object)null)
			{
				Material[] sharedMaterials = val3.sharedMaterials;
				if (sharedMaterials != null)
				{
					for (int i = 0; i < sharedMaterials.Length; i++)
					{
						if ((Object)(object)sharedMaterials[i] != (Object)null)
						{
							return _cached = sharedMaterials[i];
						}
					}
				}
			}
			return null;
		}

		private static Material? FindFirstMaterial(Transform root)
		{
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null)
				{
					continue;
				}
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if ((Object)(object)sharedMaterials[j] != (Object)null)
					{
						return sharedMaterials[j];
					}
				}
			}
			return null;
		}
	}
	internal static class MeshOnlyClone
	{
		internal static GameObject? TryCreateMeshRendererHierarchyPrefab(Transform sourceRoot)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if ((Object)(object)sourceRoot == (Object)null)
			{
				return null;
			}
			try
			{
				GameObject val = new GameObject("EasyDeliveryCoLanCoop.MeshOnlyPrefab." + ((Object)sourceRoot).name);
				((Object)val).hideFlags = (HideFlags)52;
				CopyRecursive(sourceRoot, val.transform);
				val.SetActive(false);
				return val;
			}
			catch
			{
				return null;
			}
		}

		private static void CopyRecursive(Transform src, Transform dstParent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(((Object)src).name);
			((Object)val).hideFlags = (HideFlags)52;
			val.transform.SetParent(dstParent, false);
			val.transform.localPosition = src.localPosition;
			val.transform.localRotation = src.localRotation;
			val.transform.localScale = src.localScale;
			MeshFilter component = ((Component)src).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)src).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				val.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
			}
			if ((Object)(object)component2 != (Object)null)
			{
				MeshRenderer val2 = val.AddComponent<MeshRenderer>();
				Material[] sharedMaterials = ((Renderer)component2).sharedMaterials;
				Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
				for (int i = 0; i < sharedMaterials.Length; i++)
				{
					object obj = array;
					int num = i;
					obj = (object)(((Object)(object)sharedMaterials[i] != (Object)null) ? new Material(sharedMaterials[i]) : ((Material)null));
					((object[])obj)[num] = obj;
				}
				((Renderer)val2).sharedMaterials = array;
				((Renderer)val2).shadowCastingMode = ((Renderer)component2).shadowCastingMode;
				((Renderer)val2).receiveShadows = ((Renderer)component2).receiveShadows;
				((Renderer)val2).lightProbeUsage = ((Renderer)component2).lightProbeUsage;
				((Renderer)val2).reflectionProbeUsage = ((Renderer)component2).reflectionProbeUsage;
			}
			for (int j = 0; j < src.childCount; j++)
			{
				CopyRecursive(src.GetChild(j), val.transform);
			}
		}
	}
	internal sealed class MoneyUiFormatter : MonoBehaviour
	{
		private static readonly BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private object? _hud;

		private object? _moneyText;

		private PropertyInfo? _textProp;

		private float _nextResolveAt;

		private float _nextUpdateAt;

		private void Update()
		{
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= _nextResolveAt)
			{
				_nextResolveAt = unscaledTime + 2f;
				ResolveTargets();
			}
			if (_moneyText == null || _textProp == null || unscaledTime < _nextUpdateAt)
			{
				return;
			}
			_nextUpdateAt = unscaledTime + 0.2f;
			if (!GameAccess.TryReadHudMoney(out var money))
			{
				return;
			}
			string replacement = ((float)money).ToString("F2", CultureInfo.CurrentCulture);
			try
			{
				string obj = (_textProp.GetValue(_moneyText, null) as string) ?? string.Empty;
				string text = ReplaceNumberSegment(obj, replacement);
				if (!string.Equals(obj, text, StringComparison.Ordinal))
				{
					_textProp.SetValue(_moneyText, text, null);
				}
			}
			catch
			{
				_moneyText = null;
				_textProp = null;
			}
		}

		private void ResolveTargets()
		{
			if (_hud == null)
			{
				_hud = TryFindObjectOfTypeByName("sHUD");
			}
			if (_hud == null)
			{
				_moneyText = null;
				_textProp = null;
			}
			else
			{
				if (_moneyText != null && _textProp != null)
				{
					return;
				}
				Type type = _hud.GetType();
				(object, PropertyInfo)? tuple = FindMoneyTextOnObject(_hud, type);
				if (tuple.HasValue)
				{
					_moneyText = tuple.Value.Item1;
					_textProp = tuple.Value.Item2;
					return;
				}
				object? hud = _hud;
				Component val = (Component)((hud is Component) ? hud : null);
				if (val == null)
				{
					return;
				}
				if (!GameAccess.TryReadHudMoney(out var money))
				{
					money = 0;
				}
				string value = money.ToString(CultureInfo.CurrentCulture);
				Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
				foreach (Component val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null || !TryGetWritableTextProperty(((object)val2).GetType(), out PropertyInfo prop))
					{
						continue;
					}
					try
					{
						string text = prop.GetValue(val2, null) as string;
						if (!string.IsNullOrWhiteSpace(text))
						{
							string text2 = ((Object)val2.gameObject).name?.ToLowerInvariant() ?? string.Empty;
							if (text2.Contains("money") || text2.Contains("cash") || text2.Contains("coins"))
							{
								_moneyText = val2;
								_textProp = prop;
								break;
							}
							if (text.Contains(value, StringComparison.Ordinal))
							{
								_moneyText = val2;
								_textProp = prop;
								break;
							}
						}
					}
					catch
					{
					}
				}
			}
		}

		private static (object Target, PropertyInfo TextProp)? FindMoneyTextOnObject(object instance, Type t)
		{
			FieldInfo[] fields = t.GetFields(Any);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo == null) && !string.IsNullOrEmpty(fieldInfo.Name) && fieldInfo.Name.ToLowerInvariant().Contains("money"))
				{
					object value;
					try
					{
						value = fieldInfo.GetValue(instance);
					}
					catch
					{
						continue;
					}
					if (value != null && TryGetWritableTextProperty(value.GetType(), out PropertyInfo prop))
					{
						return (value, prop);
					}
				}
			}
			PropertyInfo[] properties