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 StupidBoomboxMix v2.0.0
PersonalBoombox.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using PersonalBoombox.Patches; using Unity.Netcode; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("PersonalBoombox")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PersonalBoombox")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("90672a7b-b084-4f8d-9d78-46affb7b97e7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")] [assembly: AssemblyVersion("1.0.0.0")] namespace PersonalBoombox { public static class Assets { [Serializable] private class PBDataJson { public string name; public string description; public int price; public float volume; public int red; public int blue; public int green; public Color color; public static PBDataJson GetData(string path) { if (File.Exists(path)) { string json = File.ReadAllText(path); PBDataJson pBDataJson = CreateFromJson(json); pBDataJson.FillMissingValues(); pBDataJson.AdjustValues(); return pBDataJson; } logger.LogWarning((object)"Missing .json file. Using default values"); return GetDefault(); } public static PBDataJson GetDefault() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) PBDataJson pBDataJson = new PBDataJson(); pBDataJson.name = "Untitled"; pBDataJson.description = "Missing Description"; pBDataJson.price = 60; pBDataJson.volume = 0.5f; pBDataJson.red = 255; pBDataJson.blue = 255; pBDataJson.green = 255; pBDataJson.color = Color.white; return pBDataJson; } private void FillMissingValues() { if (string.IsNullOrWhiteSpace(name)) { name = "Untitled"; } if (string.IsNullOrWhiteSpace(description)) { description = "Missing Description"; } } private void AdjustValues() { //IL_00d0: 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) int length = Mathf.Min(name.Length, 20); name = name.Substring(0, length); price = Mathf.Clamp(price, 0, 1000); volume = Mathf.Clamp(volume, 0f, PersonalBoomboxPlugin.Instance.maxVolumeValue); red = Mathf.Clamp(red, 0, 255); blue = Mathf.Clamp(blue, 0, 255); green = Mathf.Clamp(green, 0, 255); color = new Color((float)red / 255f, (float)green / 255f, (float)blue / 255f, 1f); } private static PBDataJson CreateFromJson(string json) { return JsonUtility.FromJson<PBDataJson>(json); } public string ToJson() { return JsonUtility.ToJson((object)this); } } private const string mainAssetBundleName = "personalboombox"; private const int prefabCopyCount = 5; public static AssetBundle MainAssetBundle = null; public static GameObject originalPrefab; public static GameObject[] prefabCopies; private static readonly string[] musicExts = new string[1] { "mp3" }; private static ManualLogSource logger => PersonalBoomboxPlugin.Instance.logger; private static string GetAssemblyName() { return Assembly.GetExecutingAssembly().FullName.Split(new char[1] { ',' })[0]; } public static void LoadAssetBundle() { if ((Object)(object)MainAssetBundle == (Object)null) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetAssemblyName() + ".personalboombox"); MainAssetBundle = AssetBundle.LoadFromStream(stream); } originalPrefab = Assets.Load<GameObject>("prefab"); prefabCopies = (GameObject[])(object)new GameObject[5]; for (int i = 0; i < 5; i++) { prefabCopies[i] = Assets.Load<GameObject>($"prefab{i + 1}"); } } public static T Load<T>(string name) where T : Object { if ((Object)(object)MainAssetBundle == (Object)null) { logger.LogError((object)"Trying to load in asset but asset bundle is missing"); return default(T); } logger.LogInfo((object)("Loading asset " + name)); return MainAssetBundle.LoadAsset<T>(name); } public static void LoadMusicFolders() { List<string> paths = PersonalBoomboxPlugin.paths; List<PersonalBoomboxPlugin.PBData> list = new List<PersonalBoomboxPlugin.PBData>(); int num = 0; foreach (string item in paths) { string[] directories = Directory.GetDirectories(item); string[] array = directories; foreach (string text in array) { string fullName = Directory.GetParent(item).FullName; string text2 = text.Replace(fullName, string.Empty); logger.LogInfo((object)("Reading from directory " + text2 + "!")); try { CreateFromDirectory(text, list, num++); } catch (Exception ex) { logger.LogError((object)("Error loading at folder " + text2)); logger.LogError((object)ex.ToString()); } } } list.Sort((PersonalBoomboxPlugin.PBData first, PersonalBoomboxPlugin.PBData second) => first.name.CompareTo(second.name)); num = 0; foreach (PersonalBoomboxPlugin.PBData item2 in list) { char c = (char)(65 + num); item2.prefixName = $"pb{c}"; item2.boomboxName = item2.prefixName + " " + item2.name; ((Object)item2.prefab).name = item2.boomboxName; num++; } PersonalBoomboxPlugin.data = list; } private static void CreateFromDirectory(string directory, List<PersonalBoomboxPlugin.PBData> data, int index) { //IL_00e8: 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) if (index >= 5) { logger.LogWarning((object)$"Loading too many boomboxes. There is a limit of {5}"); return; } string path = Path.Combine(directory, "data.json"); IEnumerable<string> enumerable = from file in Directory.EnumerateFiles(directory, "*.*") where musicExts.Any((string x) => file.EndsWith(x, StringComparison.InvariantCultureIgnoreCase)) select file; PBDataJson data2 = PBDataJson.GetData(path); char c = (char)(97 + index); PersonalBoomboxPlugin.PBData pBData = new PersonalBoomboxPlugin.PBData(); pBData.name = data2.name; pBData.description = data2.description; pBData.price = data2.price; pBData.volume = data2.volume; pBData.prefab = prefabCopies[index]; pBData.script = pBData.prefab.AddComponent<PersonalBoomboxItem>(); pBData.script.musicAudios = new List<AudioClip>(); pBData.color = data2.color; List<Coroutine> list = new List<Coroutine>(); foreach (string item2 in enumerable) { Coroutine item = MyOwnCoroutine.AddCoroutine(LoadAudioClip(pBData, item2)); list.Add(item); } MyOwnCoroutine.AddCoroutine(WaitForClips(pBData, list)); data.Add(pBData); logger.LogInfo((object)("Loaded data from boombox " + pBData.name + "!")); } private static IEnumerator WaitForClips(PersonalBoomboxPlugin.PBData data, List<Coroutine> coroutines) { yield return null; foreach (Coroutine coroutine in coroutines) { yield return coroutine; } PersonalBoomboxItem script = data.script; int count = script.musicAudios.Count; script.SortAudioClips(); script.finishedLoading = true; logger.LogInfo((object)$"{data.boomboxName} is fully set up with {count} songs!"); if (count == 0) { logger.LogWarning((object)"Boomboxes with 0 songs will be skipped in the initialization process"); } } private static IEnumerator LoadAudioClip(PersonalBoomboxPlugin.PBData data, string path) { string fileName = Path.GetFileName(path); logger.LogInfo((object)("Loading music file " + fileName)); AudioType fileType = GetAudioType(path); if ((int)fileType == 0) { logger.LogError((object)("Error loading music file " + fileName + ". Unsupported file ext.")); yield break; } UnityWebRequest loader = UnityWebRequestMultimedia.GetAudioClip(path, GetAudioType(path)); loader.SendWebRequest(); while (!loader.isDone) { yield return null; } if (loader.error != null) { logger.LogError((object)("Error loading music file " + fileName + ". Download failed")); logger.LogError((object)loader.error); yield break; } AudioClip clip = DownloadHandlerAudioClip.GetContent(loader); if ((Object)(object)clip == (Object)null || (int)clip.loadState != 2) { logger.LogError((object)("Error loading music file " + fileName + ". File is weird")); } data.script.AddAudioClip(clip); logger.LogInfo((object)("Loaded music file " + ((Object)clip).name)); } public static AudioType GetAudioType(string path) { //IL_0020: 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_0024: Unknown result type (might be due to invalid IL or missing references) string text = Path.GetExtension(path).ToLowerInvariant(); string text2 = text; if (text2 == ".mp3") { return (AudioType)13; } return (AudioType)0; } } public class PersonalBoomboxItem : GrabbableObject { public AudioSource boomboxAudio; public List<AudioClip> musicAudios; public bool finishedLoading; public AudioClip[] stopAudios; public Random musicRandomizer; private StartOfRound playersManager; private RoundManager roundManager; public bool isPlayingMusic; private float noiseInterval; private int timesPlayedWithoutTurningOff; public int pbIndex; public int AudioClipCount => (musicAudios != null) ? musicAudios.Count : 0; public void AddAudioClip(AudioClip clip) { musicAudios.Add(clip); } public void SortAudioClips() { musicAudios.Sort((AudioClip first, AudioClip second) => ((Object)first).name.CompareTo(((Object)second).name)); } public override void Start() { ((GrabbableObject)this).Start(); playersManager = Object.FindObjectOfType<StartOfRound>(); roundManager = Object.FindObjectOfType<RoundManager>(); musicRandomizer = new Random(playersManager.randomMapSeed - 10); } public override void ItemActivate(bool used, bool buttonDown = true) { ((GrabbableObject)this).ItemActivate(used, buttonDown); StartMusic(used); } private void StartMusic(bool startMusic, bool pitchDown = false) { if (startMusic && musicAudios.Count > 0) { boomboxAudio.clip = musicAudios[musicRandomizer.Next(0, musicAudios.Count)]; boomboxAudio.pitch = 1f; boomboxAudio.Play(); } else if (isPlayingMusic) { if (pitchDown) { ((MonoBehaviour)this).StartCoroutine(musicPitchDown()); } else { boomboxAudio.Stop(); boomboxAudio.PlayOneShot(stopAudios[Random.Range(0, stopAudios.Length)]); } timesPlayedWithoutTurningOff = 0; } base.isBeingUsed = startMusic; isPlayingMusic = startMusic; } private IEnumerator musicPitchDown() { for (int i = 0; i < 30; i++) { yield return null; AudioSource obj = boomboxAudio; obj.pitch -= 0.033f; if (boomboxAudio.pitch <= 0f) { break; } } boomboxAudio.Stop(); boomboxAudio.PlayOneShot(stopAudios[Random.Range(0, stopAudios.Length)]); } public override void UseUpBatteries() { ((GrabbableObject)this).UseUpBatteries(); StartMusic(startMusic: false, pitchDown: true); } public override void PocketItem() { ((GrabbableObject)this).PocketItem(); StartMusic(startMusic: false); } public override void Update() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) ((GrabbableObject)this).Update(); if (isPlayingMusic) { if (noiseInterval <= 0f) { noiseInterval = 1f; timesPlayedWithoutTurningOff++; roundManager.PlayAudibleNoise(((Component)this).transform.position, 16f, 0.9f, timesPlayedWithoutTurningOff, false, 5); } else { noiseInterval -= Time.deltaTime; } if (base.insertedBattery.charge < 0.05f) { boomboxAudio.pitch = 1f - (0.05f - base.insertedBattery.charge) * 4f; } } } protected override void __initializeVariables() { ((GrabbableObject)this).__initializeVariables(); } protected override string __getTypeName() { return "TouhouBoomboxItem"; } } [BepInPlugin("ImoutoSama.PersonalBoombox", "Personal Boombox", "1.0.0")] [BepInProcess("Lethal Company.exe")] public class PersonalBoomboxPlugin : BaseUnityPlugin { public class PBData { public string path; public string name; public string prefixName; public string boomboxName; public string description; public int price; public float volume; public Color color; public GameObject prefab; public PersonalBoomboxItem script; public Item item; public int itemIndex; public bool addedToTerminalKeyword; public bool IsFinished => Object.op_Implicit((Object)(object)script) && script.finishedLoading; public bool IsValid => Object.op_Implicit((Object)(object)script) && script.AudioClipCount > 0; } private const string modGUID = "ImoutoSama.PersonalBoombox"; private const string modName = "Personal Boombox"; private const string modVersion = "1.0.0"; private readonly Harmony harmony = new Harmony("ImoutoSama.PersonalBoombox"); internal ManualLogSource logger; public static List<PBData> data; public static List<string> paths; public ConfigEntry<int> maxVolumeConfig; public float maxVolumeValue; public static PersonalBoomboxPlugin Instance { get; private set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } logger = Logger.CreateLogSource("ImoutoSama.PersonalBoombox"); logger.LogInfo((object)"Plugin Personal Boombox has been added!"); maxVolumeConfig = ConfigBindClamp("General", "Max Volume", 100, "Max possible volume value. From 0 to 100.", 0, 100); maxVolumeValue = (float)maxVolumeConfig.Value * 0.01f; harmony.PatchAll(typeof(TerminalPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); harmony.PatchAll(typeof(GameNetworkManagerPatch)); harmony.PatchAll(typeof(MenuManagerPatch)); data = new List<PBData>(); paths = new List<string>(); Assets.LoadAssetBundle(); AddFromAssemblyDll(Assembly.GetExecutingAssembly().Location); } public ConfigEntry<int> ConfigBindClamp(string section, string key, int defaultValue, string description, int min, int max) { ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(section, key, defaultValue, description); val.Value = Mathf.Clamp(val.Value, min, max); return val; } public static void AddFromAssemblyDll(string dllPath) { paths.Add(Path.GetDirectoryName(dllPath)); } public static void AddDirectory(string path) { paths.Add(path); } } public class MyOwnCoroutine : MonoBehaviour { public static MyOwnCoroutine Instance { get; private set; } public static Coroutine AddCoroutine(IEnumerator c) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("My Own Coroutine"); Instance = val.AddComponent<MyOwnCoroutine>(); Object.DontDestroyOnLoad((Object)(object)val); } return ((MonoBehaviour)Instance).StartCoroutine(c); } } } namespace PersonalBoombox.Patches { [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void StartPatch(ref GameNetworkManager __instance) { PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"Adding personal boomboxes to network list"); NetworkManager component = ((Component)__instance).GetComponent<NetworkManager>(); foreach (PersonalBoomboxPlugin.PBData datum in PersonalBoomboxPlugin.data) { component.AddNetworkPrefab(datum.prefab); } } } [HarmonyPatch(typeof(ItemDropship))] internal class ItemDropshipPatch { private static void EnableBoombox(GameObject target) { PersonalBoomboxItem component = target.GetComponent<PersonalBoomboxItem>(); if ((Object)(object)component != (Object)null) { ((Component)component).gameObject.SetActive(true); } } [HarmonyPatch("OpenShipDoorsOnServer")] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { bool found = false; int i = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Call) { i = 1; } else if (instruction.opcode == OpCodes.Dup && i == 1) { i = 2; } else if (instruction.opcode == OpCodes.Callvirt && i == 2) { MethodInfo method = typeof(ItemDropshipPatch).GetMethod("EnableBoombox", BindingFlags.Static | BindingFlags.NonPublic); yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)method); found = true; i = 0; } else { i = 0; } yield return instruction; } if (object.Equals(false, found)) { PersonalBoomboxPlugin.Instance.logger.LogError((object)"Cannot find <Stdfld someField> in OriginalType.OriginalMethod"); } } } [HarmonyPatch(typeof(MenuManager))] internal class MenuManagerPatch { public static bool done; [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePatch() { if (!done) { done = true; Assets.LoadMusicFolders(); } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { public static bool done; [HarmonyPatch("Start")] [HarmonyPrefix] public static void StartPatch(ref StartOfRound __instance) { if (done) { return; } done = true; PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"Adding personal boomboxes to items list"); foreach (PersonalBoomboxPlugin.PBData datum in PersonalBoomboxPlugin.data) { bool isFinished = datum.IsFinished; bool isValid = datum.IsValid; if (datum.IsFinished && datum.IsValid) { __instance.allItemsList.itemsList.Add(datum.item); } } } } [HarmonyPatch(typeof(Terminal))] internal class TerminalPatch { public static Item boomboxItem; public static GameObject boomboxPrefab; public static MeshFilter boomboxMeshFilter; public static MeshRenderer boomboxMeshRenderer; public static AudioSource boomboxAudioSource; public static BoomboxItem boomboxScript; public static TerminalKeyword buyKeyword; public static TerminalKeyword infoKeyword; public static CompatibleNoun buyNoun; public static CompatibleNoun infoNoun; [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePatch(ref Terminal __instance) { foreach (PersonalBoomboxPlugin.PBData datum in PersonalBoomboxPlugin.data) { bool isFinished = datum.IsFinished; bool isValid = datum.IsValid; if (datum.IsFinished && datum.IsValid) { AddToTerminal(ref __instance, datum); continue; } if (!datum.IsFinished) { PersonalBoomboxPlugin.Instance.logger.LogError((object)(datum.boomboxName + " has no script initialized or it is not done loading music")); } if (!datum.IsValid) { PersonalBoomboxPlugin.Instance.logger.LogError((object)(datum.boomboxName + " has no script initialized or it has no loaded music")); } } } private static void AddToTerminal(ref Terminal __instance, PersonalBoomboxPlugin.PBData data) { PersonalBoomboxPlugin.Instance.logger.LogInfo((object)("Adding " + data.boomboxName + " to terminal")); if ((Object)(object)data.item == (Object)null) { SetupPrefab(ref __instance, data); } PersonalBoomboxPlugin.Instance.logger.LogInfo((object)("Loading " + data.boomboxName + " into buyable list")); List<Item> list = __instance.buyableItemsList.ToList(); data.itemIndex = list.Count; list.Add(data.item); __instance.buyableItemsList = list.ToArray(); if (!data.addedToTerminalKeyword) { AddToTerminalKeywords(ref __instance, data); data.addedToTerminalKeyword = true; } } private static void SetupPrefab(ref Terminal __instance, PersonalBoomboxPlugin.PBData data) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown PersonalBoomboxPlugin.Instance.logger.LogInfo((object)("Setting up " + data.boomboxName + " prefab")); if ((Object)(object)boomboxItem == (Object)null) { InitializePrefab(ref __instance); } Item val = Object.Instantiate<Item>(boomboxItem); GameObject prefab = data.prefab; PersonalBoomboxItem script = data.script; val.creditsWorth = data.price; val.spawnPrefab = prefab; val.itemName = data.boomboxName; data.item = val; prefab.tag = boomboxPrefab.tag; prefab.layer = boomboxPrefab.layer; MeshFilter component = prefab.GetComponent<MeshFilter>(); component.mesh = boomboxMeshFilter.mesh; MeshRenderer component2 = prefab.GetComponent<MeshRenderer>(); ((Renderer)component2).materials = ((Renderer)boomboxMeshRenderer).materials; ((Renderer)component2).materials[3].color = data.color; ((Renderer)component2).materials[1].color = DarkenColor(data.color); AudioSource component3 = prefab.GetComponent<AudioSource>(); component3.volume = data.volume; component3.outputAudioMixerGroup = boomboxAudioSource.outputAudioMixerGroup; component3.SetCustomCurve((AudioSourceCurveType)0, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)0)); component3.SetCustomCurve((AudioSourceCurveType)1, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)1)); component3.SetCustomCurve((AudioSourceCurveType)3, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)3)); component3.SetCustomCurve((AudioSourceCurveType)2, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)2)); ((GrabbableObject)script).grabbable = true; ((GrabbableObject)script).isInFactory = true; ((GrabbableObject)script).grabbableToEnemies = true; ((GrabbableObject)script).propColliders = ((Component)script).GetComponents<Collider>(); ((GrabbableObject)script).mainObjectRenderer = component2; script.boomboxAudio = component3; script.stopAudios = boomboxScript.stopAudios; ((GrabbableObject)script).insertedBattery = new Battery(false, ((GrabbableObject)boomboxScript).insertedBattery.charge); ((GrabbableObject)script).itemProperties = val; static Color DarkenColor(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002f: 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) return new Color(c.r * 0.9f, c.g * 0.9f, c.b * 0.9f, 1f); } } private static void InitializePrefab(ref Terminal __instance) { PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"First time setting up boombox prefab. Grabbing boombox prefab to copy from"); List<Item> list = __instance.buyableItemsList.ToList(); int num = -1; for (int i = 0; i < list.Count; i++) { Item val = list[i]; if (val.itemName.ToLowerInvariant() == "boombox") { num = i; break; } } if (num == -1) { PersonalBoomboxPlugin.Instance.logger.LogError((object)"Items has no boomerbox item to copy from"); return; } boomboxItem = list[num]; boomboxPrefab = boomboxItem.spawnPrefab; boomboxMeshFilter = boomboxPrefab.GetComponent<MeshFilter>(); boomboxMeshRenderer = boomboxPrefab.GetComponent<MeshRenderer>(); boomboxAudioSource = boomboxPrefab.GetComponent<AudioSource>(); boomboxScript = boomboxPrefab.GetComponent<BoomboxItem>(); } private static void AddToTerminalKeywords(ref Terminal __instance, PersonalBoomboxPlugin.PBData data) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown PersonalBoomboxPlugin.Instance.logger.LogInfo((object)("Adding buy/info function to " + data.boomboxName)); if ((Object)(object)buyKeyword == (Object)null) { InitializeKeyword(ref __instance); } string word = data.boomboxName.ToLowerInvariant(); string boomboxName = data.boomboxName; CompatibleNoun val = CopyNoun(buyNoun); TerminalKeyword noun = val.noun; noun.word = word; TerminalNode result = val.result; result.buyItemIndex = data.itemIndex; result.displayText = result.displayText.Replace("boom boxes", boomboxName + "es"); result.terminalOptions = CopyNouns(result.terminalOptions); TerminalNode val2 = FindNodeWithConfirm(result.terminalOptions); val2.buyItemIndex = data.itemIndex; val2.displayText = val2.displayText.Replace("boom boxes", boomboxName + "es"); List<CompatibleNoun> list = buyKeyword.compatibleNouns.ToList(); List<CompatibleNoun> list2 = infoKeyword.compatibleNouns.ToList(); List<TerminalKeyword> list3 = __instance.terminalNodes.allKeywords.ToList(); list.Add(val); buyKeyword.compatibleNouns = list.ToArray(); CompatibleNoun val3 = new CompatibleNoun(); val3.noun = val.noun; val3.result = CopyTerminalNode(infoNoun.result); val3.result.displayText = "\n" + data.description + "\n\n"; list2.Add(val3); infoKeyword.compatibleNouns = list2.ToArray(); list3.Add(noun); __instance.terminalNodes.allKeywords = list3.ToArray(); } private static void InitializeKeyword(ref Terminal __instance) { PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"First time adding keywords to terminal. Grabbing some values to copy from"); TerminalKeyword[] allKeywords = __instance.terminalNodes.allKeywords; buyKeyword = ((IEnumerable<TerminalKeyword>)allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword a) => a.word == "buy")); infoKeyword = ((IEnumerable<TerminalKeyword>)allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword a) => a.word == "info")); buyNoun = buyKeyword.compatibleNouns.First((CompatibleNoun b) => b.noun.word == "boombox"); infoNoun = infoKeyword.compatibleNouns.First((CompatibleNoun b) => b.noun.word == "boombox"); } private static TerminalKeyword CopyTerminalKeyword(TerminalKeyword target) { return Object.Instantiate<TerminalKeyword>(target); } private static TerminalNode CopyTerminalNode(TerminalNode target) { return Object.Instantiate<TerminalNode>(target); } private static CompatibleNoun CopyNoun(CompatibleNoun target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown CompatibleNoun val = new CompatibleNoun(); val.noun = CopyTerminalKeyword(target.noun); val.result = CopyTerminalNode(target.result); return val; } private static CompatibleNoun[] CopyNouns(CompatibleNoun[] target) { CompatibleNoun[] array = (CompatibleNoun[])(object)new CompatibleNoun[target.Length]; for (int i = 0; i < target.Length; i++) { array[i] = CopyNoun(target[i]); } return array; } private static TerminalNode FindNodeWithConfirm(CompatibleNoun[] nouns) { foreach (CompatibleNoun val in nouns) { if (val.noun.word.ToLowerInvariant() == "confirm") { return val.result; } } return null; } } }