Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Coins v1.0.0
EmpressCoin.dll
Decompiled a month agousing 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; } } }