using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ItemSpawnSync.Core; using ItemSpawnSync.Data; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Peak; using Photon.Pun; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.flonou.Peak-ItemSpawnSync")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.9.4.0")] [assembly: AssemblyInformationalVersion("0.9.4+029ec5c3f80bb7881d77c7348208025a66eb7575")] [assembly: AssemblyProduct("com.github.flonou.Peak-ItemSpawnSync")] [assembly: AssemblyTitle("ItemSpawnSync")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.9.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace ItemSpawnSync { [BepInPlugin("com.github.flonou.Peak-ItemSpawnSync", "ItemSpawnSync", "0.9.4")] public class Plugin : BaseUnityPlugin { public bool EnableKeyTrigger = true; public ConfigEntry? DisableSpawningConfig; public ConfigEntry? FileNameConfig; public ConfigEntry? LoadDataKeyConfig; public ConfigEntry? ExportLootDataKeyConfig; public ConfigEntry? SaveDataKeyConfig; public ConfigEntry? SpawnIfNoDataFoundConfig; public ConfigEntry? TriggerSpawnKeyConfig; public ConfigEntry? ImportLootDataKeyConfig; private static string? dataDirectory; private Harmony? harmony; private static readonly JsonSerializerSettings jsonSettings = new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1, Formatting = (Formatting)0, ContractResolver = (IContractResolver)(object)new ContractResolver() }; public const string Id = "com.github.flonou.Peak-ItemSpawnSync"; public static Plugin? Instance { get; private set; } public bool IsSpawnDataLocked => SpawnerSyncManager.Instance.IsDataLocked; public KeyboardShortcut LoadDataKey => LoadDataKeyConfig.Value; public static ManualLogSource? Log { get; private set; } public KeyboardShortcut SaveDataKey => SaveDataKeyConfig.Value; public KeyboardShortcut TriggerSpawnKey => TriggerSpawnKeyConfig.Value; public KeyboardShortcut ExportLootDataKey => ExportLootDataKeyConfig.Value; public KeyboardShortcut ImportLootDataKey => ImportLootDataKeyConfig.Value; public static string DataDirectory => dataDirectory; public static string Name => "ItemSpawnSync"; public static string Version => "0.9.4"; public event Action? OnSpawnDataSaved; public event Action>? OnSpawnersTriggered; public event Action>? OnSpawnDataSpawnedInLevel; public event Action? OnSpawnDataLoaded; public string GetSpawnDataAsJson() { MapSpawnerData currentMapData = SpawnerSyncManager.Instance.CurrentMapData; return JsonConvert.SerializeObject((object)currentMapData); } public bool LoadSpawnDataInCurrentLevel(MapSpawnerData data, bool lockData = false) { bool flag = SpawnerSyncManager.Instance.LoadMapSpawnerDataInCurrentLevel(data, lockData); if (flag) { Log.LogMessage((object)($"Loaded spawn data with {data.Spawners.Count} spawners" + (lockData ? " (LOCKED)" : ""))); } if (SpawnerSyncManager.Instance.DisableSpawning) { SpawnerSyncManager.Instance.SpawnItemsFromStartSpawners(); } return flag; } public MapSpawnerData? LoadSpawnDataFromFile(string filename) { try { string text = Path.Combine(dataDirectory, filename); if (!File.Exists(text)) { Log.LogError((object)("Spawn data file not found: " + text)); return null; } string text2 = File.ReadAllText(text); MapSpawnerData mapSpawnerData = JsonConvert.DeserializeObject(text2); if (mapSpawnerData != null) { Log.LogMessage((object)("Loaded spawn data from: " + text)); Log.LogMessage((object)$" Spawners: {mapSpawnerData.Spawners.Count}"); Log.LogMessage((object)$" Items: {CountTotalItems(mapSpawnerData)}"); } else { Log.LogError((object)("Failed to deserialize spawn data from json " + text2)); } this.OnSpawnDataLoaded?.Invoke(text); return mapSpawnerData; } catch (Exception ex) { Log.LogError((object)("Failed to load spawn data: " + ex.Message)); return null; } } public bool LoadSpawnDataFromJson(string json, bool lockData = false) { try { MapSpawnerData mapSpawnerData = JsonConvert.DeserializeObject(json); if (mapSpawnerData != null) { return true; } Log.LogError((object)("Could not deserialize spawn data from JSON: " + json)); return false; } catch (Exception ex) { Log.LogError((object)("Failed to load spawn data from JSON: " + ex.Message)); return false; } } public void SaveCurrentSpawnData() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) try { MapSpawnerData mapSpawnerData = SpawnerSyncManager.Instance?.CurrentMapData; if (mapSpawnerData == null || mapSpawnerData.Spawners.Count == 0) { Log.LogWarning((object)"No spawn data to save. Start capture first and trigger spawners."); return; } Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; string path = $"{name}_spawn_data_{DateTime.Now:yyyyMMdd_HHmmss}.json"; string text = Path.Combine(dataDirectory, path); string contents = JsonConvert.SerializeObject((object)mapSpawnerData, (Formatting)1, jsonSettings); File.WriteAllText(text, contents); Log.LogMessage((object)("Saved spawn data to: " + text)); Log.LogMessage((object)$" Spawners: {mapSpawnerData.Spawners.Count}"); Log.LogMessage((object)$" Items: {CountTotalItems(mapSpawnerData)}"); this.OnSpawnDataSaved?.Invoke(text); } catch (Exception ex) { Log.LogError((object)("Failed to save spawn data: " + ex.Message)); } } protected void Awake() { //IL_0035: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; TriggerSpawnKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "TriggerSpawnKey", new KeyboardShortcut((KeyCode)285, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to trigger all spawners"); SaveDataKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "SaveDataKey", new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to save current spawn data to file"); LoadDataKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "LoadDataKey", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to load spawn data from file"); ExportLootDataKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "ExportLootDataKey", new KeyboardShortcut((KeyCode)288, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to export loot data to file"); ImportLootDataKeyConfig = ((BaseUnityPlugin)this).Config.Bind("Controls", "ImportLootDataKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to import loot data from file"); DisableSpawningConfig = ((BaseUnityPlugin)this).Config.Bind("General", "DisableSpawning", false, "If true, prevents any item spawning unless from loaded data"); SpawnIfNoDataFoundConfig = ((BaseUnityPlugin)this).Config.Bind("General", "SpawnIfNoDataFound", false, "If true, spawners without loaded data will spawn normally"); FileNameConfig = ((BaseUnityPlugin)this).Config.Bind("General", "DefaultFileName", "spawn_data.json", "Default filename to load spawn data."); dataDirectory = Path.Combine(Paths.ConfigPath, "ItemSpawnSync"); Directory.CreateDirectory(dataDirectory); SpawnerSyncManager.Instance.Initialize(Log); SpawnerSyncManager.Instance.EnableKeyTrigger = EnableKeyTrigger; SpawnerSyncManager.Instance.DisableSpawning = DisableSpawningConfig.Value; SpawnerSyncManager.Instance.SpawnIfNoDataFound = SpawnIfNoDataFoundConfig.Value; Log.LogMessage((object)("Plugin " + Name + " is loaded!")); Log.LogMessage((object)("Data directory: " + dataDirectory)); harmony = new Harmony(Name); harmony.PatchAll(); Log.LogMessage((object)"Harmony patches applied"); Log.LogMessage((object)"Controls:"); Log.LogMessage((object)$" {TriggerSpawnKey} - Trigger all spawners"); Log.LogMessage((object)$" {SaveDataKey} - Save spawn data to file"); Log.LogMessage((object)$" {LoadDataKey} - Load spawn data from file"); Log.LogMessage((object)$" {ExportLootDataKey} - Export loot data to file"); Log.LogMessage((object)$" {ImportLootDataKey} - Import loot data from file"); SceneManager.sceneUnloaded += OnSceneUnloaded; } protected void OnSceneUnloaded(Scene arg0) { if (((Scene)(ref arg0)).name.StartsWith("Level_")) { SpawnerSyncManager.Instance.ClearSpawnedData(((Scene)(ref arg0)).name); } } protected void Update() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut val = TriggerSpawnKey; if (((KeyboardShortcut)(ref val)).IsDown()) { SpawnerSyncManager.Instance.CaptureSpawns(); } val = SaveDataKey; if (((KeyboardShortcut)(ref val)).IsDown()) { SaveCurrentSpawnData(); } val = LoadDataKey; if (((KeyboardShortcut)(ref val)).IsDown()) { MapSpawnerData mapSpawnerData = LoadSpawnDataFromFile(FileNameConfig.Value); if (mapSpawnerData != null) { LoadSpawnDataInCurrentLevel(mapSpawnerData); } } val = ExportLootDataKey; if (((KeyboardShortcut)(ref val)).IsDown()) { LootDataContainer.ExportLootData(); } val = ImportLootDataKey; if (((KeyboardShortcut)(ref val)).IsDown()) { LootDataContainer.ImportLootData(); } } private int CountTotalItems(MapSpawnerData data) { int num = 0; foreach (SpawnerInstanceData spawner in data.Spawners) { num += spawner.SpawnedItems.Count; } return num; } private void OnDestroy() { Harmony? obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } public void PublishSpawnersTriggered(List spawners) { this.OnSpawnersTriggered?.Invoke(spawners); } public void PublishSpawnDataSpawnedInLevel(List spawners) { this.OnSpawnDataSpawnedInLevel?.Invoke(spawners); } } } namespace ItemSpawnSync.Patches { [HarmonyPatch(typeof(SpawnedItemTracker), "SpawnAndTrackFromItemHistory")] public class SpawnedItemTrackerPatch { private static bool Prefix(SpawnedItemTracker __instance, ref List __result, ref List ____historyFromSave) { if (____historyFromSave == null) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogWarning((object)(((Object)__instance).name + ": _historyFromSave is null, initializing empty list")); } ____historyFromSave = new List(); __result = new List(); return true; } return true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class SpawnedItemTrackerHasSpawnHistoryPatch { private static bool Prefix(SpawnedItemTracker __instance, ref bool __result) { SpawnerSyncManager instance = SpawnerSyncManager.Instance; if ((Object)(object)instance == (Object)null) { return true; } if (instance.UseLoadedSpawnData) { __result = false; return false; } return true; } } [HarmonyPatch] public class SpawnerSpawnItemsPatch { public static event Action>? OnItemsSpawned; private static IEnumerable TargetMethods() { List list = new List(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { IEnumerable collection = from t in assembly.GetTypes() where t.IsClass && !t.IsAbstract && typeof(Spawner).IsAssignableFrom(t) select t; list.AddRange(collection); } catch { } } foreach (Type item in list) { MethodInfo method = item.GetMethod("SpawnItems", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(List) }, null); if (method != null) { yield return method; } } } private static bool Prefix(Spawner __instance, List spawnSpots, ref List __result) { SpawnerSyncManager instance = SpawnerSyncManager.Instance; SpawnedItemTracker val = default(SpawnedItemTracker); if (!((Component)__instance).TryGetComponent(ref val)) { val = ((Component)__instance).gameObject.AddComponent(); val.Init(); } if ((Object)(object)instance == (Object)null) { return true; } if (instance.UseLoadedSpawnData) { if (instance.HasSpawnerData(__instance)) { SpawnerInstanceData spawnerData = instance.GetSpawnerData(__instance); if (spawnerData == null) { __result = new List(); return instance.SpawnIfNoDataFound; } __result = instance.SpawnItemsFromData(__instance, spawnerData); SpawnerSpawnItemsPatch.OnItemsSpawned?.Invoke(__result); return false; } __result = new List(); return instance.SpawnIfNoDataFound; } __result = new List(); if (instance.DisableSpawning) { return instance.CapturingSpawn; } return true; } } } namespace ItemSpawnSync.Data { public class ContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) JsonProperty val = ((DefaultContractResolver)this).CreateProperty(member, memberSerialization); val.Writable = true; val.Readable = true; return val; } protected override List GetSerializableMembers(Type objectType) { if (objectType.Name.Contains("AnonymousType")) { return objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Cast().ToList(); } return (from f in objectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.IsPublic || ((MemberInfo)f).GetCustomAttribute() != null select f).Cast().ToList(); } } public class LootDataContainer { protected static string LootDataFileName = "LootData.json"; public static Dictionary> SpawnData = new Dictionary>(); public static void ImportLootData() { string text = Path.Combine(Plugin.DataDirectory, LootDataFileName); if (!File.Exists(text)) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogError((object)("Loot data file not found at " + text)); } return; } string text2 = File.ReadAllText(text); SpawnData = JsonConvert.DeserializeObject>>(text2) ?? new Dictionary>(); ManualLogSource? log2 = Plugin.Log; if (log2 != null) { log2.LogMessage((object)("Loot data imported from " + text)); } ApplyLootData(); } public static void ExportLootData() { ExtractLootData(); string contents = JsonConvert.SerializeObject((object)SpawnData, (Formatting)1); string text = Path.Combine(Plugin.DataDirectory, LootDataFileName); File.WriteAllText(text, contents); ManualLogSource? log = Plugin.Log; if (log != null) { log.LogMessage((object)("Loot data exported to " + text)); } } private unsafe static void ApplyLootData() { //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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) if (LootData.AllSpawnWeightData == null) { LootData.PopulateLootData(); } if (LootData.AllSpawnWeightData == null) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogError((object)"No loot data found to export."); } return; } Item val = default(Item); foreach (KeyValuePair> spawnDatum in SpawnData) { string key = spawnDatum.Key; foreach (SpawnPool key2 in LootData.AllSpawnWeightData.Keys) { if (!(((object)(*(SpawnPool*)(&key2))/*cast due to .constrained prefix*/).ToString() == key)) { continue; } foreach (KeyValuePair item in spawnDatum.Value) { string itemName = item.Key; int value = item.Value; KeyValuePair keyValuePair = SingletonAsset.Instance.itemLookup.FirstOrDefault((KeyValuePair kvp) => ItemDatabase.TryGetItem(kvp.Key, ref val) && ((Object)((Component)val).gameObject).name == itemName); if (LootData.AllSpawnWeightData[key2].ContainsKey(keyValuePair.Key)) { LootData.AllSpawnWeightData[key2].Remove(keyValuePair.Key); } if (value > 0) { LootData.AllSpawnWeightData[key2].Add(keyValuePair.Key, value); continue; } ManualLogSource? log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("Skipping item " + itemName + " with zero spawn weight in pool " + key)); } } break; } } } private static void ExtractLootData() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (LootData.AllSpawnWeightData == null) { LootData.PopulateLootData(); } if (LootData.AllSpawnWeightData == null) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogError((object)"No loot data found to export."); } return; } Item val = default(Item); foreach (KeyValuePair> allSpawnWeightDatum in LootData.AllSpawnWeightData) { string key = ((object)allSpawnWeightDatum.Key/*cast due to .constrained prefix*/).ToString(); Dictionary dictionary = new Dictionary(); SpawnData.Add(key, dictionary); foreach (KeyValuePair item in allSpawnWeightDatum.Value) { if (ItemDatabase.TryGetItem(item.Key, ref val)) { LootData component = ((Component)val).GetComponent(); int value = item.Value; dictionary.Add(((Object)((Component)val).gameObject).name, value); } } } } } [Serializable] public class SpawnedItemData { public string ItemPrefabName = string.Empty; public Vector3 Position; public Quaternion Rotation; public int ViewID; } [Serializable] public class SpawnerInstanceData { public string SpawnerTypeName = string.Empty; public int SpawnerInstanceID; public Vector3 SpawnerPosition; public List SpawnedItems = new List(); } [Serializable] public class MapSpawnerData { public List Spawners = new List(); } } namespace ItemSpawnSync.Core { public class SpawnerSyncManager : MonoBehaviour { public bool DisableSpawning; public bool EnableKeyTrigger; public bool SpawnIfNoDataFound; protected MethodInfo ForceSyncForFramesMethod = typeof(Item).GetMethod("ForceSyncForFrames", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static SpawnerSyncManager? instance; private ManualLogSource? logger; private Dictionary spawnerRegistry = new Dictionary(); private Dictionary spawnerToDataMap = new Dictionary(); public bool CapturingSpawn { get; internal set; } public MapSpawnerData? CurrentMapData { get; private set; } public static SpawnerSyncManager Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if ((Object)(object)instance == (Object)null) { GameObject val = new GameObject("SpawnerSyncManager"); instance = val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); } return instance; } } public bool IsDataLocked { get; private set; } public bool UseLoadedSpawnData { get; private set; } public Dictionary OriginalIdToItemMap { get; private set; } = new Dictionary(); public void CaptureSpawns() { CurrentMapData = new MapSpawnerData(); TriggerAllSpawners(); } public static List FindAllSpawnersInScene() { return Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0).ToList(); } public SpawnerInstanceData? GetSpawnerData(Spawner spawner) { if (!spawnerToDataMap.TryGetValue(spawner, out SpawnerInstanceData value)) { return null; } return value; } public bool HasSpawnerData(Spawner spawner) { return spawnerToDataMap.ContainsKey(spawner); } public void Initialize(ManualLogSource logger) { this.logger = logger; } public bool LoadMapSpawnerDataInCurrentLevel(MapSpawnerData data, bool lockData = false) { //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) if (IsDataLocked) { ManualLogSource? obj = logger; if (obj != null) { obj.LogWarning((object)"Spawn data is locked. Cannot load new data."); } return false; } CurrentMapData = data; spawnerRegistry.Clear(); spawnerToDataMap.Clear(); List list = FindAllSpawnersInScene(); HashSet matchedData = new HashSet(); ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogMessage((object)$"Found {list.Count} spawners in scene, attempting to match with {data.Spawners.Count} data entries"); } int num = 0; foreach (Spawner spawner in list) { if (!((Object)(object)((MonoBehaviourPun)spawner).photonView != (Object)null) || ((MonoBehaviourPun)spawner).photonView.ViewID < 0) { continue; } SpawnerInstanceData spawnerInstanceData = data.Spawners.FirstOrDefault((SpawnerInstanceData d) => d.SpawnerInstanceID == ((MonoBehaviourPun)spawner).photonView.ViewID && !matchedData.Contains(d)); if (spawnerInstanceData != null) { spawnerToDataMap[spawner] = spawnerInstanceData; matchedData.Add(spawnerInstanceData); num++; ManualLogSource? obj3 = logger; if (obj3 != null) { obj3.LogInfo((object)$"Matched spawner {((Object)spawner).name} by ViewID {((MonoBehaviourPun)spawner).photonView.ViewID}"); } } } int num2 = 0; List list2 = list.Where((Spawner s) => !spawnerToDataMap.ContainsKey(s)).ToList(); List list3 = data.Spawners.Where((SpawnerInstanceData d) => !matchedData.Contains(d)).ToList(); foreach (Spawner spawner2 in list2) { SpawnerInstanceData spawnerInstanceData2 = (from d in list3 where d.SpawnerTypeName == ((object)spawner2).GetType().Name orderby Vector3.Distance(((Component)spawner2).transform.position, d.SpawnerPosition) select d).FirstOrDefault(); if (spawnerInstanceData2 == null) { continue; } float num3 = Vector3.Distance(((Component)spawner2).transform.position, spawnerInstanceData2.SpawnerPosition); if (num3 < 0.01f) { spawnerToDataMap[spawner2] = spawnerInstanceData2; matchedData.Add(spawnerInstanceData2); list3.Remove(spawnerInstanceData2); num2++; ManualLogSource? obj4 = logger; if (obj4 != null) { obj4.LogInfo((object)$"Matched spawner {((Object)spawner2).name} at position {spawnerInstanceData2.SpawnerPosition} by proximity ({num3:F3}m)"); } } } ManualLogSource? obj5 = logger; if (obj5 != null) { obj5.LogMessage((object)$"Matched {num} spawners by ViewID, {num2} by proximity. Total: {spawnerToDataMap.Count}/{data.Spawners.Count}"); } UseLoadedSpawnData = true; if (lockData) { IsDataLocked = true; ManualLogSource? obj6 = logger; if (obj6 != null) { obj6.LogMessage((object)$"Started replaying spawner data with {data.Spawners.Count} spawners (LOCKED)"); } } else { ManualLogSource? obj7 = logger; if (obj7 != null) { obj7.LogMessage((object)$"Started replaying spawner data with {data.Spawners.Count} spawners"); } } return true; } public List SpawnItemsFromData(Spawner spawner, SpawnerInstanceData data) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) List list = new List(); try { foreach (SpawnedItemData spawnedItem in data.SpawnedItems) { if (OriginalIdToItemMap.ContainsKey(spawnedItem.ViewID)) { ManualLogSource? obj = logger; if (obj != null) { obj.LogInfo((object)$"Skipping spawn of {spawnedItem.ItemPrefabName} (ViewID {spawnedItem.ViewID}) - already spawned"); } continue; } Item component = PhotonNetwork.InstantiateItemRoom(spawnedItem.ItemPrefabName, spawnedItem.Position, spawnedItem.Rotation).GetComponent(); PhotonView component2 = ((Component)component).GetComponent(); OriginalIdToItemMap[spawnedItem.ViewID] = component; list.Add(component2); ForceSyncForFramesMethod.Invoke(component, new object[1] { 10 }); if ((Object)(object)component != (Object)null && spawner.isKinematic) { component2.RPC("SetKinematicRPC", (RpcTarget)3, new object[3] { true, ((Component)component).transform.position, ((Component)component).transform.rotation }); } } } catch (Exception ex) { ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogError((object)("Error spawning items from data for spawner " + ((Object)spawner).name + ": " + ex.Message)); } } return list; } public void SpawnItemsFromStartSpawners() { List list = (from s in FindAllSpawnersInScene() where s.spawnOnStart select s).ToList(); ManualLogSource? obj = logger; if (obj != null) { obj.LogMessage((object)$"Spawning items from {list.Count} start spawners..."); } foreach (Spawner item in list) { try { item.baseSpawnChance = 1f; if (((Behaviour)item).enabled) { item.ForceSpawn(); } } catch (Exception ex) { ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogError((object)("Error spawning from start spawner " + ((Object)item).name + " of type " + ((object)item).GetType().Name + ": " + ex.Message + " \n " + ex.StackTrace)); } } } Plugin.Instance?.PublishSpawnDataSpawnedInLevel(list); } public void TriggerAllSpawners() { List list = FindAllSpawnersInScene(); ManualLogSource? obj = logger; if (obj != null) { obj.LogMessage((object)$"Triggering {list.Count} spawners..."); } CapturingSpawn = true; int num = 0; foreach (Spawner item in list) { try { if (TriggerSpawner(item)) { num++; } } catch (Exception ex) { if ((Object)(object)((MonoBehaviourPun)item).photonView != (Object)null) { ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogError((object)$"Error triggering spawner {((Object)item).name} [{((MonoBehaviourPun)item).photonView.ViewID}] of type {((object)item).GetType().Name}: {ex.Message} \n {ex.StackTrace}"); } continue; } ManualLogSource? obj3 = logger; if (obj3 != null) { obj3.LogError((object)("Error triggering spawner " + ((Object)item).name + " of type " + ((object)item).GetType().Name + ": " + ex.Message + " \n " + ex.StackTrace)); } } } CapturingSpawn = false; ManualLogSource? obj4 = logger; if (obj4 != null) { obj4.LogMessage((object)$"Triggered {num} spawners out of {list.Count} successfully"); } Plugin.Instance?.PublishSpawnersTriggered(list); } private void SaveSpawnerData(Spawner spawner, List spawnedObjects) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Type type = ((object)spawner).GetType(); SpawnerInstanceData spawnerInstanceData = new SpawnerInstanceData { SpawnerTypeName = type.Name, SpawnerPosition = ((Component)spawner).transform.position, SpawnerInstanceID = (((Object)(object)((MonoBehaviourPun)spawner).photonView != (Object)null) ? ((MonoBehaviourPun)spawner).photonView.ViewID : (-1)), SpawnedItems = spawnedObjects.Select(delegate(PhotonView obj) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) string text = ((Object)obj).name; if (text.EndsWith("(Clone)")) { string text2 = text; text = text2.Substring(0, text2.Length - 7); } return new SpawnedItemData { ItemPrefabName = text, Position = ((Component)obj).transform.position, Rotation = ((Component)obj).transform.rotation, ViewID = obj.ViewID }; }).ToList() }; CurrentMapData.Spawners.Add(spawnerInstanceData); spawnerToDataMap[spawner] = spawnerInstanceData; } private bool TriggerSpawner(Spawner spawner) { SpawnedItemTracker val = default(SpawnedItemTracker); if (SpawnerExtensions.HasSpawnTracking((ISpawner)(object)spawner, ref val)) { ManualLogSource? obj = logger; if (obj != null) { string name = ((Object)spawner).name; PhotonView photonView = ((MonoBehaviourPun)spawner).photonView; obj.LogInfo((object)$"Resetting spawn tracking for spawner {name} [{((photonView != null) ? new int?(photonView.ViewID) : ((int?)null))}]"); } val.HasSpawnHistory = false; } if (spawner.spawnOnStart) { List list = spawner.TrySpawnItems(); if ((Object)(object)((MonoBehaviourPun)spawner).photonView != (Object)null) { ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogInfo((object)$"Triggered spawnOnStart on spawner {((Object)spawner).name} [{((MonoBehaviourPun)spawner).photonView.ViewID}] and got {list.Count} items"); } } else { ManualLogSource? obj3 = logger; if (obj3 != null) { obj3.LogInfo((object)$"Triggered spawnOnStart on spawner {((Object)spawner).name} and got {list.Count} items"); } } SaveSpawnerData(spawner, list); return true; } Type type = ((object)spawner).GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; MethodInfo method = type.GetMethod("GetSpawnSpots", bindingAttr); if (method != null) { List list2 = method.Invoke(spawner, null) as List; List list3 = spawner.SpawnItems(list2); if ((Object)(object)((MonoBehaviourPun)spawner).photonView != (Object)null) { ManualLogSource? obj4 = logger; if (obj4 != null) { obj4.LogInfo((object)$"Triggered {type.Name}.SpawnItems() on spawner {((Object)spawner).name} [{((MonoBehaviourPun)spawner).photonView.ViewID}] and got {list3.Count} items"); } } else { ManualLogSource? obj5 = logger; if (obj5 != null) { obj5.LogInfo((object)$"Triggered {type.Name}.SpawnItems() on spawner {((Object)spawner).name} and got {list3.Count} items"); } } SaveSpawnerData(spawner, list3); return true; } ManualLogSource? obj6 = logger; if (obj6 != null) { obj6.LogWarning((object)(type.Name + " spawner " + ((Object)spawner).name + " does not have expected spawn method GetSpawnSpots.")); } return false; } public void ClearSpawnedData(string sceneName) { //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) ManualLogSource? obj = logger; if (obj != null) { obj.LogMessage((object)("Clearing spawned data for scene " + sceneName + "...")); } if (string.IsNullOrEmpty(sceneName)) { OriginalIdToItemMap.Clear(); return; } int num = 0; foreach (KeyValuePair item in OriginalIdToItemMap.ToList()) { Item value = item.Value; if (!((Object)(object)value == (Object)null)) { Scene scene = ((Component)value).gameObject.scene; if (!(((Scene)(ref scene)).name == sceneName)) { continue; } } OriginalIdToItemMap.Remove(item.Key); num++; } ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogMessage((object)$"Cleared spawned data for scene {sceneName}: {num} items removed."); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }