using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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 Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("CustomItemSpawner")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomItemSpawner")] [assembly: AssemblyTitle("CustomItemSpawner")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 CustomItemSpawner { internal struct ItemDirectoryEntry { internal int Index; internal string Name; } internal static class CreateItemDirectory { internal static ItemDirectoryEntry[] Create() { GameObject[] array = (((Object)(object)PrefabsDirectory.instance == (Object)null) ? null : PrefabsDirectory.instance.directory); if (array == null) { return new ItemDirectoryEntry[0]; } ItemDirectoryEntry[] array2 = new ItemDirectoryEntry[array.Length]; for (int i = 0; i < array.Length; i++) { GameObject val = array[i]; array2[i] = new ItemDirectoryEntry { Index = i, Name = (((Object)(object)val == (Object)null) ? null : ((Object)val).name) }; } return array2; } } [BepInPlugin("com.Exocet.customitemspawner", "Custom Item Spawner", "1.1.0")] public sealed class CustomItemSpawnerPlugin : BaseUnityPlugin { internal static ConfigEntry CrateDirectoryItem; internal static ConfigEntry SpawnKey; internal static ConfigEntry CustomBallastObject; internal static ConfigEntry CustomObjectMass; internal static ManualLogSource Log; internal static ConfigFile PluginConfig; internal static ItemDirectoryEntry[] ItemDirectory; internal static Dictionary ItemIndices; private static bool itemDirectoryCreated; private void Awake() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00de: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; PluginConfig = ((BaseUnityPlugin)this).Config; SpawnKey = ((BaseUnityPlugin)this).Config.Bind("General", "Spawn Key", (KeyCode)287, "Key used to spawn the custom object."); CustomBallastObject = ((BaseUnityPlugin)this).Config.Bind("General", "Custom Ballast Object", true, "Apply the custom mass and name to spawned objects."); CustomObjectMass = ((BaseUnityPlugin)this).Config.Bind("General", "Custom Object Mass", 10000, new ConfigDescription("User defined mass value for this spawned object.", (AcceptableValueBase)(object)new AcceptableValueRange(1000, 100000), Array.Empty())); CrateDirectoryItem = ((BaseUnityPlugin)this).Config.Bind("General", "Game Item Directory", "(Loading item directory...)", new ConfigDescription("Prefab name from PrefabsDirectory.directory used as the custom object.", (AcceptableValueBase)(object)new AcceptableValueList(new string[1] { "(Loading item directory...)" }), Array.Empty())); new Harmony("com.Exocet.customitemspawner").PatchAll(); ((MonoBehaviour)this).StartCoroutine(InitializeItemDirectoryWhenReady()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom object spawner loaded."); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(SpawnKey.Value)) { CustomItemSpawner.Spawn(); } } internal static void CreateItemDirectoryOnce() { //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown if (itemDirectoryCreated || (Object)(object)PrefabsDirectory.instance == (Object)null || PrefabsDirectory.instance.directory == null || PrefabsDirectory.instance.directory.Length == 0) { return; } ItemDirectory = CreateItemDirectory.Create(); Log.LogDebug((object)$"Created item directory with {ItemDirectory.Length} entries."); List list = new List(); ItemIndices = new Dictionary(); for (int i = 0; i < ItemDirectory.Length; i++) { string name = ItemDirectory[i].Name; if (name != null && !ItemIndices.ContainsKey(name)) { list.Add(name); ItemIndices.Add(name, ItemDirectory[i].Index); } } if (list.Count != 0) { itemDirectoryCreated = true; string text = ((ItemDirectory.Length > 23) ? ItemDirectory[23].Name : null); if (text == null || !ItemIndices.ContainsKey(text)) { text = list[0]; } if (!ItemIndices.ContainsKey(CrateDirectoryItem.Value)) { CrateDirectoryItem.Value = text; } PluginConfig.Remove(new ConfigDefinition("General", "Game Item Directory")); CrateDirectoryItem = PluginConfig.Bind("General", "Game Item Directory", text, new ConfigDescription("Prefab name from PrefabsDirectory.directory used as the custom object.", (AcceptableValueBase)(object)new AcceptableValueList(list.ToArray()), Array.Empty())); } } private static IEnumerator InitializeItemDirectoryWhenReady() { while (!itemDirectoryCreated) { CreateItemDirectoryOnce(); yield return null; } } } internal static class CustomItemSpawner { private const string ModDataPrefix = "CustomItemSpawner.item."; private const string MarkerSuffix = ".customObject"; private const string MassSuffix = ".mass"; private const string NameSuffix = ".name"; internal static void Spawn() { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) PrefabsDirectory val = (((Object)(object)SaveLoadManager.instance == (Object)null) ? null : ((Component)SaveLoadManager.instance).GetComponent()); string text = ((CustomItemSpawnerPlugin.CrateDirectoryItem == null) ? null : CustomItemSpawnerPlugin.CrateDirectoryItem.Value); int value; int num = ((CustomItemSpawnerPlugin.ItemIndices == null || text == null || !CustomItemSpawnerPlugin.ItemIndices.TryGetValue(text, out value)) ? (-1) : value); if ((Object)(object)val == (Object)null || val.directory == null || num < 0 || num >= val.directory.Length) { CustomItemSpawnerPlugin.Log.LogError((object)("Cannot spawn custom object: prefab '" + text + "' is unavailable.")); return; } GameObject val2 = val.directory[num]; if ((Object)(object)val2 == (Object)null) { CustomItemSpawnerPlugin.Log.LogError((object)$"Cannot spawn custom object: PrefabsDirectory index {num} is empty."); return; } if ((Object)(object)Refs.ovrCameraRig == (Object)null) { CustomItemSpawnerPlugin.Log.LogError((object)"Cannot spawn custom object: the camera rig is unavailable."); return; } GameObject val3 = Object.Instantiate(val2, Refs.ovrCameraRig.position + Refs.ovrCameraRig.forward, Refs.ovrCameraRig.rotation); ShipItem component = val3.GetComponent(); SaveablePrefab component2 = val3.GetComponent(); Good component3 = val3.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { Object.Destroy((Object)(object)val3); CustomItemSpawnerPlugin.Log.LogError((object)"Cannot spawn custom object: the selected prefab is missing required components."); return; } component.sold = true; component2.RegisterToSave(); if (CustomItemSpawnerPlugin.CustomBallastObject.Value) { int value2 = CustomItemSpawnerPlugin.CustomObjectMass.Value; component.mass = value2; component.name = $"{value2} Mass Custom Object"; SaveCustomObjectProperties(component2.instanceId, component); } if ((Object)(object)component3 != (Object)null) { component3.RegisterAsMissionless(); } CustomItemSpawnerPlugin.Log.LogInfo((object)$"Spawned custom object '{((Object)val2).name}' from PrefabsDirectory index {num}."); } internal static void RestoreLoadedCustomObject(ShipItem item) { if ((Object)(object)item == (Object)null || !CustomItemSpawnerPlugin.CustomBallastObject.Value) { return; } SaveablePrefab component = ((Component)item).GetComponent(); if (!((Object)(object)component == (Object)null) && IsCustomObject(component.instanceId)) { string modDataKey = GetModDataKey(component.instanceId); if (int.TryParse(GetModDataValue(modDataKey + ".mass", ((int)item.mass).ToString(CultureInfo.InvariantCulture)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { item.mass = result; } item.name = GetModDataValue(modDataKey + ".name", item.name); } } internal static void RestoreLoadedCustomObjects() { if (!CustomItemSpawnerPlugin.CustomBallastObject.Value || (Object)(object)SaveLoadManager.instance == (Object)null) { return; } List currentPrefabs = SaveLoadManager.instance.GetCurrentPrefabs(); if (currentPrefabs == null) { return; } foreach (SaveablePrefab item in currentPrefabs) { if (!((Object)(object)item == (Object)null)) { RestoreLoadedCustomObject(((Component)item).GetComponent()); } } } internal static IEnumerator RestoreLoadedCustomObjectsAfterLoad() { for (int frame = 0; frame < 2; frame++) { yield return null; RestoreLoadedCustomObjects(); } } private static void SaveCustomObjectProperties(int instanceId, ShipItem item) { if (GameState.modData == null) { CustomItemSpawnerPlugin.Log.LogWarning((object)"Custom object spawned, but save data is unavailable; custom properties cannot persist."); return; } string modDataKey = GetModDataKey(instanceId); GameState.modData[modDataKey + ".customObject"] = "1"; GameState.modData[modDataKey + ".mass"] = item.mass.ToString(CultureInfo.InvariantCulture); GameState.modData[modDataKey + ".name"] = item.name; } private static bool IsCustomObject(int instanceId) { return GameState.modData != null && GameState.modData.ContainsKey(GetModDataKey(instanceId) + ".customObject"); } private static string GetModDataKey(int instanceId) { return "CustomItemSpawner.item." + instanceId; } private static string GetModDataValue(string key, string fallback) { string value; return GameState.modData.TryGetValue(key, out value) ? value : fallback; } } [HarmonyPatch(typeof(SaveLoadManager), "LoadModData")] internal static class CustomObjectLoadPatch { private static void Postfix() { CustomItemSpawnerPlugin.CreateItemDirectoryOnce(); CustomItemSpawner.RestoreLoadedCustomObjects(); if ((Object)(object)SaveLoadManager.instance != (Object)null) { ((MonoBehaviour)SaveLoadManager.instance).StartCoroutine(CustomItemSpawner.RestoreLoadedCustomObjectsAfterLoad()); } CustomItemSpawnerPlugin.Log.LogDebug((object)"Save data loaded; item directory initialized and custom object properties restored."); } } [HarmonyPatch(typeof(ShipItem), "OnLoad")] internal static class CustomObjectShipItemLoadPatch { private static void Postfix(ShipItem __instance) { CustomItemSpawner.RestoreLoadedCustomObject(__instance); } } [HarmonyPatch(typeof(ItemRigidbody), "UpdateMass")] internal static class CustomObjectMassUpdatePatch { private static void Prefix(ItemRigidbody __instance) { if ((Object)(object)__instance != (Object)null) { CustomItemSpawner.RestoreLoadedCustomObject(__instance.GetShipItem()); } } } }