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<bool>? DisableSpawningConfig;
public ConfigEntry<string>? FileNameConfig;
public ConfigEntry<KeyboardShortcut>? LoadDataKeyConfig;
public ConfigEntry<KeyboardShortcut>? ExportLootDataKeyConfig;
public ConfigEntry<KeyboardShortcut>? SaveDataKeyConfig;
public ConfigEntry<bool>? SpawnIfNoDataFoundConfig;
public ConfigEntry<KeyboardShortcut>? TriggerSpawnKeyConfig;
public ConfigEntry<KeyboardShortcut>? 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<string>? OnSpawnDataSaved;
public event Action<List<Spawner>>? OnSpawnersTriggered;
public event Action<List<Spawner>>? OnSpawnDataSpawnedInLevel;
public event Action<string>? 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<MapSpawnerData>(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<MapSpawnerData>(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<KeyboardShortcut>("Controls", "TriggerSpawnKey", new KeyboardShortcut((KeyCode)285, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Key to trigger all spawners");
SaveDataKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("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<KeyboardShortcut>("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<KeyboardShortcut>("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<KeyboardShortcut>("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<bool>("General", "DisableSpawning", false, "If true, prevents any item spawning unless from loaded data");
SpawnIfNoDataFoundConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SpawnIfNoDataFound", false, "If true, spawners without loaded data will spawn normally");
FileNameConfig = ((BaseUnityPlugin)this).Config.Bind<string>("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<Spawner> spawners)
{
this.OnSpawnersTriggered?.Invoke(spawners);
}
public void PublishSpawnDataSpawnedInLevel(List<Spawner> spawners)
{
this.OnSpawnDataSpawnedInLevel?.Invoke(spawners);
}
}
}
namespace ItemSpawnSync.Patches
{
[HarmonyPatch(typeof(SpawnedItemTracker), "SpawnAndTrackFromItemHistory")]
public class SpawnedItemTrackerPatch
{
private static bool Prefix(SpawnedItemTracker __instance, ref List<PhotonView> __result, ref List<SpawnRecord> ____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<SpawnRecord>();
__result = new List<PhotonView>();
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<List<PhotonView>>? OnItemsSpawned;
private static IEnumerable<MethodBase> TargetMethods()
{
List<Type> list = new List<Type>();
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
try
{
IEnumerable<Type> 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<Transform>) }, null);
if (method != null)
{
yield return method;
}
}
}
private static bool Prefix(Spawner __instance, List<Transform> spawnSpots, ref List<PhotonView> __result)
{
SpawnerSyncManager instance = SpawnerSyncManager.Instance;
SpawnedItemTracker val = default(SpawnedItemTracker);
if (!((Component)__instance).TryGetComponent<SpawnedItemTracker>(ref val))
{
val = ((Component)__instance).gameObject.AddComponent<SpawnedItemTracker>();
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<PhotonView>();
return instance.SpawnIfNoDataFound;
}
__result = instance.SpawnItemsFromData(__instance, spawnerData);
SpawnerSpawnItemsPatch.OnItemsSpawned?.Invoke(__result);
return false;
}
__result = new List<PhotonView>();
return instance.SpawnIfNoDataFound;
}
__result = new List<PhotonView>();
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<MemberInfo> GetSerializableMembers(Type objectType)
{
if (objectType.Name.Contains("AnonymousType"))
{
return objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Cast<MemberInfo>().ToList();
}
return (from f in objectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where f.IsPublic || ((MemberInfo)f).GetCustomAttribute<SerializeField>() != null
select f).Cast<MemberInfo>().ToList();
}
}
public class LootDataContainer
{
protected static string LootDataFileName = "LootData.json";
public static Dictionary<string, Dictionary<string, int>> SpawnData = new Dictionary<string, Dictionary<string, int>>();
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<Dictionary<string, Dictionary<string, int>>>(text2) ?? new Dictionary<string, Dictionary<string, int>>();
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<string, Dictionary<string, int>> 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<string, int> item in spawnDatum.Value)
{
string itemName = item.Key;
int value = item.Value;
KeyValuePair<ushort, Item> keyValuePair = SingletonAsset<ItemDatabase>.Instance.itemLookup.FirstOrDefault((KeyValuePair<ushort, Item> 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<SpawnPool, Dictionary<ushort, int>> allSpawnWeightDatum in LootData.AllSpawnWeightData)
{
string key = ((object)allSpawnWeightDatum.Key/*cast due to .constrained prefix*/).ToString();
Dictionary<string, int> dictionary = new Dictionary<string, int>();
SpawnData.Add(key, dictionary);
foreach (KeyValuePair<ushort, int> item in allSpawnWeightDatum.Value)
{
if (ItemDatabase.TryGetItem(item.Key, ref val))
{
LootData component = ((Component)val).GetComponent<LootData>();
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<SpawnedItemData> SpawnedItems = new List<SpawnedItemData>();
}
[Serializable]
public class MapSpawnerData
{
public List<SpawnerInstanceData> Spawners = new List<SpawnerInstanceData>();
}
}
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<int, Spawner> spawnerRegistry = new Dictionary<int, Spawner>();
private Dictionary<Spawner, SpawnerInstanceData> spawnerToDataMap = new Dictionary<Spawner, SpawnerInstanceData>();
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<SpawnerSyncManager>();
Object.DontDestroyOnLoad((Object)(object)val);
}
return instance;
}
}
public bool IsDataLocked { get; private set; }
public bool UseLoadedSpawnData { get; private set; }
public Dictionary<int, Item> OriginalIdToItemMap { get; private set; } = new Dictionary<int, Item>();
public void CaptureSpawns()
{
CurrentMapData = new MapSpawnerData();
TriggerAllSpawners();
}
public static List<Spawner> FindAllSpawnersInScene()
{
return Object.FindObjectsByType<Spawner>((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<Spawner> list = FindAllSpawnersInScene();
HashSet<SpawnerInstanceData> matchedData = new HashSet<SpawnerInstanceData>();
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<Spawner> list2 = list.Where((Spawner s) => !spawnerToDataMap.ContainsKey(s)).ToList();
List<SpawnerInstanceData> 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<PhotonView> 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<PhotonView> list = new List<PhotonView>();
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<Item>();
PhotonView component2 = ((Component)component).GetComponent<PhotonView>();
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<Spawner> 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<Spawner> 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<PhotonView> 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<PhotonView> 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<Transform> list2 = method.Invoke(spawner, null) as List<Transform>;
List<PhotonView> 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<int, Item> 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)
{
}
}
}