Decompiled source of Coins v1.0.0

EmpressCoin.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
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("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EmpressCoin")]
[assembly: AssemblyTitle("EmpressCoin")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EmpressCoin
{
	internal static class EmpressCoinAccess
	{
		private delegate bool EmpressRunIsLevelDelegate();

		private delegate int EmpressStatGetRunCurrencyDelegate();

		private delegate int EmpressStatSetRunCurrencyDelegate(int value);

		private static readonly MethodInfo EmpressRunIsLevelMethodInfo = AccessTools.Method(typeof(SemiFunc), "RunIsLevel", (Type[])null, (Type[])null);

		private static readonly MethodInfo EmpressStatGetRunCurrencyMethodInfo = AccessTools.Method(typeof(SemiFunc), "StatGetRunCurrency", (Type[])null, (Type[])null);

		private static readonly MethodInfo EmpressStatSetRunCurrencyMethodInfo = AccessTools.Method(typeof(SemiFunc), "StatSetRunCurrency", (Type[])null, (Type[])null);

		private static readonly EmpressRunIsLevelDelegate EmpressRunIsLevelMethod = ((EmpressRunIsLevelMethodInfo != null) ? AccessTools.MethodDelegate<EmpressRunIsLevelDelegate>(EmpressRunIsLevelMethodInfo, (object)null, false) : null);

		private static readonly EmpressStatGetRunCurrencyDelegate EmpressStatGetRunCurrencyMethod = ((EmpressStatGetRunCurrencyMethodInfo != null) ? AccessTools.MethodDelegate<EmpressStatGetRunCurrencyDelegate>(EmpressStatGetRunCurrencyMethodInfo, (object)null, false) : null);

		private static readonly EmpressStatSetRunCurrencyDelegate EmpressStatSetRunCurrencyMethod = ((EmpressStatSetRunCurrencyMethodInfo != null) ? AccessTools.MethodDelegate<EmpressStatSetRunCurrencyDelegate>(EmpressStatSetRunCurrencyMethodInfo, (object)null, false) : null);

		private static readonly FieldInfo EmpressLevelGeneratorGeneratedField = AccessTools.Field(typeof(LevelGenerator), "Generated");

		private static readonly FieldInfo EmpressLevelPointInStartRoomField = AccessTools.Field(typeof(LevelPoint), "inStartRoom");

		private static readonly FieldInfo EmpressLevelPointRoomField = AccessTools.Field(typeof(LevelPoint), "Room");

		private static readonly FieldInfo EmpressLevelPointConnectedPointsField = AccessTools.Field(typeof(LevelPoint), "ConnectedPoints");

		private static readonly FieldInfo EmpressRoomVolumeTruckField = AccessTools.Field(typeof(RoomVolume), "Truck");

		private static readonly FieldInfo EmpressRoomVolumeExtractionField = AccessTools.Field(typeof(RoomVolume), "Extraction");

		private static readonly FieldInfo EmpressPlayerAvatarDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");

		internal static bool EmpressIsRunLevel()
		{
			try
			{
				return EmpressRunIsLevelMethod != null && EmpressRunIsLevelMethod();
			}
			catch
			{
				return false;
			}
		}

		internal static int EmpressGetRunCurrency()
		{
			try
			{
				return (EmpressStatGetRunCurrencyMethod != null) ? EmpressStatGetRunCurrencyMethod() : 0;
			}
			catch
			{
				return 0;
			}
		}

		internal static int EmpressSetRunCurrency(int value)
		{
			try
			{
				return (EmpressStatSetRunCurrencyMethod != null) ? EmpressStatSetRunCurrencyMethod(value) : EmpressGetRunCurrency();
			}
			catch
			{
				return EmpressGetRunCurrency();
			}
		}

		internal static bool EmpressLevelGenerated(LevelGenerator generator)
		{
			if ((Object)(object)generator != (Object)null)
			{
				return EmpressGetFieldValue(EmpressLevelGeneratorGeneratedField, generator, fallback: false);
			}
			return false;
		}

		internal static bool EmpressIsStartRoomPoint(LevelPoint point)
		{
			if ((Object)(object)point != (Object)null)
			{
				return EmpressGetFieldValue(EmpressLevelPointInStartRoomField, point, fallback: false);
			}
			return false;
		}

		internal static RoomVolume EmpressGetRoom(LevelPoint point)
		{
			if (!((Object)(object)point != (Object)null))
			{
				return null;
			}
			return EmpressGetFieldValue<RoomVolume>(EmpressLevelPointRoomField, point, null);
		}

		internal static List<LevelPoint> EmpressGetConnectedPoints(LevelPoint point)
		{
			if (!((Object)(object)point != (Object)null))
			{
				return new List<LevelPoint>();
			}
			return EmpressGetFieldValue<List<LevelPoint>>(EmpressLevelPointConnectedPointsField, point, null) ?? new List<LevelPoint>();
		}

		internal static bool EmpressRoomIsTruck(RoomVolume room)
		{
			if ((Object)(object)room != (Object)null)
			{
				return EmpressGetFieldValue(EmpressRoomVolumeTruckField, room, fallback: false);
			}
			return false;
		}

		internal static bool EmpressRoomIsExtraction(RoomVolume room)
		{
			if ((Object)(object)room != (Object)null)
			{
				return EmpressGetFieldValue(EmpressRoomVolumeExtractionField, room, fallback: false);
			}
			return false;
		}

		internal static bool EmpressPlayerDisabled(PlayerAvatar avatar)
		{
			if (!((Object)(object)avatar == (Object)null))
			{
				return EmpressGetFieldValue(EmpressPlayerAvatarDisabledField, avatar, fallback: false);
			}
			return true;
		}

		internal static Scene EmpressActiveScene()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return SceneManager.GetActiveScene();
		}

		internal static T EmpressFindFirstSceneObject<T>() where T : Object
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Scene val = EmpressActiveScene();
			T[] array = Resources.FindObjectsOfTypeAll<T>();
			foreach (T val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				T val3 = val2;
				object obj = val3;
				Component val4 = (Component)((obj is Component) ? obj : null);
				if (val4 == null)
				{
					object obj2 = val3;
					GameObject val5 = (GameObject)((obj2 is GameObject) ? obj2 : null);
					if (val5 != null && val5.scene == val)
					{
						return val2;
					}
				}
				else if (val4.gameObject.scene == val)
				{
					return val2;
				}
			}
			return default(T);
		}

		internal static List<T> EmpressFindSceneObjects<T>() where T : Object
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			Scene val = EmpressActiveScene();
			List<T> list = new List<T>();
			T[] array = Resources.FindObjectsOfTypeAll<T>();
			foreach (T val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				T val3 = val2;
				object obj = val3;
				Component val4 = (Component)((obj is Component) ? obj : null);
				if (val4 == null)
				{
					object obj2 = val3;
					GameObject val5 = (GameObject)((obj2 is GameObject) ? obj2 : null);
					if (val5 != null && val5.scene == val)
					{
						list.Add(val2);
					}
				}
				else if (val4.gameObject.scene == val)
				{
					list.Add(val2);
				}
			}
			return list;
		}

		internal static PlayerAvatar EmpressFindLocalPlayer()
		{
			List<PlayerAvatar> list = EmpressCoinAccess.EmpressFindSceneObjects<PlayerAvatar>();
			if (PhotonNetwork.InRoom)
			{
				foreach (PlayerAvatar item in list)
				{
					if (!EmpressPlayerDisabled(item))
					{
						PhotonView val = (((Object)(object)item.photonView != (Object)null) ? item.photonView : ((Component)item).GetComponent<PhotonView>());
						if ((Object)(object)val != (Object)null && val.IsMine)
						{
							return item;
						}
					}
				}
			}
			foreach (PlayerAvatar item2 in list)
			{
				if (!EmpressPlayerDisabled(item2))
				{
					return item2;
				}
			}
			return null;
		}

		internal static PlayerAvatar EmpressFindPlayerByPhotonViewId(int photonViewId)
		{
			if (photonViewId <= 0)
			{
				return null;
			}
			foreach (PlayerAvatar item in EmpressCoinAccess.EmpressFindSceneObjects<PlayerAvatar>())
			{
				PhotonView val = (((Object)(object)item.photonView != (Object)null) ? item.photonView : ((Component)item).GetComponent<PhotonView>());
				if ((Object)(object)val != (Object)null && val.ViewID == photonViewId)
				{
					return item;
				}
			}
			return null;
		}

		private static T EmpressGetFieldValue<T>(FieldInfo fieldInfo, object instance, T fallback)
		{
			if (fieldInfo == null || instance == null)
			{
				return fallback;
			}
			try
			{
				object value = fieldInfo.GetValue(instance);
				if (value is T)
				{
					return (T)value;
				}
			}
			catch
			{
			}
			return fallback;
		}
	}
	internal sealed class EmpressCoinAssets
	{
		private const string EmpressBundleName = "coin";

		private const string EmpressPrefabName = "BoingImACoin";

		private static readonly string[] EmpressBundleCandidates = new string[4] { "coin", "coin.bundle", "coin.unity3d", "coin.assets" };

		private static readonly string[] EmpressPreferredSoundCandidates = new string[5] { "EmpressCoinPickup.bin", "EmpressCoinPickup.xorbin", "coinpickup.bin", "coin-pickup.bin", "pickup.bin" };

		private readonly EmpressCoinPlugin empressPlugin;

		private readonly string empressAssemblyDirectory;

		private AssetBundle empressBundle;

		private GameObject empressCoinPrefab;

		private AudioClip empressPickupClip;

		private Coroutine empressSoundLoadRoutine;

		private bool empressBundleResolved;

		private bool empressSoundResolved;

		internal float EmpressFloorOffset { get; private set; }

		internal float EmpressHeight { get; private set; }

		internal float EmpressRadius { get; private set; }

		internal bool EmpressHasPrefab => (Object)(object)empressCoinPrefab != (Object)null;

		internal EmpressCoinAssets(EmpressCoinPlugin plugin)
		{
			empressPlugin = plugin;
			empressAssemblyDirectory = Path.GetDirectoryName(typeof(EmpressCoinPlugin).Assembly.Location) ?? AppDomain.CurrentDomain.BaseDirectory;
			EmpressFloorOffset = 0.05f;
			EmpressHeight = 0.6f;
			EmpressRadius = 0.25f;
		}

		internal bool EmpressEnsureBundle()
		{
			if (empressBundleResolved)
			{
				return (Object)(object)empressCoinPrefab != (Object)null;
			}
			empressBundleResolved = true;
			string text = EmpressResolveBundlePath();
			if (string.IsNullOrWhiteSpace(text))
			{
				empressPlugin.EmpressWarn("asset bundle 'coin' was not found. EmpressCoin will stay inactive until the bundle is placed beside the DLL or in an assets folder.");
				return false;
			}
			try
			{
				empressBundle = AssetBundle.LoadFromFile(text);
			}
			catch (Exception ex)
			{
				empressPlugin.EmpressWarn("asset bundle load failed: " + ex.Message);
				return false;
			}
			if ((Object)(object)empressBundle == (Object)null)
			{
				empressPlugin.EmpressWarn("asset bundle 'coin' could not be opened.");
				return false;
			}
			empressCoinPrefab = empressBundle.LoadAsset<GameObject>("BoingImACoin");
			if ((Object)(object)empressCoinPrefab == (Object)null)
			{
				empressPlugin.EmpressWarn("asset bundle 'coin' did not contain prefab 'BoingImACoin'.");
				return false;
			}
			EmpressMeasurePrefab();
			empressPlugin.EmpressDebug("assets ready from bundle '" + Path.GetFileName(text) + "'.");
			return true;
		}

		internal void EmpressWarmupSound(MonoBehaviour host)
		{
			if (!((Object)(object)host == (Object)null) && !empressSoundResolved && empressSoundLoadRoutine == null)
			{
				empressSoundLoadRoutine = host.StartCoroutine(EmpressLoadSoundAsync());
			}
		}

		internal GameObject EmpressInstantiateCoin(Transform parent, Vector3 position, Quaternion rotation)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!EmpressEnsureBundle())
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(empressCoinPrefab, position, rotation, parent);
			((Object)val).name = "EmpressCoin.Actor";
			Rigidbody[] componentsInChildren = val.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody obj in componentsInChildren)
			{
				obj.isKinematic = true;
				obj.useGravity = false;
				obj.velocity = Vector3.zero;
				obj.angularVelocity = Vector3.zero;
			}
			return val;
		}

		internal void EmpressPlayPickupSound(Vector3 position, float volume)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			if (!((Object)(object)empressPickupClip == (Object)null) && !(volume <= 0f))
			{
				GameObject val = new GameObject("EmpressCoin.PickupAudio")
				{
					hideFlags = (HideFlags)61
				};
				val.transform.position = position;
				AudioSource obj = val.AddComponent<AudioSource>();
				obj.playOnAwake = false;
				obj.spatialBlend = 1f;
				obj.rolloffMode = (AudioRolloffMode)1;
				obj.minDistance = 1f;
				obj.maxDistance = 18f;
				obj.volume = Mathf.Clamp01(volume);
				obj.clip = empressPickupClip;
				obj.Play();
				Object.Destroy((Object)val, Mathf.Max(0.25f, empressPickupClip.length + 0.25f));
			}
		}

		private void EmpressMeasurePrefab()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(empressCoinPrefab);
			((Object)val).hideFlags = (HideFlags)61;
			val.transform.position = Vector3.zero;
			val.transform.rotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.SetActive(true);
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(Vector3.zero, Vector3.zero);
			bool flag = false;
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!flag)
				{
					bounds = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren2)
			{
				if (!flag)
				{
					bounds = val3.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val3.bounds);
				}
			}
			if (flag)
			{
				EmpressFloorOffset = Mathf.Max(0.02f, 0f - ((Bounds)(ref bounds)).min.y + 0.01f);
				EmpressHeight = Mathf.Max(0.2f, ((Bounds)(ref bounds)).size.y);
				EmpressRadius = Mathf.Max(0.15f, Mathf.Max(((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.z));
			}
			Object.Destroy((Object)(object)val);
		}

		private IEnumerator EmpressLoadSoundAsync()
		{
			empressSoundResolved = true;
			string text = EmpressResolveSoundPath();
			if (string.IsNullOrWhiteSpace(text) || !File.Exists(text))
			{
				empressSoundLoadRoutine = null;
				empressPlugin.EmpressDebug("pickup sound container was not found. Coins will stay silent.");
				yield break;
			}
			byte[] encryptedBytes;
			try
			{
				encryptedBytes = File.ReadAllBytes(text);
			}
			catch (Exception ex)
			{
				empressSoundLoadRoutine = null;
				empressPlugin.EmpressWarn("pickup sound container could not be read: " + ex.Message);
				yield break;
			}
			if (encryptedBytes.Length == 0)
			{
				empressSoundLoadRoutine = null;
				empressPlugin.EmpressWarn("pickup sound container was empty.");
				yield break;
			}
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
			foreach (byte[] item in EmpressBuildXorKeys(fileNameWithoutExtension))
			{
				byte[] bytes = EmpressXorBytes(encryptedBytes, item);
				if (EmpressTryCreateWavClip(bytes, "EmpressCoin.Pickup", out var clip))
				{
					empressPickupClip = clip;
					empressSoundLoadRoutine = null;
					empressPlugin.EmpressDebug("pickup sound ready from XOR container.");
					yield break;
				}
				if (!EmpressTryDetectCompressedAudio(bytes, out var extension, out var audioType))
				{
					continue;
				}
				string tempPath = Path.Combine(Path.GetTempPath(), "EmpressCoin_Pickup_" + Guid.NewGuid().ToString("N") + extension);
				try
				{
					File.WriteAllBytes(tempPath, bytes);
				}
				catch (Exception ex2)
				{
					empressPlugin.EmpressWarn("pickup sound could not be staged for decode: " + ex2.Message);
					continue;
				}
				UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(tempPath).AbsoluteUri, audioType);
				try
				{
					yield return request.SendWebRequest();
					try
					{
						if ((int)request.result == 1)
						{
							empressPickupClip = DownloadHandlerAudioClip.GetContent(request);
						}
					}
					finally
					{
						EmpressDeleteTempFile(tempPath);
					}
				}
				finally
				{
					((IDisposable)request)?.Dispose();
				}
				if ((Object)(object)empressPickupClip != (Object)null)
				{
					((Object)empressPickupClip).name = "EmpressCoin.Pickup";
					empressSoundLoadRoutine = null;
					empressPlugin.EmpressDebug("pickup sound ready from XOR container.");
					yield break;
				}
			}
			empressSoundLoadRoutine = null;
			empressPlugin.EmpressWarn("pickup sound decode failed. Coin pickups will continue without audio.");
		}

		private string EmpressResolveBundlePath()
		{
			foreach (string item in EmpressEnumerateAssetDirectories())
			{
				string[] empressBundleCandidates = EmpressBundleCandidates;
				foreach (string path in empressBundleCandidates)
				{
					string text = Path.Combine(item, path);
					if (File.Exists(text))
					{
						return text;
					}
				}
				empressBundleCandidates = Directory.GetFiles(item);
				foreach (string text2 in empressBundleCandidates)
				{
					if (string.Equals(Path.GetFileName(text2), "coin", StringComparison.OrdinalIgnoreCase) || string.Equals(Path.GetFileNameWithoutExtension(text2), "coin", StringComparison.OrdinalIgnoreCase))
					{
						return text2;
					}
				}
			}
			return null;
		}

		private string EmpressResolveSoundPath()
		{
			foreach (string item in EmpressEnumerateAssetDirectories())
			{
				string[] empressPreferredSoundCandidates = EmpressPreferredSoundCandidates;
				foreach (string path in empressPreferredSoundCandidates)
				{
					string text = Path.Combine(item, path);
					if (File.Exists(text))
					{
						return text;
					}
				}
				empressPreferredSoundCandidates = Directory.GetFiles(item);
				foreach (string text2 in empressPreferredSoundCandidates)
				{
					string fileName = Path.GetFileName(text2);
					if ((fileName.EndsWith(".bin", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".xorbin", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".xor", StringComparison.OrdinalIgnoreCase)) && (fileName.IndexOf("coin", StringComparison.OrdinalIgnoreCase) >= 0 || fileName.IndexOf("pickup", StringComparison.OrdinalIgnoreCase) >= 0))
					{
						return text2;
					}
				}
			}
			return null;
		}

		private IEnumerable<string> EmpressEnumerateAssetDirectories()
		{
			HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = new string[3]
			{
				empressAssemblyDirectory,
				Path.Combine(empressAssemblyDirectory, "assets"),
				Path.Combine(empressAssemblyDirectory, "Assets")
			};
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!string.IsNullOrWhiteSpace(text))
				{
					string fullPath = Path.GetFullPath(text);
					if (seen.Add(fullPath) && Directory.Exists(fullPath))
					{
						yield return fullPath;
					}
				}
			}
		}

		private static IEnumerable<byte[]> EmpressBuildXorKeys(string stem)
		{
			yield return Encoding.UTF8.GetBytes("empress.repo.empresscoin|pickup-sound|v1");
			yield return Encoding.UTF8.GetBytes("empress.repo.empresscoin|pickup|v1");
			yield return Encoding.UTF8.GetBytes("empress.repo.empresscoin|coin-pickup|v1");
			yield return Encoding.UTF8.GetBytes("empress.repo.empresscoin");
			if (!string.IsNullOrWhiteSpace(stem))
			{
				yield return Encoding.UTF8.GetBytes("empress.repo.empresscoin|" + stem + "|v1");
			}
		}

		private static byte[] EmpressXorBytes(byte[] source, byte[] key)
		{
			byte[] array = new byte[source.Length];
			for (int i = 0; i < source.Length; i++)
			{
				array[i] = (byte)(source[i] ^ key[i % key.Length]);
			}
			return array;
		}

		private static bool EmpressTryDetectCompressedAudio(byte[] bytes, out string extension, out AudioType audioType)
		{
			extension = string.Empty;
			audioType = (AudioType)0;
			if (bytes.Length < 4)
			{
				return false;
			}
			if (bytes[0] == 79 && bytes[1] == 103 && bytes[2] == 103 && bytes[3] == 83)
			{
				extension = ".ogg";
				audioType = (AudioType)14;
				return true;
			}
			if (bytes[0] == 73 && bytes[1] == 68 && bytes[2] == 51)
			{
				extension = ".mp3";
				audioType = (AudioType)13;
				return true;
			}
			if (bytes[0] == byte.MaxValue && (bytes[1] & 0xE0) == 224)
			{
				extension = ".mp3";
				audioType = (AudioType)13;
				return true;
			}
			return false;
		}

		private static bool EmpressTryCreateWavClip(byte[] bytes, string clipName, out AudioClip clip)
		{
			clip = null;
			if (bytes.Length < 44)
			{
				return false;
			}
			if (Encoding.ASCII.GetString(bytes, 0, 4) != "RIFF" || Encoding.ASCII.GetString(bytes, 8, 4) != "WAVE")
			{
				return false;
			}
			short num = 0;
			short num2 = 0;
			int num3 = 0;
			short num4 = 0;
			int num5 = -1;
			int num6 = 0;
			int num7 = 12;
			while (num7 + 8 <= bytes.Length)
			{
				string @string = Encoding.ASCII.GetString(bytes, num7, 4);
				int num8 = BitConverter.ToInt32(bytes, num7 + 4);
				num7 += 8;
				if (num8 < 0 || num7 + num8 > bytes.Length)
				{
					return false;
				}
				if (@string == "fmt " && num8 >= 16)
				{
					num = BitConverter.ToInt16(bytes, num7);
					num2 = BitConverter.ToInt16(bytes, num7 + 2);
					num3 = BitConverter.ToInt32(bytes, num7 + 4);
					num4 = BitConverter.ToInt16(bytes, num7 + 14);
				}
				else if (@string == "data")
				{
					num5 = num7;
					num6 = num8;
					break;
				}
				num7 += num8;
				if (((uint)num8 & (true ? 1u : 0u)) != 0)
				{
					num7++;
				}
			}
			if (num2 <= 0 || num3 <= 0 || num5 < 0 || num6 <= 0)
			{
				return false;
			}
			int num9;
			float[] array;
			try
			{
				switch (num)
				{
				case 1:
					switch (num4)
					{
					case 8:
					{
						num9 = num6;
						array = new float[num9];
						for (int m = 0; m < num9; m++)
						{
							array[m] = ((float)(int)bytes[num5 + m] - 128f) / 128f;
						}
						break;
					}
					case 16:
					{
						num9 = num6 / 2;
						array = new float[num9];
						for (int k = 0; k < num9; k++)
						{
							short num11 = BitConverter.ToInt16(bytes, num5 + k * 2);
							array[k] = (float)num11 / 32768f;
						}
						break;
					}
					case 24:
					{
						num9 = num6 / 3;
						array = new float[num9];
						for (int l = 0; l < num9; l++)
						{
							int num12 = num5 + l * 3;
							int num13 = bytes[num12] | (bytes[num12 + 1] << 8) | (bytes[num12 + 2] << 16);
							if (((uint)num13 & 0x800000u) != 0)
							{
								num13 |= -16777216;
							}
							array[l] = (float)num13 / 8388608f;
						}
						break;
					}
					case 32:
					{
						num9 = num6 / 4;
						array = new float[num9];
						for (int j = 0; j < num9; j++)
						{
							int num10 = BitConverter.ToInt32(bytes, num5 + j * 4);
							array[j] = (float)num10 / 2.1474836E+09f;
						}
						break;
					}
					default:
						return false;
					}
					goto end_IL_0117;
				case 3:
				{
					if (num4 != 32)
					{
						break;
					}
					num9 = num6 / 4;
					array = new float[num9];
					for (int i = 0; i < num9; i++)
					{
						array[i] = BitConverter.ToSingle(bytes, num5 + i * 4);
					}
					goto end_IL_0117;
				}
				}
				return false;
				end_IL_0117:;
			}
			catch
			{
				return false;
			}
			if (num9 <= 0 || num9 % num2 != 0)
			{
				return false;
			}
			clip = AudioClip.Create(clipName, num9 / num2, (int)num2, num3, false);
			clip.SetData(array, 0);
			return true;
		}

		private static void EmpressDeleteTempFile(string path)
		{
			try
			{
				if (File.Exists(path))
				{
					File.Delete(path);
				}
			}
			catch
			{
			}
		}
	}
	internal sealed class EmpressCoinConfig
	{
		internal ConfigEntry<bool> EmpressEnabled { get; }

		internal ConfigEntry<int> EmpressDefaultCoinValueK { get; }

		internal ConfigEntry<EmpressCoinDensityPreset> EmpressCoinDensityPreset { get; }

		internal ConfigEntry<int> EmpressOptionalAdvancedCoinCountOverride { get; }

		internal ConfigEntry<float> EmpressPickupRange { get; }

		internal ConfigEntry<bool> EmpressDebugLogging { get; }

		internal ConfigEntry<float> EmpressOptionalSoundVolume { get; }

		internal EmpressCoinConfig(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			EmpressEnabled = config.Bind<bool>("Empress General", "Enabled", true, "Turns EmpressCoin on for host-authoritative scene sessions.");
			EmpressDefaultCoinValueK = config.Bind<int>("Empress Gameplay", "DefaultCoinValueK", 1, new ConfigDescription("How much team currency each Empress coin grants in K.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			EmpressCoinDensityPreset = config.Bind<EmpressCoinDensityPreset>("Empress Gameplay", "CoinDensityPreset", EmpressCoin.EmpressCoinDensityPreset.Max, "Simple Empress coin density preset for host-authoritative spawn counts.");
			EmpressOptionalAdvancedCoinCountOverride = config.Bind<int>("Empress Gameplay", "OptionalAdvancedCoinCountOverride", 0, new ConfigDescription("If above zero, EmpressCoin uses this exact per-level spawn count instead of the preset.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 250), Array.Empty<object>()));
			EmpressPickupRange = config.Bind<float>("Empress Gameplay", "PickupRange", 2.1f, new ConfigDescription("Maximum host-validated pickup distance in world units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), Array.Empty<object>()));
			EmpressDebugLogging = config.Bind<bool>("Empress Debug", "DebugLogging", false, "Adds concise EmpressCoin debug logs for asset loading, spawn planning, requests, validation, and sync.");
			EmpressOptionalSoundVolume = config.Bind<float>("Empress Audio", "OptionalSoundVolume", 0.9f, new ConfigDescription("Local pickup sound playback volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		}

		internal EmpressCoinAuthoritySettings EmpressCreateAuthoritySettings(bool assetsReady)
		{
			return new EmpressCoinAuthoritySettings(EmpressEnabled.Value && assetsReady, Mathf.Clamp(EmpressDefaultCoinValueK.Value, 1, 1000), EmpressCoinDensityPreset.Value, Mathf.Clamp(EmpressOptionalAdvancedCoinCountOverride.Value, 0, 250), Mathf.Clamp(EmpressPickupRange.Value, 0.5f, 8f));
		}
	}
	internal enum EmpressCoinDensityPreset : byte
	{
		Min,
		Medium,
		Max
	}
	internal readonly struct EmpressCoinAuthoritySettings : IEquatable<EmpressCoinAuthoritySettings>
	{
		internal bool EmpressEnabled { get; }

		internal int EmpressCoinValueK { get; }

		internal EmpressCoinDensityPreset EmpressDensityPreset { get; }

		internal int EmpressOptionalAdvancedCoinCountOverride { get; }

		internal float EmpressPickupRange { get; }

		internal EmpressCoinAuthoritySettings(bool enabled, int coinValueK, EmpressCoinDensityPreset densityPreset, int optionalAdvancedCoinCountOverride, float pickupRange)
		{
			EmpressEnabled = enabled;
			EmpressCoinValueK = coinValueK;
			EmpressDensityPreset = densityPreset;
			EmpressOptionalAdvancedCoinCountOverride = optionalAdvancedCoinCountOverride;
			EmpressPickupRange = pickupRange;
		}

		internal int EmpressResolveSpawnCount(int availableSpawnCount)
		{
			if (!EmpressEnabled || availableSpawnCount <= 0)
			{
				return 0;
			}
			if (EmpressOptionalAdvancedCoinCountOverride > 0)
			{
				return Mathf.Clamp(EmpressOptionalAdvancedCoinCountOverride, 1, availableSpawnCount);
			}
			int num;
			int num2;
			float num3;
			switch (EmpressDensityPreset)
			{
			case EmpressCoinDensityPreset.Min:
				num = 6;
				num2 = 18;
				num3 = 0.08f;
				break;
			case EmpressCoinDensityPreset.Max:
				num = 20;
				num2 = 64;
				num3 = 0.28f;
				break;
			default:
				num = 12;
				num2 = 36;
				num3 = 0.16f;
				break;
			}
			return Mathf.Clamp(Mathf.RoundToInt((float)availableSpawnCount * num3), Mathf.Min(num, availableSpawnCount), Mathf.Min(num2, availableSpawnCount));
		}

		public bool Equals(EmpressCoinAuthoritySettings other)
		{
			if (EmpressEnabled == other.EmpressEnabled && EmpressCoinValueK == other.EmpressCoinValueK && EmpressDensityPreset == other.EmpressDensityPreset && EmpressOptionalAdvancedCoinCountOverride == other.EmpressOptionalAdvancedCoinCountOverride)
			{
				return Mathf.Abs(EmpressPickupRange - other.EmpressPickupRange) < 0.0001f;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is EmpressCoinAuthoritySettings other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return HashCode.Combine(EmpressEnabled, EmpressCoinValueK, (byte)EmpressDensityPreset, EmpressOptionalAdvancedCoinCountOverride, Mathf.RoundToInt(EmpressPickupRange * 1000f));
		}
	}
	internal readonly struct EmpressCoinSpawnPoint
	{
		internal int EmpressCoinId { get; }

		internal Vector3 EmpressPosition { get; }

		internal float EmpressYaw { get; }

		internal EmpressCoinSpawnPoint(int coinId, Vector3 position, float yaw)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			EmpressCoinId = coinId;
			EmpressPosition = position;
			EmpressYaw = yaw;
		}
	}
	internal sealed class EmpressCoinSceneCoin : MonoBehaviour
	{
		internal int EmpressCoinId;

		internal float EmpressNextRequestTime;

		internal Vector3 EmpressPickupPosition;

		private void Awake()
		{
			//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)
			EmpressPickupPosition = ((Component)this).transform.position;
		}
	}
	internal static class EmpressCoinWire
	{
		private const string EmpressVersion = "1";

		internal static string EmpressSerializeConfig(EmpressCoinAuthoritySettings settings)
		{
			return string.Join("|", "1", settings.EmpressEnabled ? "1" : "0", settings.EmpressCoinValueK.ToString(CultureInfo.InvariantCulture), ((byte)settings.EmpressDensityPreset).ToString(CultureInfo.InvariantCulture), settings.EmpressOptionalAdvancedCoinCountOverride.ToString(CultureInfo.InvariantCulture), settings.EmpressPickupRange.ToString("0.###", CultureInfo.InvariantCulture));
		}

		internal static bool EmpressTryParseConfig(string value, out EmpressCoinAuthoritySettings settings)
		{
			settings = default(EmpressCoinAuthoritySettings);
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Split('|');
			if (array.Length != 6 || array[0] != "1")
			{
				return false;
			}
			if (!int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				return false;
			}
			if (!byte.TryParse(array[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
			{
				return false;
			}
			if (!int.TryParse(array[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3))
			{
				return false;
			}
			if (!float.TryParse(array[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
			{
				return false;
			}
			settings = new EmpressCoinAuthoritySettings(array[1] == "1", Mathf.Clamp(result, 1, 1000), (EmpressCoinDensityPreset)((!Enum.IsDefined(typeof(EmpressCoinDensityPreset), result2)) ? 1 : result2), Mathf.Clamp(result3, 0, 250), Mathf.Clamp(result4, 0.5f, 8f));
			return true;
		}

		internal static string EmpressSerializeSpawn(string sessionToken, string sceneName, IReadOnlyList<EmpressCoinSpawnPoint> spawns)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("1").Append('|').Append(sessionToken ?? string.Empty)
				.Append('|')
				.Append(sceneName ?? string.Empty)
				.Append('|');
			for (int i = 0; i < spawns.Count; i++)
			{
				EmpressCoinSpawnPoint empressCoinSpawnPoint = spawns[i];
				if (i > 0)
				{
					stringBuilder.Append(';');
				}
				stringBuilder.Append(empressCoinSpawnPoint.EmpressCoinId.ToString(CultureInfo.InvariantCulture)).Append(',').Append(empressCoinSpawnPoint.EmpressPosition.x.ToString("0.###", CultureInfo.InvariantCulture))
					.Append(',')
					.Append(empressCoinSpawnPoint.EmpressPosition.y.ToString("0.###", CultureInfo.InvariantCulture))
					.Append(',')
					.Append(empressCoinSpawnPoint.EmpressPosition.z.ToString("0.###", CultureInfo.InvariantCulture))
					.Append(',')
					.Append(empressCoinSpawnPoint.EmpressYaw.ToString("0.###", CultureInfo.InvariantCulture));
			}
			return stringBuilder.ToString();
		}

		internal static bool EmpressTryParseSpawn(string value, out string sessionToken, out string sceneName, out List<EmpressCoinSpawnPoint> spawns)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			sessionToken = string.Empty;
			sceneName = string.Empty;
			spawns = new List<EmpressCoinSpawnPoint>();
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Split(new char[1] { '|' }, 4);
			if (array.Length < 4 || array[0] != "1")
			{
				return false;
			}
			sessionToken = array[1];
			sceneName = array[2];
			if (string.IsNullOrWhiteSpace(array[3]))
			{
				return true;
			}
			string[] array2 = array[3].Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array2.Length; i++)
			{
				string[] array3 = array2[i].Split(',');
				if (array3.Length != 5)
				{
					return false;
				}
				if (!int.TryParse(array3[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
				{
					return false;
				}
				if (!float.TryParse(array3[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array3[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) || !float.TryParse(array3[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4) || !float.TryParse(array3[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5))
				{
					return false;
				}
				spawns.Add(new EmpressCoinSpawnPoint(result, new Vector3(result2, result3, result4), result5));
			}
			spawns = spawns.OrderBy((EmpressCoinSpawnPoint spawn) => spawn.EmpressCoinId).ToList();
			return true;
		}

		internal static string EmpressSerializePicked(string sessionToken, IReadOnlyCollection<int> pickedIds)
		{
			string text = ((pickedIds == null || pickedIds.Count == 0) ? string.Empty : string.Join(",", from id in pickedIds
				orderby id
				select id.ToString(CultureInfo.InvariantCulture)));
			return string.Join("|", "1", sessionToken ?? string.Empty, text);
		}

		internal static bool EmpressTryParsePicked(string value, out string sessionToken, out HashSet<int> pickedIds)
		{
			sessionToken = string.Empty;
			pickedIds = new HashSet<int>();
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Split(new char[1] { '|' }, 3);
			if (array.Length < 2 || array[0] != "1")
			{
				return false;
			}
			sessionToken = array[1];
			if (array.Length == 2 || string.IsNullOrWhiteSpace(array[2]))
			{
				return true;
			}
			string[] array2 = array[2].Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array2.Length; i++)
			{
				if (int.TryParse(array2[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
				{
					pickedIds.Add(result);
				}
			}
			return true;
		}
	}
	[BepInPlugin("empress.repo.empresscoin", "EmpressCoin", "1.0.0")]
	public sealed class EmpressCoinPlugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "empress.repo.empresscoin";

		internal const string PluginName = "EmpressCoin";

		internal const string PluginVersion = "1.0.0";

		private float empressNextRuntimeAuditTime;

		internal static EmpressCoinPlugin Instance { get; private set; }

		internal static EmpressCoinRuntime Runtime { get; private set; }

		internal EmpressCoinConfig EmpressConfig { get; private set; }

		internal ManualLogSource EmpressLog => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			Instance = this;
			((Component)this).transform.SetParent((Transform)null, true);
			((Object)this).hideFlags = (HideFlags)61;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			EmpressConfig = new EmpressCoinConfig(((BaseUnityPlugin)this).Config);
			EmpressEnsureRuntime();
			EmpressInfo("loaded");
		}

		private void Update()
		{
			((Component)this).transform.SetParent((Transform)null, true);
			if (!(Time.unscaledTime < empressNextRuntimeAuditTime))
			{
				empressNextRuntimeAuditTime = Time.unscaledTime + 1f;
				EmpressEnsureRuntime();
			}
		}

		internal EmpressCoinRuntime EmpressEnsureRuntime()
		{
			//IL_0080: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			List<EmpressCoinRuntime> source = (from runtime in Resources.FindObjectsOfTypeAll<EmpressCoinRuntime>()
				where (Object)(object)runtime != (Object)null
				select runtime).ToList();
			EmpressCoinRuntime empressCoinRuntime = source.FirstOrDefault();
			foreach (EmpressCoinRuntime item in source.Skip(1))
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
			}
			if ((Object)(object)empressCoinRuntime == (Object)null)
			{
				GameObject val = new GameObject("EmpressCoin.Runtime");
				val.transform.SetParent((Transform)null, true);
				((Object)val).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)val);
				empressCoinRuntime = val.AddComponent<EmpressCoinRuntime>();
			}
			else
			{
				((Component)empressCoinRuntime).transform.SetParent((Transform)null, true);
				((Object)empressCoinRuntime).hideFlags = (HideFlags)61;
				((Object)((Component)empressCoinRuntime).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)empressCoinRuntime).gameObject);
			}
			Runtime = empressCoinRuntime;
			Runtime.EmpressBindPlugin(this);
			return empressCoinRuntime;
		}

		internal void EmpressInfo(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[EmpressCoin] " + message));
		}

		internal void EmpressWarn(string message)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[EmpressCoin] " + message));
		}

		internal void EmpressError(string message)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[EmpressCoin] " + message));
		}

		internal void EmpressDebug(string message)
		{
			if (EmpressConfig != null && EmpressConfig.EmpressDebugLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[EmpressCoin] " + message));
			}
		}
	}
	internal sealed class EmpressCoinRelay : MonoBehaviourPunCallbacks, IOnEventCallback
	{
		private const string EmpressConfigKey = "empress.coin.cfg";

		private const string EmpressSpawnKey = "empress.coin.spawn";

		private const string EmpressPickedKey = "empress.coin.picked";

		private PhotonView empressPhotonView;

		private EmpressCoinRuntime empressRuntime;

		private const byte EmpressPickupRequestEventCode = 189;

		private const byte EmpressPickupConfirmedEventCode = 190;

		internal bool EmpressIsReady => (Object)(object)empressPhotonView != (Object)null;

		internal static EmpressCoinRelay EmpressEnsureAttached(GameObject hostObject, EmpressCoinRuntime runtime)
		{
			if ((Object)(object)hostObject == (Object)null || (Object)(object)runtime == (Object)null)
			{
				return null;
			}
			EmpressCoinRelay empressCoinRelay = hostObject.GetComponent<EmpressCoinRelay>();
			if ((Object)(object)empressCoinRelay == (Object)null)
			{
				empressCoinRelay = hostObject.AddComponent<EmpressCoinRelay>();
			}
			empressCoinRelay.empressPhotonView = hostObject.GetComponent<PhotonView>();
			empressCoinRelay.empressRuntime = runtime;
			return empressCoinRelay;
		}

		private void Awake()
		{
			empressPhotonView = ((Component)this).GetComponent<PhotonView>();
		}

		internal void EmpressAttachRuntime(EmpressCoinRuntime runtime)
		{
			empressRuntime = runtime;
			if ((Object)(object)empressPhotonView == (Object)null)
			{
				empressPhotonView = ((Component)this).GetComponent<PhotonView>();
			}
		}

		internal void EmpressRefreshCurrentState()
		{
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null)
			{
				EmpressApplyRoomState((IDictionary)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties);
			}
		}

		internal void EmpressPublishSession(EmpressCoinAuthoritySettings settings, string sessionToken, string sceneName, List<EmpressCoinSpawnPoint> spawns, HashSet<int> pickedCoins)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0059: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.IsMasterClient)
			{
				Hashtable val = new Hashtable
				{
					[(object)"empress.coin.cfg"] = EmpressCoinWire.EmpressSerializeConfig(settings),
					[(object)"empress.coin.spawn"] = EmpressCoinWire.EmpressSerializeSpawn(sessionToken, sceneName, spawns),
					[(object)"empress.coin.picked"] = EmpressCoinWire.EmpressSerializePicked(sessionToken, pickedCoins)
				};
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
			empressRuntime?.EmpressConsumeSyncedState(settings, sessionToken, sceneName, spawns, pickedCoins);
		}

		internal void EmpressPublishPickedState(string sessionToken, HashSet<int> pickedCoins)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.IsMasterClient)
			{
				Hashtable val = new Hashtable { [(object)"empress.coin.picked"] = EmpressCoinWire.EmpressSerializePicked(sessionToken, pickedCoins) };
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
		}

		internal void EmpressRequestPickup(int coinId, int requesterPhotonViewId)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0062: Expected O, but got Unknown
			//IL_0068: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (!PhotonNetwork.InRoom)
			{
				empressRuntime?.EmpressTryResolvePickupAsAuthority(coinId, requesterPhotonViewId, null);
				return;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				empressRuntime?.EmpressTryResolvePickupAsAuthority(coinId, requesterPhotonViewId, PhotonNetwork.LocalPlayer);
				return;
			}
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)"c", (object)coinId);
			((Dictionary<object, object>)val).Add((object)"v", (object)requesterPhotonViewId);
			Hashtable val2 = val;
			PhotonNetwork.RaiseEvent((byte)189, (object)val2, new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)2
			}, SendOptions.SendReliable);
		}

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		public override void OnDisable()
		{
			((MonoBehaviourPunCallbacks)this).OnDisable();
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		void IOnEventCallback.OnEvent(EventData photonEvent)
		{
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code == 189)
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				object customData = photonEvent.CustomData;
				Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
				if (val == null)
				{
					return;
				}
				object obj = val[(object)"c"];
				if (!(obj is int))
				{
					return;
				}
				int coinId = (int)obj;
				obj = val[(object)"v"];
				if (!(obj is int))
				{
					return;
				}
				int requesterPhotonViewId = (int)obj;
				Player sender = null;
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val2 in playerList)
				{
					if (val2.ActorNumber == photonEvent.Sender)
					{
						sender = val2;
						break;
					}
				}
				empressRuntime?.EmpressTryResolvePickupAsAuthority(coinId, requesterPhotonViewId, sender);
			}
			else
			{
				if (photonEvent.Code != 190 || (PhotonNetwork.InRoom && photonEvent.Sender != PhotonNetwork.MasterClient.ActorNumber))
				{
					return;
				}
				object customData2 = photonEvent.CustomData;
				Hashtable val3 = (Hashtable)((customData2 is Hashtable) ? customData2 : null);
				if (val3 == null || !(val3[(object)"t"] is string sessionToken))
				{
					return;
				}
				object obj = val3[(object)"c"];
				if (!(obj is int))
				{
					return;
				}
				int coinId2 = (int)obj;
				obj = val3[(object)"px"];
				if (!(obj is float))
				{
					return;
				}
				float num = (float)obj;
				obj = val3[(object)"py"];
				if (!(obj is float))
				{
					return;
				}
				float num2 = (float)obj;
				obj = val3[(object)"pz"];
				if (!(obj is float))
				{
					return;
				}
				float num3 = (float)obj;
				obj = val3[(object)"r"];
				if (obj is int)
				{
					int rewardK = (int)obj;
					obj = val3[(object)"v"];
					if (obj is int)
					{
						int pickerPhotonViewId = (int)obj;
						empressRuntime?.EmpressHandlePickupConfirmed(sessionToken, coinId2, new Vector3(num, num2, num3), rewardK, pickerPhotonViewId);
					}
				}
			}
		}

		internal void EmpressBroadcastPickupConfirmed(string sessionToken, int coinId, Vector3 pickupPosition, int rewardK, int pickerPhotonViewId)
		{
			//IL_000a: 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_001b: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0058: 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_006e: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0093: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom)
			{
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"t", (object)sessionToken);
				((Dictionary<object, object>)val).Add((object)"c", (object)coinId);
				((Dictionary<object, object>)val).Add((object)"px", (object)pickupPosition.x);
				((Dictionary<object, object>)val).Add((object)"py", (object)pickupPosition.y);
				((Dictionary<object, object>)val).Add((object)"pz", (object)pickupPosition.z);
				((Dictionary<object, object>)val).Add((object)"r", (object)rewardK);
				((Dictionary<object, object>)val).Add((object)"v", (object)pickerPhotonViewId);
				Hashtable val2 = val;
				PhotonNetwork.RaiseEvent((byte)190, (object)val2, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)1
				}, SendOptions.SendReliable);
			}
			else
			{
				empressRuntime?.EmpressHandlePickupConfirmed(sessionToken, coinId, pickupPosition, rewardK, pickerPhotonViewId);
			}
		}

		[PunRPC]
		private void EmpressRpcPickupRequest(int coinId, int requesterPhotonViewId, PhotonMessageInfo info)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient)
			{
				empressRuntime?.EmpressTryResolvePickupAsAuthority(coinId, requesterPhotonViewId, info.Sender);
			}
		}

		[PunRPC]
		private void EmpressRpcPickupConfirmed(string sessionToken, int coinId, Vector3 pickupPosition, int rewardK, int pickerPhotonViewId, PhotonMessageInfo info)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || info.Sender == PhotonNetwork.MasterClient)
			{
				empressRuntime?.EmpressHandlePickupConfirmed(sessionToken, coinId, pickupPosition, rewardK, pickerPhotonViewId);
			}
		}

		public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			EmpressApplyRoomState((IDictionary)((PhotonNetwork.CurrentRoom != null) ? ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties : propertiesThatChanged));
		}

		public override void OnMasterClientSwitched(Player newMasterClient)
		{
			if (PhotonNetwork.LocalPlayer == newMasterClient)
			{
				empressRuntime?.EmpressHandleMasterClientSwitch();
			}
		}

		private void EmpressApplyRoomState(IDictionary roomProperties)
		{
			if (roomProperties == null || !roomProperties.Contains("empress.coin.cfg") || !roomProperties.Contains("empress.coin.spawn"))
			{
				return;
			}
			string value = roomProperties["empress.coin.cfg"] as string;
			string value2 = roomProperties["empress.coin.spawn"] as string;
			string value3 = (roomProperties.Contains("empress.coin.picked") ? (roomProperties["empress.coin.picked"] as string) : null);
			if (EmpressCoinWire.EmpressTryParseConfig(value, out var settings) && EmpressCoinWire.EmpressTryParseSpawn(value2, out var sessionToken, out var sceneName, out var spawns))
			{
				HashSet<int> pickedCoins = new HashSet<int>();
				if (!string.IsNullOrWhiteSpace(value3) && EmpressCoinWire.EmpressTryParsePicked(value3, out var sessionToken2, out var pickedIds) && sessionToken2 == sessionToken)
				{
					pickedCoins = pickedIds;
				}
				empressRuntime?.EmpressConsumeSyncedState(settings, sessionToken, sceneName, spawns, pickedCoins);
			}
		}
	}
	internal sealed class EmpressCoinRuntime : MonoBehaviour
	{
		private static readonly Vector2[] EmpressSpawnProbeOffsets = (Vector2[])(object)new Vector2[9]
		{
			Vector2.zero,
			new Vector2(0.45f, 0f),
			new Vector2(-0.45f, 0f),
			new Vector2(0f, 0.45f),
			new Vector2(0f, -0.45f),
			new Vector2(0.32f, 0.32f),
			new Vector2(-0.32f, 0.32f),
			new Vector2(0.32f, -0.32f),
			new Vector2(-0.32f, -0.32f)
		};

		private readonly Dictionary<int, EmpressCoinSceneCoin> empressSceneCoins = new Dictionary<int, EmpressCoinSceneCoin>();

		private readonly Dictionary<int, EmpressCoinSpawnPoint> empressSpawnLookup = new Dictionary<int, EmpressCoinSpawnPoint>();

		private readonly List<EmpressCoinSpawnPoint> empressSpawnPoints = new List<EmpressCoinSpawnPoint>();

		private HashSet<int> empressPickedCoins = new HashSet<int>();

		private EmpressCoinPlugin empressPlugin;

		private EmpressCoinAssets empressAssets;

		private EmpressCoinRelay empressRelay;

		private Coroutine empressSceneInitRoutine;

		private GameObject empressSceneRoot;

		private int empressSceneSerial;

		private int empressAppliedSceneHandle = -1;

		private string empressSessionToken = string.Empty;

		private string empressSceneName = string.Empty;

		private EmpressCoinAuthoritySettings empressCurrentSettings;

		private EmpressCoinAuthoritySettings empressPendingSettings;

		private string empressPendingSessionToken = string.Empty;

		private string empressPendingSceneName = string.Empty;

		private List<EmpressCoinSpawnPoint> empressPendingSpawns = new List<EmpressCoinSpawnPoint>();

		private HashSet<int> empressPendingPickedCoins = new HashSet<int>();

		private bool empressPendingStateAvailable;

		private float empressNextRelayAuditTime;

		private float empressNextPickupScanTime;

		private int EmpressBlockedSpawnMask => LayerMask.GetMask(new string[2] { "Player", "Enemy" });

		private int EmpressFloorSpawnMask
		{
			get
			{
				int mask = LayerMask.GetMask(new string[1] { "Default" });
				if (mask == 0)
				{
					return -1;
				}
				return mask;
			}
		}

		internal void EmpressBindPlugin(EmpressCoinPlugin plugin)
		{
			empressPlugin = plugin;
			if (empressAssets == null && (Object)(object)empressPlugin != (Object)null)
			{
				empressAssets = new EmpressCoinAssets(empressPlugin);
			}
		}

		private void Awake()
		{
			((Component)this).transform.SetParent((Transform)null, true);
			((Object)this).hideFlags = (HideFlags)61;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		private void OnEnable()
		{
			SceneManager.sceneLoaded += EmpressOnSceneLoaded;
			EmpressScheduleSceneInit();
		}

		private void OnDisable()
		{
			SceneManager.sceneLoaded -= EmpressOnSceneLoaded;
		}

		private void Update()
		{
			((Component)this).transform.SetParent((Transform)null, true);
			((Object)this).hideFlags = (HideFlags)61;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			if (!((Object)(object)empressPlugin == (Object)null))
			{
				if (Time.unscaledTime >= empressNextRelayAuditTime)
				{
					empressNextRelayAuditTime = Time.unscaledTime + 0.25f;
					EmpressAuditSceneState();
				}
				if (Time.unscaledTime >= empressNextPickupScanTime)
				{
					empressNextPickupScanTime = Time.unscaledTime + 0.1f;
					EmpressScanForLocalPickups();
				}
			}
		}

		internal void EmpressConsumeSyncedState(EmpressCoinAuthoritySettings settings, string sessionToken, string sceneName, List<EmpressCoinSpawnPoint> spawns, HashSet<int> pickedCoins)
		{
			empressPendingSettings = settings;
			empressPendingSessionToken = sessionToken ?? string.Empty;
			empressPendingSceneName = sceneName ?? string.Empty;
			empressPendingSpawns = ((spawns != null) ? new List<EmpressCoinSpawnPoint>(spawns.OrderBy((EmpressCoinSpawnPoint spawn) => spawn.EmpressCoinId)) : new List<EmpressCoinSpawnPoint>());
			empressPendingPickedCoins = ((pickedCoins != null) ? new HashSet<int>(pickedCoins) : new HashSet<int>());
			empressPendingStateAvailable = true;
			EmpressTryApplyPendingState();
		}

		internal void EmpressTryResolvePickupAsAuthority(int coinId, int requesterPhotonViewId, Player sender)
		{
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			empressPlugin.EmpressDebug("resolve pickup for coin " + coinId + " token=" + (string.IsNullOrWhiteSpace(empressSessionToken) ? "EMPTY" : "SET") + " enabled=" + empressCurrentSettings.EmpressEnabled + " spawnCount=" + empressSpawnLookup.Count + ".");
			if (string.IsNullOrWhiteSpace(empressSessionToken))
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because the session token was empty.");
				return;
			}
			if (!empressCurrentSettings.EmpressEnabled)
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because the current session is inactive.");
				return;
			}
			if (empressPickedCoins.Contains(coinId))
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because it was already collected.");
				return;
			}
			if (!empressSpawnLookup.TryGetValue(coinId, out var value))
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because no authoritative spawn was found.");
				return;
			}
			PlayerAvatar val = EmpressResolvePickupPlayer(requesterPhotonViewId, sender);
			if ((Object)(object)val == (Object)null)
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because the requesting player was invalid.");
				return;
			}
			if (EmpressCoinAccess.EmpressPlayerDisabled(val))
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because the requesting player is disabled.");
				return;
			}
			Vector3 val2 = value.EmpressPosition;
			if (empressSceneCoins.TryGetValue(coinId, out var value2) && (Object)(object)value2 != (Object)null)
			{
				val2 = value2.EmpressPickupPosition;
			}
			float num = empressCurrentSettings.EmpressPickupRange + Mathf.Max(0.25f, empressAssets.EmpressRadius);
			float num2 = Vector3.Distance(((Component)val).transform.position, val2);
			if (num2 > num)
			{
				empressPlugin.EmpressDebug("pickup rejected for coin " + coinId + " because the requester was too far away at " + num2.ToString("0.##", CultureInfo.InvariantCulture) + ".");
				return;
			}
			empressPickedCoins.Add(coinId);
			int num3 = EmpressCoinAccess.EmpressSetRunCurrency(EmpressCoinAccess.EmpressGetRunCurrency() + empressCurrentSettings.EmpressCoinValueK);
			empressPlugin.EmpressDebug("pickup validated for coin " + coinId + ". Team currency is now " + num3 + "K.");
			if ((Object)(object)empressRelay != (Object)null)
			{
				empressRelay.EmpressBroadcastPickupConfirmed(empressSessionToken, coinId, val2, empressCurrentSettings.EmpressCoinValueK, requesterPhotonViewId);
				empressRelay.EmpressPublishPickedState(empressSessionToken, empressPickedCoins);
			}
			else
			{
				EmpressHandlePickupConfirmed(empressSessionToken, coinId, val2, empressCurrentSettings.EmpressCoinValueK, requesterPhotonViewId);
			}
		}

		internal void EmpressHandlePickupConfirmed(string sessionToken, int coinId, Vector3 pickupPosition, int rewardK, int pickerPhotonViewId)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!string.Equals(sessionToken, empressSessionToken, StringComparison.Ordinal))
			{
				return;
			}
			bool num = empressPickedCoins.Add(coinId);
			bool flag = EmpressRemoveCoin(coinId);
			if (num || flag)
			{
				if (flag && empressAssets != null && (Object)(object)empressPlugin != (Object)null)
				{
					empressAssets.EmpressPlayPickupSound(pickupPosition, empressPlugin.EmpressConfig.EmpressOptionalSoundVolume.Value);
				}
				empressPlugin.EmpressDebug("pickup synced for coin " + coinId + " from player view " + pickerPhotonViewId + " with reward " + rewardK + "K.");
			}
		}

		internal void EmpressHandleMasterClientSwitch()
		{
			empressPlugin.EmpressInfo("master client changed. EmpressCoin is refreshing the authoritative room state.");
			empressRelay?.EmpressRefreshCurrentState();
			EmpressTryApplyPendingState();
		}

		private void EmpressOnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			EmpressScheduleSceneInit();
		}

		private void EmpressScheduleSceneInit()
		{
			empressSceneSerial++;
			if (empressSceneInitRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(empressSceneInitRoutine);
				empressSceneInitRoutine = null;
			}
			empressRelay = null;
			empressPendingStateAvailable = false;
			empressPendingSessionToken = string.Empty;
			empressPendingSceneName = string.Empty;
			empressPendingSpawns = new List<EmpressCoinSpawnPoint>();
			empressPendingPickedCoins = new HashSet<int>();
			EmpressClearSceneState();
			empressSceneInitRoutine = ((MonoBehaviour)this).StartCoroutine(EmpressSceneInitAsync(empressSceneSerial));
		}

		private IEnumerator EmpressSceneInitAsync(int serial)
		{
			float timeoutAt = Time.unscaledTime + 30f;
			while (serial == empressSceneSerial)
			{
				if (!EmpressCoinAccess.EmpressIsRunLevel())
				{
					empressSceneInitRoutine = null;
					yield break;
				}
				empressAssets?.EmpressEnsureBundle();
				empressAssets?.EmpressWarmupSound((MonoBehaviour)(object)this);
				EmpressEnsureRelay();
				empressRelay?.EmpressRefreshCurrentState();
				if (EmpressTryApplyPendingState())
				{
					empressSceneInitRoutine = null;
					yield break;
				}
				LevelGenerator val = EmpressCoinAccess.EmpressFindFirstSceneObject<LevelGenerator>();
				if ((Object)(object)val != (Object)null && EmpressCoinAccess.EmpressLevelGenerated(val) && (Object)(object)empressRelay != (Object)null && (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient))
				{
					Scene val2 = EmpressCoinAccess.EmpressActiveScene();
					if (empressAppliedSceneHandle != ((Scene)(ref val2)).handle)
					{
						EmpressCreateAuthoritativeSceneState(val, ((Scene)(ref val2)).name);
					}
					empressSceneInitRoutine = null;
					yield break;
				}
				if (Time.unscaledTime >= timeoutAt)
				{
					EmpressCoinPlugin empressCoinPlugin = empressPlugin;
					Scene val3 = EmpressCoinAccess.EmpressActiveScene();
					empressCoinPlugin.EmpressDebug("scene initialization timed out for " + ((Scene)(ref val3)).name + ".");
					empressSceneInitRoutine = null;
					yield break;
				}
				yield return (object)new WaitForSecondsRealtime(0.25f);
			}
			empressSceneInitRoutine = null;
		}

		private void EmpressAuditSceneState()
		{
			if (!EmpressCoinAccess.EmpressIsRunLevel())
			{
				if (empressAppliedSceneHandle != -1 || empressSceneCoins.Count > 0)
				{
					EmpressClearSceneState();
				}
			}
			else
			{
				empressAssets?.EmpressEnsureBundle();
				empressAssets?.EmpressWarmupSound((MonoBehaviour)(object)this);
				EmpressEnsureRelay();
				EmpressTryApplyPendingState();
			}
		}

		private void EmpressEnsureRelay()
		{
			empressRelay = EmpressCoinRelay.EmpressEnsureAttached(((Component)this).gameObject, this);
			empressRelay?.EmpressAttachRuntime(this);
		}

		private bool EmpressTryApplyPendingState()
		{
			//IL_000a: 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)
			if (!empressPendingStateAvailable)
			{
				return false;
			}
			Scene val = EmpressCoinAccess.EmpressActiveScene();
			if (!((Scene)(ref val)).IsValid() || !string.Equals(((Scene)(ref val)).name, empressPendingSceneName, StringComparison.Ordinal))
			{
				return false;
			}
			LevelGenerator val2 = EmpressCoinAccess.EmpressFindFirstSceneObject<LevelGenerator>();
			if ((Object)(object)val2 == (Object)null || !EmpressCoinAccess.EmpressLevelGenerated(val2))
			{
				return false;
			}
			if (empressAppliedSceneHandle != ((Scene)(ref val)).handle || !string.Equals(empressSessionToken, empressPendingSessionToken, StringComparison.Ordinal) || !empressCurrentSettings.Equals(empressPendingSettings) || empressSpawnPoints.Count != empressPendingSpawns.Count)
			{
				empressSessionToken = empressPendingSessionToken;
				empressSceneName = empressPendingSceneName;
				empressCurrentSettings = empressPendingSettings;
				empressPickedCoins = new HashSet<int>(empressPendingPickedCoins);
				empressSpawnPoints.Clear();
				empressSpawnPoints.AddRange(empressPendingSpawns);
				empressSpawnLookup.Clear();
				foreach (EmpressCoinSpawnPoint empressSpawnPoint in empressSpawnPoints)
				{
					empressSpawnLookup[empressSpawnPoint.EmpressCoinId] = empressSpawnPoint;
				}
				EmpressRebuildSceneCoins();
				empressAppliedSceneHandle = ((Scene)(ref val)).handle;
				empressPlugin.EmpressDebug("scene sync applied for " + empressSceneName + " with " + empressSceneCoins.Count + " visible coins and " + empressPickedCoins.Count + " picked.");
			}
			else
			{
				foreach (int item in new HashSet<int>(empressPendingPickedCoins))
				{
					if (empressPickedCoins.Add(item))
					{
						EmpressRemoveCoin(item);
					}
				}
			}
			empressPendingStateAvailable = false;
			return true;
		}

		private void EmpressCreateAuthoritativeSceneState(LevelGenerator levelGenerator, string sceneName)
		{
			if ((Object)(object)levelGenerator == (Object)null || (Object)(object)empressPlugin == (Object)null || (Object)(object)empressRelay == (Object)null)
			{
				return;
			}
			bool assetsReady = empressAssets != null && empressAssets.EmpressEnsureBundle();
			EmpressCoinAuthoritySettings settings = empressPlugin.EmpressConfig.EmpressCreateAuthoritySettings(assetsReady);
			List<EmpressCoinSpawnPoint> list = (settings.EmpressEnabled ? EmpressBuildSpawnPlan(levelGenerator, settings) : new List<EmpressCoinSpawnPoint>());
			string sessionToken = Guid.NewGuid().ToString("N");
			if (settings.EmpressEnabled)
			{
				if (list.Count > 0)
				{
					empressPlugin.EmpressInfo("scene " + sceneName + " armed with " + list.Count + " coins.");
				}
				else
				{
					empressPlugin.EmpressWarn("scene " + sceneName + " produced no valid coin placements.");
				}
			}
			empressPlugin.EmpressDebug("host published " + list.Count + " coins for scene " + sceneName + ".");
			empressRelay.EmpressPublishSession(settings, sessionToken, sceneName, list, new HashSet<int>());
		}

		private List<EmpressCoinSpawnPoint> EmpressBuildSpawnPlan(LevelGenerator levelGenerator, EmpressCoinAuthoritySettings settings)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			List<LevelPoint> list = (((Object)(object)levelGenerator != (Object)null && levelGenerator.LevelPathPoints != null && levelGenerator.LevelPathPoints.Count > 0) ? levelGenerator.LevelPathPoints.Where((LevelPoint point) => (Object)(object)point != (Object)null).Distinct().ToList() : (from point in EmpressCoinAccess.EmpressFindSceneObjects<LevelPoint>()
				where (Object)(object)point != (Object)null
				select point).Distinct().ToList()).Where((LevelPoint point) => !EmpressCoinAccess.EmpressIsStartRoomPoint(point)).Where(delegate(LevelPoint point)
			{
				RoomVolume val = EmpressCoinAccess.EmpressGetRoom(point);
				return (Object)(object)val != (Object)null && !EmpressCoinAccess.EmpressRoomIsTruck(val) && !EmpressCoinAccess.EmpressRoomIsExtraction(val);
			}).ToList();
			Scene activeScene = SceneManager.GetActiveScene();
			Random random = new Random(HashCode.Combine(((Scene)(ref activeScene)).name, list.Count, Time.frameCount, PhotonNetwork.InRoom ? PhotonNetwork.ServerTimestamp : Environment.TickCount));
			List<EmpressCoinSpawnPoint> list2 = EmpressBuildCandidateSpawnPoints(list, random);
			int num = settings.EmpressResolveSpawnCount(list2.Count);
			if (num <= 0 || list2.Count == 0)
			{
				return new List<EmpressCoinSpawnPoint>();
			}
			float num2 = Mathf.Max(1.35f, empressAssets.EmpressRadius * 3.25f);
			switch (settings.EmpressDensityPreset)
			{
			case EmpressCoinDensityPreset.Min:
				num2 *= 1.35f;
				break;
			case EmpressCoinDensityPreset.Max:
				num2 *= 0.7f;
				break;
			}
			return EmpressSelectSpawnPoints(list2, num, num2, random);
		}

		private List<EmpressCoinSpawnPoint> EmpressBuildCandidateSpawnPoints(List<LevelPoint> eligiblePoints, Random random)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			List<EmpressCoinSpawnPoint> list = new List<EmpressCoinSpawnPoint>();
			if (eligiblePoints.Count == 0)
			{
				return list;
			}
			HashSet<LevelPoint> hashSet = new HashSet<LevelPoint>(eligiblePoints);
			foreach (LevelPoint item2 in eligiblePoints.OrderBy((LevelPoint _) => random.Next()))
			{
				if (EmpressTryBuildSpawn(((Component)item2).transform.position, random, 1.6f, out var position, out var yaw))
				{
					list.Add(new EmpressCoinSpawnPoint(list.Count, position, yaw));
				}
			}
			HashSet<ulong> hashSet2 = new HashSet<ulong>();
			foreach (LevelPoint eligiblePoint in eligiblePoints)
			{
				foreach (LevelPoint item3 in EmpressCoinAccess.EmpressGetConnectedPoints(eligiblePoint))
				{
					if (!((Object)(object)item3 == (Object)null) && !((Object)(object)item3 == (Object)(object)eligiblePoint) && hashSet.Contains(item3))
					{
						ulong item = EmpressBuildSegmentKey(eligiblePoint, item3);
						if (hashSet2.Add(item))
						{
							EmpressAddSegmentCandidates(((Component)eligiblePoint).transform.position, ((Component)item3).transform.position, list, random);
						}
					}
				}
			}
			if (list.Count < eligiblePoints.Count * 2)
			{
				foreach (LevelPoint item4 in eligiblePoints.OrderBy((LevelPoint _) => random.Next()))
				{
					for (int i = 0; i < 2; i++)
					{
						double num = random.NextDouble() * Math.PI * 2.0;
						float num2 = 0.9f + (float)random.NextDouble() * 0.9f;
						Vector3 anchorSeed = ((Component)item4).transform.position + new Vector3(Mathf.Cos((float)num) * num2, 0f, Mathf.Sin((float)num) * num2);
						if (EmpressTryBuildSpawn(anchorSeed, random, 1.9f, out var position2, out var yaw2))
						{
							list.Add(new EmpressCoinSpawnPoint(list.Count, position2, yaw2));
						}
					}
				}
			}
			return list;
		}

		private void EmpressAddSegmentCandidates(Vector3 from, Vector3 to, List<EmpressCoinSpawnPoint> candidates, Random random)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Distance(from, to);
			if (num < 2.5f)
			{
				return;
			}
			int num2 = Mathf.Clamp(Mathf.FloorToInt(num / 2.75f), 1, 6);
			Vector3 val = to - from;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(0f - normalized.z, 0f, normalized.x);
			for (int i = 0; i < num2; i++)
			{
				float num3 = ((float)i + 1f) / ((float)num2 + 1f);
				float num4 = Mathf.Min(0.45f, num * 0.08f);
				float num5 = ((i % 2 == 0) ? 1f : (-1f));
				float num6 = 0.35f + (float)random.NextDouble() * 0.65f;
				Vector3 anchorSeed = Vector3.Lerp(from, to, num3) + val2 * (num4 * num5 * num6);
				if (EmpressTryBuildSpawn(anchorSeed, random, 1.45f, out var position, out var yaw))
				{
					candidates.Add(new EmpressCoinSpawnPoint(candidates.Count, position, yaw));
				}
			}
		}

		private List<EmpressCoinSpawnPoint> EmpressSelectSpawnPoints(List<EmpressCoinSpawnPoint> candidates, int targetCount, float minSpacing, Random random)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			List<EmpressCoinSpawnPoint> list = candidates.OrderBy((EmpressCoinSpawnPoint _) => random.Next()).ToList();
			List<EmpressCoinSpawnPoint> list2 = new List<EmpressCoinSpawnPoint>(Mathf.Min(targetCount, list.Count));
			EmpressSelectSpawnPass(list, list2, targetCount, minSpacing);
			if (list2.Count < targetCount)
			{
				EmpressSelectSpawnPass(list, list2, targetCount, minSpacing * 0.65f);
			}
			if (list2.Count < targetCount)
			{
				EmpressSelectSpawnPass(list, list2, targetCount, 0.01f);
			}
			for (int i = 0; i < list2.Count; i++)
			{
				EmpressCoinSpawnPoint empressCoinSpawnPoint = list2[i];
				list2[i] = new EmpressCoinSpawnPoint(i, empressCoinSpawnPoint.EmpressPosition, empressCoinSpawnPoint.EmpressYaw);
			}
			return list2;
		}

		private static void EmpressSelectSpawnPass(List<EmpressCoinSpawnPoint> candidates, List<EmpressCoinSpawnPoint> selectedSpawns, int targetCount, float minSpacing)
		{
			float requiredSpacing = Mathf.Max(0.01f, minSpacing);
			foreach (EmpressCoinSpawnPoint candidate in candidates)
			{
				if (selectedSpawns.Count >= targetCount)
				{
					break;
				}
				if (!selectedSpawns.Any((EmpressCoinSpawnPoint existing) => Vector3.Distance(existing.EmpressPosition, candidate.EmpressPosition) < requiredSpacing))
				{
					selectedSpawns.Add(candidate);
				}
			}
		}

		private static ulong EmpressBuildSegmentKey(LevelPoint first, LevelPoint second)
		{
			int num = (((Object)(object)first != (Object)null) ? ((Object)first).GetInstanceID() : 0);
			int num2 = (((Object)(object)second != (Object)null) ? ((Object)second).GetInstanceID() : 0);
			int num3 = ((num < num2) ? num : num2);
			uint num4 = (uint)((num < num2) ? num2 : num);
			return ((ulong)(uint)num3 << 32) | num4;
		}

		private bool EmpressTryBuildSpawn(Vector3 anchorSeed, Random random, float navMeshRadius, out Vector3 position, out float yaw)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			yaw = 0f;
			if (empressAssets == null)
			{
				return false;
			}
			float num = Mathf.Max(0.35f, empressAssets.EmpressRadius * 1.45f);
			float num2 = Mathf.Max(4f, empressAssets.EmpressHeight + 2f);
			float num3 = num2 + Mathf.Max(8f, empressAssets.EmpressHeight + 4f);
			float num4 = Mathf.Max(empressAssets.EmpressFloorOffset, 0.18f) + 0.06f;
			NavMeshHit val2 = default(NavMeshHit);
			RaycastHit val3 = default(RaycastHit);
			foreach (Vector2 item in EmpressSpawnProbeOffsets.OrderBy((Vector2 _) => random.Next()))
			{
				Vector3 val = anchorSeed + new Vector3(item.x * num, 0f, item.y * num);
				if (!NavMesh.SamplePosition(val, ref val2, navMeshRadius, -1))
				{
					continue;
				}
				val = ((NavMeshHit)(ref val2)).position;
				if ((Physics.Raycast(val + Vector3.up * num2, Vector3.down, ref val3, num3, EmpressFloorSpawnMask, (QueryTriggerInteraction)1) || Physics.Raycast(val + Vector3.up * num2, Vector3.down, ref val3, num3, -1, (QueryTriggerInteraction)1)) && !(((RaycastHit)(ref val3)).normal.y < 0.45f))
				{
					Vector3 val4 = ((RaycastHit)(ref val3)).point + Vector3.up * num4;
					Vector3 val5 = val4 + Vector3.up * 0.05f;
					Vector3 val6 = val4 + Vector3.up * Mathf.Max(empressAssets.EmpressHeight * 0.9f, 0.35f);
					if (EmpressBlockedSpawnMask == 0 || !Physics.CheckCapsule(val5, val6, Mathf.Max(empressAssets.EmpressRadius * 0.55f, 0.12f), EmpressBlockedSpawnMask, (QueryTriggerInteraction)1))
					{
						position = val4;
						yaw = (float)random.NextDouble() * 360f;
						return true;
					}
				}
			}
			return false;
		}

		private PlayerAvatar EmpressResolvePickupPlayer(int requesterPhotonViewId, Player sender)
		{
			if (!PhotonNetwork.InRoom || sender == null)
			{
				if (requesterPhotonViewId > 0)
				{
					PlayerAvatar val = EmpressCoinAccess.EmpressFindPlayerByPhotonViewId(requesterPhotonViewId);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				return EmpressCoinAccess.EmpressFindLocalPlayer();
			}
			PlayerAvatar val2 = EmpressCoinAccess.EmpressFindPlayerByPhotonViewId(requesterPhotonViewId);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			PhotonView val3 = (((Object)(object)val2.photonView != (Object)null) ? val2.photonView : ((Component)val2).GetComponent<PhotonView>());
			if ((Object)(object)val3 == (Object)null || val3.Owner == null || val3.Owner.ActorNumber != sender.ActorNumber)
			{
				return null;
			}
			return val2;
		}

		private void EmpressRebuildSceneCoins()
		{
			//IL_0068: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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)
			EmpressDestroySceneCoins();
			if (!empressCurrentSettings.EmpressEnabled || empressAssets == null || !empressAssets.EmpressHasPrefab)
			{
				return;
			}
			EmpressEnsureSceneRoot();
			foreach (EmpressCoinSpawnPoint empressSpawnPoint in empressSpawnPoints)
			{
				if (!empressPickedCoins.Contains(empressSpawnPoint.EmpressCoinId))
				{
					GameObject val = empressAssets.EmpressInstantiateCoin(null, empressSpawnPoint.EmpressPosition, Quaternion.Euler(0f, empressSpawnPoint.EmpressYaw, 0f));
					if (!((Object)(object)val == (Object)null))
					{
						val.transform.SetParent((Transform)null, true);
						SceneManager.MoveGameObjectToScene(val, EmpressCoinAccess.EmpressActiveScene());
						Vector3 empressPickupPosition = EmpressLiftCoinAboveFloor(val);
						val.transform.SetParent(empressSceneRoot.transform, true);
						EmpressCoinSceneCoin empressCoinSceneCoin = val.GetComponent<EmpressCoinSceneCoin>() ?? val.AddComponent<EmpressCoinSceneCoin>();
						empressCoinSceneCoin.EmpressCoinId = empressSpawnPoint.EmpressCoinId;
						empressCoinSceneCoin.EmpressPickupPosition = empressPickupPosition;
						empressSceneCoins[empressSpawnPoint.EmpressCoinId] = empressCoinSceneCoin;
					}
				}
			}
		}

		private void EmpressEnsureSceneRoot()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)empressSceneRoot != (Object)null))
			{
				empressSceneRoot = new GameObject("EmpressCoin.SceneRoot");
				((Object)empressSceneRoot).hideFlags = (HideFlags)1;
				SceneManager.MoveGameObjectToScene(empressSceneRoot, EmpressCoinAccess.EmpressActiveScene());
			}
		}

		private void EmpressScanForLocalPickups()
		{
			//IL_00b5: 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)
			if (empressSceneCoins.Count == 0 || !empressCurrentSettings.EmpressEnabled || (Object)(object)empressRelay == (Object)null)
			{
				return;
			}
			PlayerAvatar val = EmpressCoinAccess.EmpressFindLocalPlayer();
			if ((Object)(object)val == (Object)null || EmpressCoinAccess.EmpressPlayerDisabled(val))
			{
				return;
			}
			PhotonView val2 = (((Object)(object)val.photonView != (Object)null) ? val.photonView : ((Component)val).GetComponent<PhotonView>());
			int requesterPhotonViewId = (((Object)(object)val2 != (Object)null) ? val2.ViewID : 0);
			EmpressCoinSceneCoin empressCoinSceneCoin = null;
			float num = float.MaxValue;
			foreach (EmpressCoinSceneCoin value in empressSceneCoins.Values)
			{
				if (!((Object)(object)value == (Object)null) && !(Time.unscaledTime < value.EmpressNextRequestTime))
				{
					float num2 = Vector3.Distance(((Component)val).transform.position, value.EmpressPickupPosition);
					if (num2 <= empressCurrentSettings.EmpressPickupRange && num2 < num)
					{
						empressCoinSceneCoin = value;
						num = num2;
					}
				}
			}
			if (!((Object)(object)empressCoinSceneCoin == (Object)null))
			{
				empressCoinSceneCoin.EmpressNextRequestTime = Time.unscaledTime + 0.75f;
				empressPlugin.EmpressDebug("pickup requested for coin " + empressCoinSceneCoin.EmpressCoinId + " at distance " + num.ToString("0.##", CultureInfo.InvariantCulture) + ".");
				empressRelay.EmpressRequestPickup(empressCoinSceneCoin.EmpressCoinId, requesterPhotonViewId);
			}
		}

		private bool EmpressRemoveCoin(int coinId)
		{
			if (!empressSceneCoins.TryGetValue(coinId, out var value))
			{
				return false;
			}
			empressSceneCoins.Remove(coinId);
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value).gameObject);
			}
			return true;
		}

		private void EmpressClearSceneState()
		{
			EmpressDestroySceneCoins();
			empressSpawnLookup.Clear();
			empressSpawnPoints.Clear();
			empressPickedCoins.Clear();
			empressSessionToken = string.Empty;
			empressSceneName = string.Empty;
			empressAppliedSceneHandle = -1;
			empressCurrentSettings = default(EmpressCoinAuthoritySettings);
		}

		private void EmpressDestroySceneCoins()
		{
			foreach (EmpressCoinSceneCoin value in empressSceneCoins.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			empressSceneCoins.Clear();
			if ((Object)(object)empressSceneRoot != (Object)null)
			{
				Object.Destroy((Object)(object)empressSceneRoot);
				empressSceneRoot = null;
			}
		}

		private Vector3 EmpressLiftCoinAboveFloor(GameObject coinObject)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_0125: 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_0109: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)coinObject == (Object)null || empressAssets == null)
			{
				return Vector3.zero;
			}
			Vector3 position = coinObject.transform.position;
			float num = Mathf.Max(2f, empressAssets.EmpressHeight + 1.5f);
			float num2 = num + Mathf.Max(6f, empressAssets.EmpressHeight + 3f);
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(position + Vector3.up * num, Vector3.down, ref val, num2, -1, (QueryTriggerInteraction)1))
			{
				return position;
			}
			if (!EmpressTryGetCoinBounds(coinObject, out var bounds))
			{
				coinObject.transform.position = ((RaycastHit)(ref val)).point + Vector3.up * (Mathf.Max(empressAssets.EmpressFloorOffset, 0.14f) + 0.05f);
				return coinObject.transform.position;
			}
			float num3 = ((RaycastHit)(ref val)).point.y + 0.05f - ((Bounds)(ref bounds)).min.y;
			if (num3 > 0f)
			{
				Transform transform = coinObject.transform;
				transform.position += Vector3.up * num3;
			}
			return coinObject.transform.position;
		}

		private static bool EmpressTryGetCoinBounds(GameObject coinObject, out Bounds bounds)
		{
			//IL_0001: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			if ((Object)(object)coinObject == (Object)null)
			{
				return false;
			}
			bool flag = false;
			Renderer[] componentsInChildren = coinObject.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
			Collider[] componentsInChildren2 = coinObject.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if (!flag)
				{
					bounds = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
			}
			return flag;
		}
	}
}