Decompiled source of lammOS v1.5.0
lammOS.dll
Decompiled 10 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; using lammOS.Commands; using lammOS.Keybinds; using lammOS.Macros; using lammOS.NewTerminal; using lammOS.SyncedConfig; using lammOS.Variables; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("lammOS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("lammOS")] [assembly: AssemblyTitle("lammOS")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace lammOS { [BepInPlugin("lammas123.lammOS", "lammOS", "1.5.0")] [BepInDependency("com.rune580.LethalCompanyInputUtils", "0.6.3")] public class lammOS : BaseUnityPlugin { internal static lammOS Instance; internal static ManualLogSource Logger; internal static ConfigFile Config; public static IReadOnlyDictionary<string, string> WeatherColors; internal static AudioClip savedShipIntroSpeechSFX; internal static RawImage bodyHelmetCameraImage = null; internal static GameObject Clock; public static bool ShowCommandConfirmations { get; internal set; } public static int CharsToAutocomplete { get; internal set; } public static bool ShowMinimumChars { get; internal set; } public static char ListPaddingChar { get; internal set; } public static string ShowPercentagesOrRarity { get; internal set; } public static int MaxCommandHistory { get; internal set; } public static bool ShowTerminalClock { get; internal set; } public static bool DisableIntroSpeech { get; internal set; } public static bool hasBodyHelmetCameraMod { get; internal set; } = true; internal static TextMeshProUGUI ClockText => Clock.GetComponent<TextMeshProUGUI>(); internal static void SetupBodyHelmetCamera(Texture texture) { //IL_0051: 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) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) bodyHelmetCameraImage = Object.Instantiate<RawImage>(global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage, ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.parent); bodyHelmetCameraImage.texture = texture; ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.localScale = new Vector3(0.5f, 0.5f, 1f); ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.localPosition = new Vector3(((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.localPosition.x + 100f, ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.localPosition.y + 75f, ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).transform.localPosition.z); ((Component)bodyHelmetCameraImage).transform.localScale = new Vector3(0.5f, 0.5f, 1f); ((Component)bodyHelmetCameraImage).transform.localPosition = new Vector3(((Component)bodyHelmetCameraImage).transform.localPosition.x + 100f, ((Component)bodyHelmetCameraImage).transform.localPosition.y - 75f, ((Component)bodyHelmetCameraImage).transform.localPosition.z); } internal static void SetBodyHelmetCameraVisibility() { if ((Object)(object)bodyHelmetCameraImage != (Object)null) { ((Behaviour)bodyHelmetCameraImage).enabled = ((Behaviour)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).enabled; } else { if (!hasBodyHelmetCameraMod) { return; } if (Chainloader.PluginInfos.ContainsKey("ShaosilGaming.GeneralImprovements") && (Object)(object)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/MonitorGroup(Clone)") != (Object)null) { if (Chainloader.PluginInfos.ContainsKey("RickArg.lethalcompany.helmetcameras")) { Logger.LogWarning((object)"Unable to use RickArg's HelmetCameras with GeneralImprovements by ShaosilGaming enabled."); } else if (Chainloader.PluginInfos.ContainsKey("Zaggy1024.OpenBodyCams")) { Material material = ((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/MonitorGroup(Clone)/Monitors/BigRight/RScreen").GetComponent<MeshRenderer>()).material; if (((Object)material).name == "BodyCamMaterial (Instance)") { SetupBodyHelmetCamera(material.mainTexture); } else { Logger.LogWarning((object)"Unable to use Zaggy1024's OpenBodyCams with GeneralImprovements by ShaosilGaming if it's not on the bottom right monitor."); } } else if (Chainloader.PluginInfos.ContainsKey("SolosBodycams")) { Logger.LogWarning((object)"Unable to use Solo's BodyCams with GeneralImprovements by ShaosilGaming enabled."); } } else if (Chainloader.PluginInfos.ContainsKey("RickArg.lethalcompany.helmetcameras")) { GameObject val = GameObject.Find("HelmetCamera"); if ((Object)(object)val == (Object)null) { return; } Camera component = val.GetComponent<Camera>(); if ((Object)(object)component == (Object)null) { return; } SetupBodyHelmetCamera((Texture)(object)component.targetTexture); } else if (Chainloader.PluginInfos.ContainsKey("Zaggy1024.OpenBodyCams") || Chainloader.PluginInfos.ContainsKey("SolosBodycams")) { SetupBodyHelmetCamera(((Renderer)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001").GetComponent<MeshRenderer>()).materials[2].mainTexture); } if ((Object)(object)bodyHelmetCameraImage != (Object)null) { ((Behaviour)bodyHelmetCameraImage).enabled = ((Behaviour)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).enabled; } else { hasBodyHelmetCameraMod = false; } } } internal static void SetupClock() { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00c8: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)global::lammOS.NewTerminal.NewTerminal.Terminal).transform.parent.parent.Find("Canvas").Find("MainContainer"); try { Clock = ((Component)val.Find("Clock")).gameObject; } catch { GameObject gameObject = ((Component)val.Find("CurrentCreditsNum")).gameObject; Clock = Object.Instantiate<GameObject>(gameObject, val); ((Object)Clock).name = "Clock"; Clock.transform.localPosition = new Vector3(195f, gameObject.transform.localPosition.y + 9f, gameObject.transform.localPosition.z); Clock.transform.localScale = new Vector3(0.75f, 0.75f, 1f); ((TMP_Text)ClockText).text = ""; ((TMP_Text)ClockText).alignment = (TextAlignmentOptions)260; } } public static void Load() { global::lammOS.Variables.Variables.LoadConfigValues(); global::lammOS.Variables.Variables.LoadKeywords(); global::lammOS.Variables.Variables.LoadMoons(); global::lammOS.Variables.Variables.LoadPurchasables(); global::lammOS.Variables.Variables.LoadEntities(); global::lammOS.Variables.Variables.PostLoadingEntities(); global::lammOS.Variables.Variables.LoadLogs(); global::lammOS.SyncedConfig.SyncedConfig.LoadSyncedConfigValues(); global::lammOS.Macros.Macros.Load(); } public static void Setup() { Load(); SetupClock(); if (!global::lammOS.Commands.Commands.hasSetup) { global::lammOS.Commands.Commands.hasSetup = true; global::lammOS.Commands.Commands.AddCodeCommands(); global::lammOS.Commands.Commands.AddCompatibilityCommands(); } global::lammOS.SyncedConfig.SyncedConfig.SetupSyncedConfig(); } internal void Awake() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Instance = this; Logger = Logger.CreateLogSource("lammOS"); Config = new ConfigFile(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.cfg" }), false, MetadataHelper.GetMetadata((object)this)); new global::lammOS.SyncedConfig.SyncedConfig(); global::lammOS.Commands.Commands.commands = new Dictionary<string, global::lammOS.Commands.Commands.Command>(); global::lammOS.Commands.Commands.shortcuts = new Dictionary<string, string>(); global::lammOS.Variables.Variables.LoadConfigValues(); global::lammOS.Commands.Commands.AddCommands(); global::lammOS.Keybinds.Keybinds.Setup(); global::lammOS.Macros.Macros.Load(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); Logger.LogInfo((object)"lammas123.lammOS Loaded"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "lammOS"; public const string PLUGIN_NAME = "lammOS"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace lammOS.Variables { public static class Variables { public class Moon { public string id; public SelectableLevel level; public TerminalNode node; public string name; public string shortName; public string styledName; public string shortestChars; public Moon(string id, SelectableLevel level, TerminalNode node, string shortName) { this.id = id; this.level = level; this.node = node; name = level.PlanetName; this.shortName = shortName; if (name == shortName) { styledName = name; return; } int num = name.IndexOf(' '); if (num == -1) { styledName = name; } else { styledName = name.Substring(0, num) + "-" + name.Substring(num + 1); } } } public class PurchasableItem { public int index; public Item item; public string name; public string shortestChars; public int salePercentage => global::lammOS.NewTerminal.NewTerminal.Terminal.itemSalesPercentages[index]; public PurchasableItem(int index) { this.index = index; item = global::lammOS.NewTerminal.NewTerminal.Terminal.buyableItemsList[index]; } } public class PurchasableUnlockable { public UnlockableItem unlockable; public TerminalNode node; public string shortestChars; public PurchasableUnlockable(UnlockableItem unlockable, TerminalNode node) { this.unlockable = unlockable; this.node = node; } } public class Entity { public EnemyType type; public TerminalNode entry; public string name; public string shortestChars; public Entity(EnemyType type, TerminalNode entry, string name = null) { this.type = type; this.entry = entry; if (name == null) { name = (((Object)(object)entry == (Object)null) ? type.enemyName : entry.creatureName); } this.name = name; } } public class Log { public TerminalNode log; public string shortestChars; public Log(TerminalNode log) { this.log = log; } } public static Dictionary<string, TerminalKeyword> terminalKeywords = new Dictionary<string, TerminalKeyword>(); internal static TerminalKeyword[] terminalKeywordsBackup; public static Dictionary<string, int> terminalSyncedSounds = new Dictionary<string, int> { { "buy", 0 }, { "error", 1 }, { "loading", 2 }, { "warning", 3 } }; public static Dictionary<string, Moon> moons; public static Dictionary<string, string> moonNameToMoonNode; public static Dictionary<string, PurchasableItem> purchasableItems; public static Dictionary<string, PurchasableUnlockable> purchasableUnlockables; public static Dictionary<string, Entity> entities; public static List<EnemyType> entitiesWithoutEntry; public static List<TerminalNode> entriesWithoutEntity; public static Dictionary<string, Log> logs; public static readonly int DefaultMaxDropshipItems = 12; public static readonly float DefaultMacroInstructionsPerSecond = 5f; internal static void LoadConfigValues() { if (File.Exists(lammOS.Config.ConfigFilePath)) { lammOS.Config.Reload(); } else { lammOS.Config.Clear(); } Dictionary<string, string> dictionary = new Dictionary<string, string>(); Dictionary<string, string> dictionary2 = new Dictionary<string, string> { { "Foggy", "#666666" }, { "Rainy", "#FFFF00" }, { "Stormy", "#FF7700" }, { "Flooded", "#FF0000" }, { "Eclipsed", "#AA0000" } }; string[] names = Enum.GetNames(typeof(LevelWeatherType)); foreach (string text in names) { if (text == "None" || text == "DustClouds") { continue; } ConfigEntry<string> val = lammOS.Config.Bind<string>("Colors", "Weather_" + text + "_Color", "null", (ConfigDescription)null); val.Value = global::lammOS.Commands.Commands.Command.RemoveRichText(val.Value); if (val.Value == "null") { if (dictionary2.ContainsKey(text)) { val.Value = dictionary2[text]; } else { val.Value = "#03e715"; } } dictionary.Add(text, val.Value); } lammOS.WeatherColors = dictionary; lammOS.ShowCommandConfirmations = lammOS.Config.Bind<bool>("General", "ShowCommandConfirmations", true, "If commands like >BUY should ask you for confirmation before doing something.").Value; ConfigEntry<int> val2 = lammOS.Config.Bind<int>("General", "CharsToAutocomplete", 3, "The amount of characters required to autocomplete an argument, such as when buying an item, the minimum value is 1. Values over the length of an argument will be treated as the length of the argument to avoid errors, meaning you'll have to type the full name of the argument and no autocompleting can occur."); if (val2.Value < 1) { val2.Value = 1; } lammOS.CharsToAutocomplete = val2.Value; lammOS.ShowMinimumChars = lammOS.Config.Bind<bool>("General", "ShowMinimumChars", false, "If the minimum characters required for the terminal to autocomplete an argument should be shown. For example: 'p' when buying a pro flashlight, or 'te' for the teleporter, while 'telev' is the minimum for the television. Having this on all the time doesn't look the greatest, but it helps when learning typing shortcuts.").Value; ConfigEntry<string> val3 = lammOS.Config.Bind<string>("General", "ListPaddingChar", ".", "The character that should be used when adding padding to lists. If you want to use a space, the config parser will trim it out, but I will check if the config is empty and replace it with a space."); if (val3.Value == "") { val3.Value = " "; } lammOS.ListPaddingChar = val3.Value[0]; ConfigEntry<string> val4 = lammOS.Config.Bind<string>("General", "ShowPercentagesOrRarity", "Percentage", "Whether a percentage (%) or rarity (fraction) should be shown next to things that have a chance of happening. Percentage or Rarity"); if (val4.Value != "Percentage" && val4.Value != "Rarity") { val4.Value = "Percentage"; } lammOS.ShowPercentagesOrRarity = val4.Value; ConfigEntry<int> val5 = lammOS.Config.Bind<int>("General", "MaxCommandHistory", 25, "How far back the terminal should remember commands you've typed in, the minimum value is 1 and the maximum is 100."); if (val5.Value < 1) { val5.Value = 1; } else if (val5.Value > 100) { val5.Value = 100; } lammOS.MaxCommandHistory = val5.Value; lammOS.ShowTerminalClock = lammOS.Config.Bind<bool>("General", "ShowTerminalClock", true, "If the terminal clock should be shown in the top right corner or not.").Value; lammOS.DisableIntroSpeech = lammOS.Config.Bind<bool>("General", "DisableIntroSpeech", false, "If the intro speech should be disabled.").Value; if ((Object)(object)StartOfRound.Instance != (Object)null) { if (lammOS.DisableIntroSpeech && (Object)(object)lammOS.savedShipIntroSpeechSFX == (Object)null) { lammOS.savedShipIntroSpeechSFX = StartOfRound.Instance.shipIntroSpeechSFX; StartOfRound.Instance.shipIntroSpeechSFX = StartOfRound.Instance.disableSpeakerSFX; } else if (!lammOS.DisableIntroSpeech && (Object)(object)lammOS.savedShipIntroSpeechSFX != (Object)null) { StartOfRound.Instance.shipIntroSpeechSFX = lammOS.savedShipIntroSpeechSFX; lammOS.savedShipIntroSpeechSFX = null; } } lammOS.Config.Save(); } internal static void LoadKeywords() { TerminalKeyword[] allKeywords; if (terminalKeywords.Count != 0) { allKeywords = global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords; foreach (TerminalKeyword val in allKeywords) { if (terminalKeywords.ContainsKey(val.word)) { terminalKeywords.Remove(val.word); } } } allKeywords = global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords; foreach (TerminalKeyword val2 in allKeywords) { if (terminalKeywords.ContainsKey(val2.word)) { lammOS.Logger.LogWarning((object)("A terminal keyword has already been added with the name: '" + val2.word + "'")); } else { terminalKeywords.Add(val2.word, val2); } } } internal static void LoadMoons() { moons = new Dictionary<string, Moon>(); moonNameToMoonNode = new Dictionary<string, string>(); entitiesWithoutEntry = new List<EnemyType>(); Dictionary<int, bool> dictionary = new Dictionary<int, bool>(); for (int i = 0; i < StartOfRound.Instance.levels.Length; i++) { dictionary.Add(i, value: false); } CompatibleNoun[] compatibleNouns = terminalKeywords["route"].compatibleNouns; foreach (CompatibleNoun val in compatibleNouns) { if (moons.ContainsKey(val.noun.word)) { lammOS.Logger.LogWarning((object)("A moon has already been added with the id '" + val.noun.word + "'.")); continue; } if (val.result.terminalOptions[1].result.buyRerouteToMoon < 0 || val.result.terminalOptions[1].result.buyRerouteToMoon >= StartOfRound.Instance.levels.Length) { lammOS.Logger.LogWarning((object)("Moon terminal node '" + val.noun.word + "' with a selectable level index of " + val.result.terminalOptions[1].result.buyRerouteToMoon + " is out of the selectable level range: 0-" + (StartOfRound.Instance.levels.Length - 1))); continue; } SelectableLevel val2 = StartOfRound.Instance.levels[val.result.terminalOptions[1].result.buyRerouteToMoon]; string text = val2.PlanetName.TrimStart('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); if (text.IndexOf(' ') == 0) { text = text.Substring(1); } dictionary[val.result.terminalOptions[1].result.buyRerouteToMoon] = true; Moon moon = new Moon(val.noun.word, val2, val.result.terminalOptions[1].result, text); moons.Add(moon.id, moon); moonNameToMoonNode.Add(val2.PlanetName.ToLower(), moon.id); foreach (SpawnableEnemyWithRarity enemy in moon.level.Enemies) { if (!entitiesWithoutEntry.Contains(enemy.enemyType)) { entitiesWithoutEntry.Add(enemy.enemyType); } } foreach (SpawnableEnemyWithRarity outsideEnemy in moon.level.OutsideEnemies) { if (!entitiesWithoutEntry.Contains(outsideEnemy.enemyType)) { entitiesWithoutEntry.Add(outsideEnemy.enemyType); } } foreach (SpawnableEnemyWithRarity daytimeEnemy in moon.level.DaytimeEnemies) { if (!entitiesWithoutEntry.Contains(daytimeEnemy.enemyType)) { entitiesWithoutEntry.Add(daytimeEnemy.enemyType); } } } foreach (int key in dictionary.Keys) { if (!dictionary[key]) { lammOS.Logger.LogWarning((object)("Could not find a matching terminal node for the moon: " + StartOfRound.Instance.levels[key].PlanetName)); } } foreach (string key2 in moons.Keys) { for (int k = Mathf.Min(key2.Length, lammOS.CharsToAutocomplete); k <= key2.Length; k++) { string text2 = key2.Substring(0, k); bool flag = true; foreach (string key3 in moons.Keys) { if (key2 == key3) { break; } if (key3.StartsWith(text2)) { flag = false; break; } } if (flag) { moons[key2].shortestChars = text2; break; } } if (moons[key2].shortestChars == null) { moons[key2].shortestChars = "ERR"; } } } internal static void LoadPurchasables() { purchasableItems = new Dictionary<string, PurchasableItem>(); for (int i = 0; i < global::lammOS.NewTerminal.NewTerminal.Terminal.buyableItemsList.Length; i++) { purchasableItems.Add(global::lammOS.NewTerminal.NewTerminal.Terminal.buyableItemsList[i].itemName.ToLower(), new PurchasableItem(i)); } foreach (string key in purchasableItems.Keys) { for (int j = Mathf.Min(key.Length, lammOS.CharsToAutocomplete); j < key.Length; j++) { string text = key.Substring(0, j); bool flag = true; foreach (string key2 in purchasableItems.Keys) { if (key == key2) { break; } if (key2.StartsWith(text)) { flag = false; break; } } if (flag) { purchasableItems[key].shortestChars = text; break; } } if (purchasableItems[key].shortestChars == null) { purchasableItems[key].shortestChars = "ERR"; } } purchasableUnlockables = new Dictionary<string, PurchasableUnlockable>(); foreach (UnlockableItem unlockable in StartOfRound.Instance.unlockablesList.unlockables) { if ((Object)(object)unlockable.shopSelectionNode == (Object)null) { bool flag2 = false; for (int k = 0; k < terminalKeywords["buy"].compatibleNouns.Length; k++) { if (unlockable.unlockableName.ToLower().Replace("-", " ").StartsWith(terminalKeywords["buy"].compatibleNouns[k].noun.word.Replace("-", " "))) { if (!purchasableUnlockables.ContainsKey(terminalKeywords["buy"].compatibleNouns[k].result.creatureName.ToLower())) { purchasableUnlockables.Add(terminalKeywords["buy"].compatibleNouns[k].result.creatureName.ToLower(), new PurchasableUnlockable(unlockable, terminalKeywords["buy"].compatibleNouns[k].result)); flag2 = true; break; } lammOS.Logger.LogWarning((object)("A purchasable unlockable has already been added with the name: '" + terminalKeywords["buy"].compatibleNouns[k].result.creatureName.ToLower() + "'")); } } if (!flag2 && !unlockable.alreadyUnlocked && !unlockable.unlockedInChallengeFile && unlockable.unlockableType != 753) { lammOS.Logger.LogWarning((object)("Could not find a matching buy node for the unlockable: '" + unlockable.unlockableName + "'" + unlockable.IsPlaceable)); } } else if (purchasableUnlockables.ContainsKey(unlockable.shopSelectionNode.creatureName.ToLower())) { lammOS.Logger.LogWarning((object)("A purchasable unlockable has already been added with the name: '" + unlockable.shopSelectionNode.creatureName.ToLower() + "'")); } else { purchasableUnlockables.Add(unlockable.shopSelectionNode.creatureName.ToLower(), new PurchasableUnlockable(unlockable, unlockable.shopSelectionNode)); } } foreach (string key3 in purchasableUnlockables.Keys) { for (int l = Mathf.Min(key3.Length, lammOS.CharsToAutocomplete); l < key3.Length; l++) { string text2 = key3.Substring(0, l); bool flag3 = true; foreach (string key4 in purchasableItems.Keys) { if (key3 == key4) { break; } if (key4.StartsWith(text2)) { flag3 = false; break; } } if (!flag3) { continue; } foreach (string key5 in purchasableUnlockables.Keys) { if (key3 == key5) { break; } if (key5.StartsWith(text2)) { flag3 = false; break; } } if (flag3) { purchasableUnlockables[key3].shortestChars = text2; break; } } if (purchasableUnlockables[key3].shortestChars == null) { purchasableUnlockables[key3].shortestChars = "ERR"; } } } public static void AddEntity(EnemyType entity, TerminalNode entry, int entityIndex, string name = null, int entryWithoutEntityIndex = -1) { entities.Add(entity.enemyName, new Entity(entity, entry, name)); if (entityIndex == -1) { return; } entitiesWithoutEntry.RemoveAt(entityIndex); if (entryWithoutEntityIndex != -1) { entriesWithoutEntity.RemoveAt(entryWithoutEntityIndex); } else { if ((Object)(object)entry == (Object)null) { return; } for (int i = 0; i < entriesWithoutEntity.Count; i++) { if (entriesWithoutEntity[i].creatureFileID == entry.creatureFileID) { entriesWithoutEntity.RemoveAt(i); break; } } } } internal static void LoadEntities() { int num = 0; entities = new Dictionary<string, Entity>(); entriesWithoutEntity = new List<TerminalNode>(global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles); while (num < entitiesWithoutEntry.Count) { EnemyType val = entitiesWithoutEntry[num]; switch (val.enemyName) { case "Centipede": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[0], num); continue; case "Flowerman": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[1], num); continue; case "Crawler": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[2], num); continue; case "MouthDog": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[3], num); continue; case "Hoarding bug": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[4], num); continue; case "Blob": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[5], num); continue; case "ForestGiant": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[6], num); continue; case "Spring": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[7], num); continue; case "Lasso": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[8], num); continue; case "Earth Leviathan": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[9], num); continue; case "Jester": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[10], num); continue; case "Puffer": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[11], num); continue; case "Bunker Spider": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[12], num); continue; case "Manticoil": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[13], num); continue; case "Red Locust Bees": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[14], num); continue; case "Docile Locust Bees": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[15], num); continue; case "Baboon hawk": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[16], num); continue; case "Nutcracker": AddEntity(val, global::lammOS.NewTerminal.NewTerminal.Terminal.enemyFiles[17], num); continue; case "Girl": AddEntity(val, null, num, "Ghost girls"); continue; case "Masked": AddEntity(val, null, num); continue; } bool flag = false; for (int i = 0; i < entriesWithoutEntity.Count; i++) { if (entriesWithoutEntity[i].creatureName.ToLower().Replace(" ", "").Replace("-", "") .StartsWith(val.enemyName.ToLower().Replace(" ", "").Replace("-", ""))) { AddEntity(val, entriesWithoutEntity[i], num, entriesWithoutEntity[i].creatureName, i); flag = true; break; } } if (!flag) { num++; } } } internal static void PostLoadingEntities() { foreach (EnemyType item in entitiesWithoutEntry) { lammOS.Logger.LogWarning((object)("The entity '" + item.enemyName + "' could not successfully be matched to a bestiary entry.")); } entitiesWithoutEntry.Clear(); foreach (TerminalNode item2 in entriesWithoutEntity) { if (entities.ContainsKey(item2.creatureName)) { lammOS.Logger.LogWarning((object)("A bestiary entry for the entity '" + item2.creatureName + "' has already been added.")); continue; } lammOS.Logger.LogWarning((object)("The bestiary entry for the entity '" + item2.creatureName + "' could not successfully be matched to an entity. Adding as a standalone bestiary entry.")); entities.Add(item2.creatureName, new Entity(null, item2, item2.creatureName)); } entriesWithoutEntity.Clear(); foreach (Entity value in entities.Values) { for (int i = Mathf.Min(value.name.Length, lammOS.CharsToAutocomplete); i < value.name.Length; i++) { string text = value.name.Substring(0, i).ToLower(); bool flag = true; foreach (Entity value2 in entities.Values) { if (value.name == value2.name) { break; } if (value2.name.ToLower().StartsWith(text)) { flag = false; break; } } if (flag) { value.shortestChars = text; break; } } if (value.shortestChars == null) { value.shortestChars = "ERR"; } } } internal static void LoadLogs() { logs = new Dictionary<string, Log>(); for (int i = 0; i < global::lammOS.NewTerminal.NewTerminal.Terminal.logEntryFiles.Count; i++) { logs.Add(global::lammOS.NewTerminal.NewTerminal.Terminal.logEntryFiles[i].creatureName.ToLower(), new Log(global::lammOS.NewTerminal.NewTerminal.Terminal.logEntryFiles[i])); } foreach (string key in logs.Keys) { for (int j = Mathf.Min(key.Length, lammOS.CharsToAutocomplete); j <= key.Length; j++) { string text = key.Substring(0, j); bool flag = true; foreach (string key2 in logs.Keys) { if (key == key2) { break; } if (key2.StartsWith(text)) { flag = false; break; } } if (flag) { logs[key].shortestChars = text; break; } } if (logs[key].shortestChars == null) { logs[key].shortestChars = "ERR"; } } } internal static void RemoveVanillaKeywords() { terminalKeywordsBackup = (TerminalKeyword[])global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords.Clone(); List<TerminalKeyword> list = new List<TerminalKeyword>(); TerminalKeyword[] allKeywords = global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords; foreach (TerminalKeyword val in allKeywords) { if (val.accessTerminalObjects || val.word == "buy" || val.word == "money" || val.word == "help" || val.word == "store" || val.word == "bestiary" || val.word == "reset credits" || val.word == "inside cam" || val.word == "moons" || val.word == "route" || val.word == "decor" || val.word == "upgrades" || val.word == "sigurd" || val.word == "storage" || val.word == "other" || val.word == "scan" || val.word == "monitor" || val.word == "switch" || val.word == "eject") { continue; } if ((Object)(object)val.defaultVerb != (Object)null) { if (val.defaultVerb.word == "buy" || val.defaultVerb.word == "route") { continue; } if (val.defaultVerb.word == "info") { bool flag = false; CompatibleNoun[] compatibleNouns = terminalKeywords["info"].compatibleNouns; foreach (CompatibleNoun val2 in compatibleNouns) { if (val2 != null && !((Object)(object)val2.noun == (Object)null) && !((Object)(object)val2.result == (Object)null) && val2.noun.word == val.word && val2.result.creatureFileID != -1) { flag = true; break; } } if (flag) { continue; } } if (val.defaultVerb.word == "view") { bool flag2 = false; CompatibleNoun[] compatibleNouns = terminalKeywords["view"].compatibleNouns; foreach (CompatibleNoun val3 in compatibleNouns) { if (val3 != null && !((Object)(object)val3.noun == (Object)null) && !((Object)(object)val3.result == (Object)null) && val3.noun.word == val.word && val3.result.storyLogFileID != -1) { flag2 = true; break; } } if (flag2) { continue; } } } list.Add(val); } global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords = list.ToArray(); } public static int GetMoonCost(string moonId) { float value; float num = (global::lammOS.SyncedConfig.SyncedConfig.Instance.MoonPriceMultipliers.TryGetValue(moonId, out value) ? value : (-1f)); int buyRerouteToMoon = moons[moonId].node.buyRerouteToMoon; moons[moonId].node.buyRerouteToMoon = -1; int itemCost = moons[moonId].node.itemCost; moons[moonId].node.buyRerouteToMoon = buyRerouteToMoon; if (num == -1f) { return itemCost; } if (itemCost == 0) { return (int)num; } return (int)((float)itemCost * num); } public static int GetItemCost(string itemId, bool includeSale = false) { float value; float num = (global::lammOS.SyncedConfig.SyncedConfig.Instance.ItemPriceMultipliers.TryGetValue(itemId, out value) ? value : (-1f)); int creditsWorth = purchasableItems[itemId].item.creditsWorth; if (num == -1f) { if (includeSale) { return (int)((float)(creditsWorth * purchasableItems[itemId].salePercentage) / 100f); } return creditsWorth; } if (creditsWorth == 0) { if (includeSale) { return (int)(num * (float)purchasableItems[itemId].salePercentage / 100f); } return (int)num; } if (includeSale) { return (int)((float)creditsWorth * num * (float)purchasableItems[itemId].salePercentage / 100f); } return (int)((float)creditsWorth * num); } public static int GetUnlockableCost(string unlockableId) { float value; float num = (global::lammOS.SyncedConfig.SyncedConfig.Instance.UnlockablePriceMultipliers.TryGetValue(unlockableId, out value) ? value : (-1f)); int shipUnlockableID = purchasableUnlockables[unlockableId].node.shipUnlockableID; purchasableUnlockables[unlockableId].node.shipUnlockableID = -1; int itemCost = purchasableUnlockables[unlockableId].node.itemCost; purchasableUnlockables[unlockableId].node.shipUnlockableID = shipUnlockableID; if (num == -1f) { return itemCost; } if (itemCost == 0) { return (int)num; } return (int)((float)itemCost * num); } } } namespace lammOS.SyncedConfig { [Serializable] public class SyncedConfig { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnNotifyVersionMismatch; public static HandleNamedMessageDelegate <2>__OnReceiveSync; } internal string ModVersion = Chainloader.PluginInfos["lammas123.lammOS"].Metadata.Version.ToString(); internal Dictionary<string, bool> EnabledCommands; internal Dictionary<string, float> MoonPriceMultipliers; internal Dictionary<string, float> ItemPriceMultipliers; internal Dictionary<string, float> UnlockablePriceMultipliers; internal static ConfigFile Config; internal static SyncedConfig Instance; public int MaxDropshipItems { get; internal set; } = global::lammOS.Variables.Variables.DefaultMaxDropshipItems; public float MacroInstructionsPerSecond { get; internal set; } = global::lammOS.Variables.Variables.DefaultMacroInstructionsPerSecond; internal SyncedConfig() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Instance = this; Config = new ConfigFile(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Synced.cfg" }), false, MetadataHelper.GetMetadata((object)lammOS.Instance)); } internal static void LoadSyncedConfigValues() { if (!NetworkManager.Singleton.IsHost) { return; } if (File.Exists(Config.ConfigFilePath)) { Config.Reload(); } else { Config.Clear(); } Instance.MaxDropshipItems = Config.Bind<int>("Synced", "MaxDropshipItems", global::lammOS.Variables.Variables.DefaultMaxDropshipItems, "The maximum amount of items the dropship can have in it at a time.").Value; if (Instance.MaxDropshipItems < 1) { Instance.MaxDropshipItems = 1; } Instance.MacroInstructionsPerSecond = Config.Bind<float>("Synced", "MacroInstructionsPerSecond", global::lammOS.Variables.Variables.DefaultMacroInstructionsPerSecond, "The number of macro instructions that can be ran per second, ranging from just above 0 to 100.").Value; if (Instance.MacroInstructionsPerSecond <= 0f) { Instance.MacroInstructionsPerSecond = 0.001f; } else if (Instance.MacroInstructionsPerSecond > 100f) { Instance.MacroInstructionsPerSecond = 100f; } Instance.EnabledCommands = new Dictionary<string, bool>(); bool flag = true; foreach (global::lammOS.Commands.Commands.Command command in global::lammOS.Commands.Commands.GetCommands()) { if (!(command is global::lammOS.Commands.Commands.AlphanumericCodeCommand) && !(command is global::lammOS.Commands.Commands.CompatibilityCommand)) { ConfigEntry<bool> val; if (flag) { val = Config.Bind<bool>("Synced - Enabled Commands", command.id + "_Enabled", command.enabled, "Whether a command should be enabled or disabled."); flag = false; } else { val = Config.Bind<bool>("Synced - Enabled Commands", command.id + "_Enabled", command.enabled, (ConfigDescription)null); } Instance.EnabledCommands.Add(command.id, val.Value); } } Instance.MoonPriceMultipliers = new Dictionary<string, float>(); flag = true; foreach (string key in global::lammOS.Variables.Variables.moons.Keys) { ConfigEntry<float> val2; if (flag) { val2 = Config.Bind<float>("Synced - Moon Price Multipliers", key + "_PriceMultiplier", -1f, "If a moon's default price is 0, the multiplier will override the actual price of the moon, otherwise the multiplier will multiply the moon's default price. A price multiplier of -1 will count as the multiplier being disabled."); flag = false; } else { val2 = Config.Bind<float>("Synced - Moon Price Multipliers", key + "_PriceMultiplier", -1f, (ConfigDescription)null); } Instance.MoonPriceMultipliers.Add(key, (val2.Value >= 0f || val2.Value == -1f) ? val2.Value : 0f); } Instance.ItemPriceMultipliers = new Dictionary<string, float>(); flag = true; foreach (string key2 in global::lammOS.Variables.Variables.purchasableItems.Keys) { ConfigEntry<float> val3; if (flag) { val3 = Config.Bind<float>("Synced - Item Price Multipliers", key2 + "_PriceMultiplier", -1f, "If an item's default price is 0, the multiplier will override the actual price of the item, otherwise the multiplier will multiply the item's default price. A price multiplier of -1 will count as the multiplier being disabled."); flag = false; } else { val3 = Config.Bind<float>("Synced - Item Price Multipliers", key2 + "_PriceMultiplier", -1f, (ConfigDescription)null); } Instance.ItemPriceMultipliers.Add(key2, (val3.Value >= 0f || val3.Value == -1f) ? val3.Value : 0f); } Instance.UnlockablePriceMultipliers = new Dictionary<string, float>(); flag = true; foreach (string key3 in global::lammOS.Variables.Variables.purchasableUnlockables.Keys) { ConfigEntry<float> val4; if (flag) { val4 = Config.Bind<float>("Synced - Unlockable Price Multipliers", key3 + "_PriceMultiplier", -1f, "If an unlockable's default price is 0, the multiplier will override the actual price of the unlockable, otherwise the multiplier will multiply the unlockable's default price. A price multiplier of -1 will count as the multiplier being disabled."); flag = false; } else { val4 = Config.Bind<float>("Synced - Unlockable Price Multipliers", key3 + "_PriceMultiplier", -1f, (ConfigDescription)null); } Instance.UnlockablePriceMultipliers.Add(key3, (val4.Value >= 0f || val4.Value == -1f) ? val4.Value : 0f); } Config.Save(); foreach (ulong key4 in StartOfRound.Instance.ClientPlayerList.Keys) { SyncWithClient(key4); } } internal static void SetupSyncedConfig() { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_005a: 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_0065: Expected O, but got Unknown if (NetworkManager.Singleton.IsHost) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("lammOS_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnNotifyVersionMismatch; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnNotifyVersionMismatch; <>O.<1>__OnNotifyVersionMismatch = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("lammOS_OnNotifyVersionMismatch", (HandleNamedMessageDelegate)obj2); } else { Instance.MaxDropshipItems = global::lammOS.Variables.Variables.DefaultMaxDropshipItems; Instance.MacroInstructionsPerSecond = global::lammOS.Variables.Variables.DefaultMacroInstructionsPerSecond; Instance.EnabledCommands = new Dictionary<string, bool>(); Instance.MoonPriceMultipliers = new Dictionary<string, float>(); Instance.ItemPriceMultipliers = new Dictionary<string, float>(); Instance.UnlockablePriceMultipliers = new Dictionary<string, float>(); CustomMessagingManager customMessagingManager3 = NetworkManager.Singleton.CustomMessagingManager; object obj3 = <>O.<2>__OnReceiveSync; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnReceiveSync; <>O.<2>__OnReceiveSync = val3; obj3 = (object)val3; } customMessagingManager3.RegisterNamedMessageHandler("lammOS_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj3); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("lammOS_OnRequestConfigSync", 0uL, new FastBufferWriter(4, (Allocator)2, -1), (NetworkDelivery)3); } } internal static void OnRequestSync(ulong clientId, FastBufferReader _) { SyncWithClient(clientId); } internal static void SyncWithClient(ulong clientId) { //IL_0030: 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_0056: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsHost) { return; } byte[] array = SerializeToBytes(Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(array.Length + 4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("lammOS_OnReceiveConfigSync", clientId, val, (NetworkDelivery)4); } catch (Exception arg) { lammOS.Logger.LogError((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } } internal static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { lammOS.Logger.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { lammOS.Logger.LogError((object)"Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncWithHost(DeserializeFromBytes<SyncedConfig>(data)); } internal static void SyncWithHost(SyncedConfig newConfig) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (Instance.ModVersion != newConfig.ModVersion) { lammOS.Logger.LogWarning((object)("The host is using a different version of the mod than you are, this may lead to certain synced options not syncing properly if the synced config was changed between versions! Your version: " + Instance.ModVersion + " Host's version: " + newConfig.ModVersion)); byte[] array = SerializeToBytes(Instance.ModVersion); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(array.Length + 4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("lammOS_OnNotifyVersionMismatch", 0uL, val, (NetworkDelivery)3); } catch (Exception arg) { lammOS.Logger.LogError((object)$"Error occurred sending version to host: {arg}"); } } Instance.MaxDropshipItems = newConfig.MaxDropshipItems; Instance.MacroInstructionsPerSecond = newConfig.MacroInstructionsPerSecond; Instance.EnabledCommands = newConfig.EnabledCommands; Instance.MoonPriceMultipliers = newConfig.MoonPriceMultipliers; Instance.ItemPriceMultipliers = newConfig.ItemPriceMultipliers; Instance.UnlockablePriceMultipliers = newConfig.UnlockablePriceMultipliers; } internal static void OnNotifyVersionMismatch(ulong clientId, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { lammOS.Logger.LogError((object)"Version notification error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { lammOS.Logger.LogError((object)"Version notification error: Could not read version."); return; } byte[] array = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref array, num, 0); new BinaryFormatter(); using (new MemoryStream(array)) { string text = DeserializeFromBytes<string>(array); string text2 = "Unknown"; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val.actualClientId == clientId) { text2 = ((TMP_Text)val.usernameBillboardText).text; break; } } lammOS.Logger.LogWarning((object)("The client '" + text2 + "' (" + clientId + ") has a different version than your own, this may lead to certain synced options not syncing properly if the synced config was changed between versions! Your version: " + Instance.ModVersion + " Client's version: " + text)); } } internal static byte[] SerializeToBytes<T>(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { lammOS.Logger.LogError((object)$"Error serializing to bytes: {arg}"); return null; } } internal static T DeserializeFromBytes<T>(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { lammOS.Logger.LogError((object)$"Error deserializing from bytes: {arg}"); return default(T); } } } } namespace lammOS.Patches { public static class Patches { [HarmonyPatch(typeof(Terminal))] public static class TerminalPatches { [HarmonyPatch("Awake")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static void PostAwake(ref Terminal __instance) { global::lammOS.NewTerminal.NewTerminal.Terminal = __instance; } [HarmonyPatch("QuitTerminal")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostQuitTerminal(ref Terminal __instance) { __instance.textAdded = 0; global::lammOS.NewTerminal.NewTerminal.inputIndex = 0; if (global::lammOS.NewTerminal.NewTerminal.currentCommand != null) { global::lammOS.NewTerminal.NewTerminal.currentCommand.QuitTerminal(__instance); global::lammOS.NewTerminal.NewTerminal.currentCommand = null; } global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex = -1; } [HarmonyPatch("TextChanged")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static bool PreTextChanged(ref Terminal __instance, ref string newText) { global::lammOS.NewTerminal.NewTerminal.OnTextChanged(); return false; } [HarmonyPatch("OnSubmit")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static bool PreOnSubmit(ref Terminal __instance) { if ((Object)(object)__instance.currentNode != (Object)null && (__instance.currentNode.acceptAnything || __instance.currentNode.overrideOptions)) { global::lammOS.Variables.Variables.RemoveVanillaKeywords(); return true; } global::lammOS.NewTerminal.NewTerminal.OnSubmit(); if (global::lammOS.NewTerminal.NewTerminal.currentCommand == null) { global::lammOS.Variables.Variables.RemoveVanillaKeywords(); return true; } return false; } [HarmonyPatch("OnSubmit")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostOnSubmit() { if (global::lammOS.Variables.Variables.terminalKeywordsBackup != null) { global::lammOS.NewTerminal.NewTerminal.Terminal.terminalNodes.allKeywords = global::lammOS.Variables.Variables.terminalKeywordsBackup; global::lammOS.Variables.Variables.terminalKeywordsBackup = null; } if (global::lammOS.NewTerminal.NewTerminal.currentCommand != null && global::lammOS.NewTerminal.NewTerminal.currentCommand.blockingLevel == global::lammOS.Commands.Commands.BlockingLevel.None) { global::lammOS.NewTerminal.NewTerminal.currentCommand = null; } } [HarmonyPatch("LoadNewNode")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static void PreLoadNewNode(ref TerminalNode node) { node.maxCharactersToType = int.MaxValue; if (!node.clearPreviousText && !node.displayText.StartsWith("</noparse>")) { global::lammOS.NewTerminal.NewTerminal.previousNodeText = node.displayText; node.displayText = "</noparse>" + node.displayText; return; } if (node.displayText.StartsWith(">MOONS\n")) { global::lammOS.NewTerminal.NewTerminal.previousNodeText = node.displayText; node.displayText = global::lammOS.Commands.Commands.HelpCommand.GenerateHelpPage(); node.displayText = global::lammOS.NewTerminal.NewTerminal.HandleDisplayText(node.displayText); return; } if (node.displayText.Contains("Halden Electronics Inc.")) { global::lammOS.NewTerminal.NewTerminal.previousNodeText = node.displayText; node.displayText = global::lammOS.NewTerminal.NewTerminal.HandleDisplayText(node.displayText.Replace("Halden Electronics Inc.", "lammas123").Replace("FORTUNE-9", "lammOS")); return; } int num = node.displayText.IndexOf("Welcome to the FORTUNE-9 OS"); if (num != -1) { global::lammOS.NewTerminal.NewTerminal.previousNodeText = node.displayText; node.displayText = global::lammOS.NewTerminal.NewTerminal.HandleDisplayText(node.displayText.Substring(0, num) + global::lammOS.NewTerminal.NewTerminal.NewTerminalStartupText); } } [HarmonyPatch("LoadNewNode")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostLoadNewNode(ref Terminal __instance, ref TerminalNode node) { global::lammOS.NewTerminal.NewTerminal.SetTerminalText(__instance.screenText.text, 1, selectTextField: false); if (global::lammOS.NewTerminal.NewTerminal.previousNodeText != "") { node.displayText = global::lammOS.NewTerminal.NewTerminal.previousNodeText; global::lammOS.NewTerminal.NewTerminal.previousNodeText = ""; } if (((Behaviour)global::lammOS.NewTerminal.NewTerminal.Terminal.terminalImage).enabled) { lammOS.SetBodyHelmetCameraVisibility(); } } [HarmonyPatch("BuyItemsServerRpc")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static bool PreBuyItemsServerRpc(ref Terminal __instance, ref int[] boughtItems, ref int newGroupCredits, ref int numItemsInShip) { if (!((NetworkBehaviour)__instance).IsHost) { return true; } if (numItemsInShip > global::lammOS.SyncedConfig.SyncedConfig.Instance.MaxDropshipItems) { lammOS.Logger.LogWarning((object)"The item amount purchased by a client goes over max dropship items, canceling purchase"); __instance.SyncGroupCreditsServerRpc(__instance.groupCredits, __instance.numberOfItemsInDropship); return false; } int num = 0; int[] array = boughtItems; foreach (int num2 in array) { foreach (string key in global::lammOS.Variables.Variables.purchasableItems.Keys) { if (global::lammOS.Variables.Variables.purchasableItems[key].index == num2) { num += global::lammOS.Variables.Variables.GetItemCost(key, includeSale: true); } } } if (__instance.groupCredits - num != newGroupCredits) { lammOS.Logger.LogWarning((object)"Items were bought by a client for the incorrect price"); if (__instance.groupCredits - num < 0) { lammOS.Logger.LogWarning((object)"Resulting credits of this purchase is negative, canceling purchase"); __instance.SyncGroupCreditsServerRpc(__instance.groupCredits, __instance.numberOfItemsInDropship); return false; } lammOS.Logger.LogWarning((object)"Resulting credits of this purchase is positive, fix and sync credits but allow purchase"); newGroupCredits = Mathf.Clamp(__instance.groupCredits - num, 0, 10000000); } return true; } } [HarmonyPatch(typeof(StartOfRound))] public static class StartOfRoundPatches { [HarmonyPatch("Awake")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostStart() { if (lammOS.DisableIntroSpeech) { lammOS.savedShipIntroSpeechSFX = StartOfRound.Instance.shipIntroSpeechSFX; StartOfRound.Instance.shipIntroSpeechSFX = StartOfRound.Instance.disableSpeakerSFX; } } [HarmonyPatch("ChangeLevelServerRpc")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static bool PreChangeLevelServerRpc(ref StartOfRound __instance, ref int levelID, ref int newGroupCreditsAmount) { if (!((NetworkBehaviour)__instance).IsHost) { return true; } string text = null; foreach (string key in global::lammOS.Variables.Variables.moons.Keys) { if (global::lammOS.Variables.Variables.moons[key].node.buyRerouteToMoon == levelID) { text = key; break; } } if (text == null) { return true; } int moonCost = global::lammOS.Variables.Variables.GetMoonCost(text); if (global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - moonCost != newGroupCreditsAmount) { lammOS.Logger.LogWarning((object)"Routing to moon was bought by a client for an incorrect price"); if (global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - moonCost < 0) { lammOS.Logger.LogWarning((object)"Resulting credits of routing is negative, canceling purchase"); global::lammOS.NewTerminal.NewTerminal.Terminal.SyncGroupCreditsServerRpc(global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits, global::lammOS.NewTerminal.NewTerminal.Terminal.numberOfItemsInDropship); return false; } lammOS.Logger.LogWarning((object)"Resulting credits of routing is positive, fix and sync credits but allow purchase"); newGroupCreditsAmount = Mathf.Clamp(global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - moonCost, 0, 10000000); } return true; } [HarmonyPatch("BuyShipUnlockableServerRpc")] [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] public static bool PreBuyShipUnlockableServerRpc(ref StartOfRound __instance, ref int unlockableID, ref int newGroupCreditsAmount) { if (!((NetworkBehaviour)__instance).IsHost) { return true; } string text = null; foreach (string key in global::lammOS.Variables.Variables.purchasableUnlockables.Keys) { if (global::lammOS.Variables.Variables.purchasableUnlockables[key].node.shipUnlockableID == unlockableID) { text = key; break; } } if (text == null) { return true; } int unlockableCost = global::lammOS.Variables.Variables.GetUnlockableCost(text); if (global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - unlockableCost != newGroupCreditsAmount) { lammOS.Logger.LogWarning((object)"Unlockable bought by a client for an incorrect price"); if (global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - unlockableCost < 0) { lammOS.Logger.LogWarning((object)"Resulting credits of purchase is negative, canceling purchase"); global::lammOS.NewTerminal.NewTerminal.Terminal.SyncGroupCreditsServerRpc(global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits, global::lammOS.NewTerminal.NewTerminal.Terminal.numberOfItemsInDropship); return false; } lammOS.Logger.LogWarning((object)"Resulting credits of purchase is positive, fix and sync credits but allow purchase"); newGroupCreditsAmount = Mathf.Clamp(global::lammOS.NewTerminal.NewTerminal.Terminal.groupCredits - unlockableCost, 0, 10000000); } return true; } [HarmonyPatch("SwitchMapMonitorPurpose")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostSwitchMapMonitorPurpose(ref bool displayInfo) { if (displayInfo && (Object)(object)lammOS.bodyHelmetCameraImage != (Object)null) { ((Behaviour)lammOS.bodyHelmetCameraImage).enabled = false; } } [HarmonyPatch("SyncShipUnlockablesClientRpc")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostSyncShipUnlockablesClientRpc() { GrabbableObject[] array = Object.FindObjectsByType<GrabbableObject>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (GrabbableObject obj in array) { obj.isInShipRoom = true; obj.isInFactory = false; } } } [HarmonyPatch(typeof(RoundManager))] public static class RoundManagerPatches { [HarmonyPatch("Start")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostStart() { lammOS.Setup(); } } [HarmonyPatch(typeof(HUDManager))] public static class HUDManagerPatches { [HarmonyPatch("SetClock")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostSetClock(ref HUDManager __instance) { if (lammOS.ShowTerminalClock) { ((TMP_Text)lammOS.ClockText).text = ((TMP_Text)__instance.clockNumber).text.Replace("\n", " "); } else { ((TMP_Text)lammOS.ClockText).text = ""; } } [HarmonyPatch("FillEndGameStats")] [HarmonyPostfix] [HarmonyPriority(int.MinValue)] public static void PostFillEndGameStats() { ((TMP_Text)lammOS.ClockText).text = ""; } } } } namespace lammOS.NewTerminal { public static class NewTerminal { public static readonly int MaxTerminalLineWidth = 50; public static bool saveSubmissionsToHistory = true; internal static List<string> commandHistory = new List<string>(); internal static int commandHistoryIndex = -1; internal static string lastTypedCommand = ""; internal static string previousNodeText = ""; public static readonly string NewTerminalStartupText = "Powered by lammOS Created by <color=#007fff>lammas123</color>\n Courtesy of the Company\n\nType HELP for a list of available commands."; public static Terminal Terminal { get; internal set; } public static int inputIndex { get; internal set; } = 0; public static global::lammOS.Commands.Commands.Command currentCommand { get; internal set; } = null; public static string HandleDisplayText(string text) { if (Object.op_Implicit((Object)(object)Terminal.displayingPersistentImage)) { text = text.Replace("\n\n\nn\n\n\n", ""); } text = text.TrimStart('\n').TrimEnd('\n'); if (text == "") { return "><noparse>"; } if (text.EndsWith("\n\n><noparse>")) { return text; } return text + "\n\n><noparse>"; } public static string HandleInputText(string input) { return input.Replace("<noparse>", "").Replace("</noparse>", ""); } public static void SetTerminalText(string text, int forceScroll = 1, bool selectTextField = true) { Terminal.modifyingText = true; text = "\n\n" + HandleDisplayText(text); inputIndex = text.Length; Terminal.screenText.text = text; if (selectTextField) { Terminal.screenText.ActivateInputField(); ((Selectable)Terminal.screenText).Select(); } ForceScrollbar(forceScroll); } public static void SetDisplayText(string text, int forceScroll = 1, bool selectTextField = true) { Terminal.modifyingText = true; string text2 = Terminal.screenText.text.Substring(inputIndex); text = "\n\n" + HandleDisplayText(text); inputIndex = text.Length - text2.Length; Terminal.screenText.text = text + text2; if (selectTextField) { Terminal.screenText.ActivateInputField(); ((Selectable)Terminal.screenText).Select(); } ForceScrollbar(forceScroll); } public static void SetInputText(string text, int forceScroll = -1, bool selectTextField = true) { Terminal.screenText.text = Terminal.screenText.text.Substring(0, inputIndex) + HandleInputText(text); if (selectTextField) { Terminal.screenText.ActivateInputField(); ((Selectable)Terminal.screenText).Select(); } ForceScrollbar(forceScroll); } public static void AppendTerminalText(string text, int forceScroll = -1, bool selectTextField = true) { Terminal.modifyingText = true; text = "</noparse>\n\n" + HandleDisplayText(text); inputIndex = Terminal.screenText.text.Length + text.Length; TMP_InputField screenText = Terminal.screenText; screenText.text += text; if (selectTextField) { Terminal.screenText.ActivateInputField(); ((Selectable)Terminal.screenText).Select(); } ForceScrollbar(forceScroll); } public static void PlaySyncedClip(int clipIndex) { if (clipIndex < 0 || clipIndex >= Terminal.syncedAudios.Length) { lammOS.Logger.LogWarning((object)(clipIndex + " is outside the synced clip index range of 0-" + (Terminal.syncedAudios.Length - 1) + ".")); } else { Terminal.PlayTerminalAudioServerRpc(clipIndex); } } public static void PlayClip(AudioClip clip) { if ((Object)(object)clip == (Object)null) { lammOS.Logger.LogWarning((object)"The provided audio clip may not be null."); } else { Terminal.terminalAudio.PlayOneShot(clip); } } public static void ForceScrollbar(int forceScroll = 1) { if (forceScroll < 0) { if (Terminal.forceScrollbarCoroutine != null) { ((MonoBehaviour)Terminal).StopCoroutine(Terminal.forceScrollbarCoroutine); } Terminal.forceScrollbarCoroutine = ((MonoBehaviour)Terminal).StartCoroutine(Terminal.forceScrollbarDown()); } else if (forceScroll > 0) { if (Terminal.forceScrollbarCoroutine != null) { ((MonoBehaviour)Terminal).StopCoroutine(Terminal.forceScrollbarCoroutine); } Terminal.forceScrollbarCoroutine = ((MonoBehaviour)Terminal).StartCoroutine(Terminal.forceScrollbarUp()); } } public static void OnTextChanged() { if (commandHistoryIndex != -1 && (inputIndex > Terminal.screenText.text.Length || commandHistory[commandHistoryIndex] != Terminal.screenText.text.Substring(inputIndex))) { commandHistoryIndex = -1; } if (Terminal.modifyingText) { Terminal.modifyingText = false; Terminal.currentText = Terminal.screenText.text; Terminal.textAdded = Terminal.screenText.text.Length - inputIndex; return; } if (inputIndex > Terminal.screenText.text.Length) { Terminal.screenText.text = Terminal.currentText; return; } string text = Terminal.screenText.text.Substring(inputIndex); string text2 = HandleInputText(text); if (text != text2) { Terminal.screenText.text = Terminal.screenText.text.Substring(0, inputIndex) + text2; return; } if (currentCommand != null && currentCommand.blockingLevel >= global::lammOS.Commands.Commands.BlockingLevel.UntilTyping) { currentCommand.Handle(Terminal, Terminal.screenText.text.Substring(inputIndex)); return; } Terminal.currentText = Terminal.screenText.text; Terminal.textAdded = Terminal.screenText.text.Length - inputIndex; } public static void OnSubmit() { if (!Terminal.terminalInUse) { return; } string text = Terminal.screenText.text.Substring(inputIndex); if (text == "") { return; } if (saveSubmissionsToHistory) { commandHistory.Add(text); while (commandHistory.Count > lammOS.MaxCommandHistory) { commandHistory.RemoveAt(0); } } HandleCommand(text); } public static void HandleCommand(string input) { if (currentCommand != null) { try { currentCommand.Handle(Terminal, input); return; } catch (Exception ex) { lammOS.Logger.LogError((object)("An error occurred handling the current command: '" + currentCommand.id + "'\n" + ex.ToString())); global::lammOS.Commands.Commands.Command.ErrorResponse("An error occurred handling the current command: '" + currentCommand.id + "'"); return; } } int num = input.IndexOf(' '); string text; string text2; if (num == -1) { text = input; text2 = ""; } else { text = input.Substring(0, num); text2 = input.Substring(num + 1); } if (global::lammOS.Commands.Commands.IsShortcut(text)) { text = global::lammOS.Commands.Commands.GetCommandIdByShortcut(text); SetInputText((text + " " + text2).TrimEnd(' ')); } global::lammOS.Commands.Commands.Command command = global::lammOS.Commands.Commands.GetCommand(text); if (command == null || command is global::lammOS.Commands.Commands.CommandArgument || command is global::lammOS.Commands.Commands.CompatibilityCommand) { return; } currentCommand = command; if (!command.enabled) { global::lammOS.Commands.Commands.Command.ErrorResponse("That command has been disabled by the host."); return; } try { command.Execute(Terminal, text2); } catch (Exception ex2) { lammOS.Logger.LogError((object)("An error occurred executing the command: '" + text + "'\n" + ex2.ToString())); global::lammOS.Commands.Commands.Command.ErrorResponse("An error occurred executing the command: '" + text + "'"); } } } } namespace lammOS.Macros { public static class Macros { internal static Dictionary<string, List<string>> macros = new Dictionary<string, List<string>>(); public static bool AddMacro(string id, List<string> inputs) { if (HasMacro(id)) { return false; } macros.Add(id, new List<string>(inputs)); return true; } public static bool HasMacro(string id) { return macros.ContainsKey(id); } public static List<string> GetMacro(string id) { if (!HasMacro(id)) { return null; } return new List<string>(macros[id]); } public static List<string> GetMacroIds() { return new List<string>(macros.Keys); } public static bool ModifyMacro(string id, List<string> inputs) { if (!HasMacro(id)) { return false; } macros[id] = new List<string>(inputs); return true; } public static bool RemoveMacro(string id) { if (!HasMacro(id)) { return false; } macros.Remove(id); return true; } public static void Save() { List<string> list = new List<string>(); foreach (string key in macros.Keys) { list.Add("[" + key + "]"); list.AddRange(macros[key]); } File.WriteAllText(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.txt" }), string.Join('\n', list)); } public static void Load() { if (File.Exists(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.es3" }))) { macros = ES3.Load<Dictionary<string, List<string>>>("lammOS_Macros", Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.es3" })); File.Delete(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.es3" })); Save(); } else if (File.Exists(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.txt" }))) { string[] array = File.ReadAllText(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "lammas123.lammOS.Macros.txt" })).Split('\n'); string text = null; macros = new Dictionary<string, List<string>>(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text2 = array2[i].Trim(); if (text2 == "") { continue; } if (text2.StartsWith('[') && text2.EndsWith(']')) { string text3 = text2.Substring(1, text2.Length - 2).Trim(); if (!(text3 == "") && !macros.ContainsKey(text3)) { if (text != null && macros[text].Count == 0) { macros.Remove(text); } text = text3; macros.Add(text, new List<string>()); } } else if (text != null) { macros[text].Add(text2); } } if (text != null && macros[text].Count == 0) { macros.Remove(text); } } else { macros = new Dictionary<string, List<string>>(); Save(); } } } } namespace lammOS.Keybinds { internal class Keybinds : LcInputActions { internal static Keybinds Instance; [InputAction("<Keyboard>/leftArrow", Name = "Previous Radar Target")] internal InputAction PreviousRadarTargetKey { get; set; } [InputAction("<Keyboard>/rightArrow", Name = "Next Radar Target")] internal InputAction NextRadarTargetKey { get; set; } [InputAction("<Keyboard>/upArrow", Name = "Previous Command History")] internal InputAction PreviousCommandHistoryKey { get; set; } [InputAction("<Keyboard>/downArrow", Name = "Next Command History")] internal InputAction NextCommandHistoryKey { get; set; } internal static void Setup() { Instance = new Keybinds(); Instance.PreviousRadarTargetKey.performed += OnPreviousRadarTargetKeyPressed; Instance.NextRadarTargetKey.performed += OnNextRadarTargetKeyPressed; Instance.PreviousCommandHistoryKey.performed += OnPreviousCommandHistoryKeyPressed; Instance.NextCommandHistoryKey.performed += OnNextCommandHistoryKeyPressed; } internal static void OnPreviousRadarTargetKeyPressed(CallbackContext context) { PreviousRadarTarget(); } public static void PreviousRadarTarget() { if (!GameNetworkManager.Instance.localPlayerController.inTerminalMenu) { return; } int num = StartOfRound.Instance.mapScreen.targetTransformIndex - 1; for (int i = 0; i < StartOfRound.Instance.mapScreen.radarTargets.Count; i++) { if (num == -1) { num = StartOfRound.Instance.mapScreen.radarTargets.Count - 1; } if (StartOfRound.Instance.mapScreen.radarTargets[num] == null) { num--; continue; } if (StartOfRound.Instance.mapScreen.radarTargets[num].isNonPlayer) { break; } PlayerControllerB component = ((Component)StartOfRound.Instance.mapScreen.radarTargets[num].transform).gameObject.GetComponent<PlayerControllerB>(); if ((Object)(object)component == (Object)null || component.isPlayerControlled || component.isPlayerDead || (Object)(object)component.redirectToEnemy != (Object)null) { break; } num--; } StartOfRound.Instance.mapScreen.SwitchRadarTargetAndSync(num); } internal static void OnNextRadarTargetKeyPressed(CallbackContext context) { NextRadarTarget(); } public static void NextRadarTarget() { if (GameNetworkManager.Instance.localPlayerController.inTerminalMenu) { StartOfRound.Instance.mapScreen.SwitchRadarTargetAndSync((StartOfRound.Instance.mapScreen.targetTransformIndex + 1) % StartOfRound.Instance.mapScreen.radarTargets.Count); } } internal static void OnPreviousCommandHistoryKeyPressed(CallbackContext context) { PreviousCommandHistory(); } public static void PreviousCommandHistory() { if (GameNetworkManager.Instance.localPlayerController.inTerminalMenu && global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex != 0 && global::lammOS.NewTerminal.NewTerminal.commandHistory.Count != 0) { if (global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex == -1) { global::lammOS.NewTerminal.NewTerminal.lastTypedCommand = global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Substring(global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Length - global::lammOS.NewTerminal.NewTerminal.Terminal.textAdded); global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex = global::lammOS.NewTerminal.NewTerminal.commandHistory.Count; } global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex--; global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text = global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Substring(0, global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Length - global::lammOS.NewTerminal.NewTerminal.Terminal.textAdded) + global::lammOS.NewTerminal.NewTerminal.commandHistory[global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex]; } } internal static void OnNextCommandHistoryKeyPressed(CallbackContext context) { NextCommandHistory(); } public static void NextCommandHistory() { if (GameNetworkManager.Instance.localPlayerController.inTerminalMenu && global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex != -1) { global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex++; if (global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex == global::lammOS.NewTerminal.NewTerminal.commandHistory.Count) { global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex = -1; global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text = global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Substring(0, global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Length - global::lammOS.NewTerminal.NewTerminal.Terminal.textAdded) + global::lammOS.NewTerminal.NewTerminal.lastTypedCommand; } else { global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text = global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Substring(0, global::lammOS.NewTerminal.NewTerminal.Terminal.screenText.text.Length - global::lammOS.NewTerminal.NewTerminal.Terminal.textAdded) + global::lammOS.NewTerminal.NewTerminal.commandHistory[global::lammOS.NewTerminal.NewTerminal.commandHistoryIndex]; } } } } } namespace lammOS.Commands { public static class Commands { public enum BlockingLevel { None, UntilSubmission, UntilTyping, All } public class HelpCommand : Command { public HelpCommand() { category = "Helpful"; base.id = "help"; description = "View helpful information about available commands. Why did you need help to know what help does?"; AddShortcut("?", base.id); AddShortcut("h", base.id); args = "[Command]"; } public static string GenerateHelpPage() { Dictionary<string, List<Command>> dictionary = new Dictionary<string, List<Command>>(); foreach (Command command in GetCommands()) { if (!command.hidden) { if (!dictionary.ContainsKey(command.category)) { dictionary[command.category] = new List<Command>(); } dictionary[command.category].Add(command); } } string text = ""; foreach (string key in dictionary.Keys) { text = text + "\n [" + key + "]\n"; foreach (Command item in dictionary[key]) { if (!item.enabled) { text += "DISABLED "; } text = text + ">" + item.id.ToUpper(); if (item.args != "") { text = text + " " + item.args; } text += "\n"; } } return text; } public static string GenerateCommandHelp(Command command) { string text = " [" + command.category + "]\n"; if (!command.enabled) { text += "DISABLED "; } text = text + ">" + command.id.ToUpper(); if (command.args != "") { text = text + " " + command.args; } List<string> list = new List<string>(); foreach (string shortcut in GetShortcuts()) { if (GetCommandIdByShortcut(shortcut) == command.id) { list.Add(">" + shortcut.ToUpper()); } } if (list.Count != 0) { text = text + " - " + string.Join(", ", list); } return text + "\n * " + command.description; } public override void Execute(Terminal terminal, string input) { if (input == "") { global::lammOS.NewTerminal.NewTerminal.SetTerminalText(GenerateHelpPage()); return; } input = input.ToLower(); if (IsShortcut(input)) { input = GetCommandIdByShortcut(input); } Command command = GetCommand(input); if (command == null) { Command.ErrorResponse("No command command found with id: '" + input + "'"); } else { global::lammOS.NewTerminal.NewTerminal.SetTerminalText(GenerateCommandHelp(command)); } } } public class ShortcutsCommand : Command { public ShortcutsCommand() { category = "Helpful"; base.id = "shortcuts"; description = "View all of the shortcuts there are for commands."; AddShortcut("sh", base.id); } public override void Execute(Terminal terminal, string input) { int num = 0; foreach (string shortcut in GetShortcuts()) { Command command = GetCommand(GetCommandIdByShortcut(shortcut)); if (!command.hidden && command.id.Length + 1 > num) { num = command.id.Length + 1; } } Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); foreach (string shortcut2 in GetShortcuts()) { Command command2 = GetCommand(GetCommandIdByShortcut(shortcut2)); if (!command2.hidden) { if (!dictionary.ContainsKey(command2.category)) { dictionary[command2.category] = new List<string>(); } dictionary[command2.category].Add(">" + (command2.id.ToUpper() + " ").PadRight(num, lammOS.ListPaddingChar) + " >" + shortcut2.ToUpper() + "\n"); } } string text = ""; foreach (string key in dictionary.Keys) { text = text + "\n [" + key + "]\n"; foreach (string item in dictionary[key]) { text += item; } } if (text == "") { text = "There are no shortcuts for any commands."; } global::lammOS.NewTerminal.NewTerminal.SetTerminalText(text); } } public class MoonsCommand : Command { public MoonsCommand() { category = "Moons"; base.id = "moons"; description = "Lists the available moons you can travel to."; AddShortcut("ms", base.id); } public static string GenerateMoonIndexWeather(global::lammOS.Variables.Variables.Moon moon) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 if ((int)moon.level.currentWeather != -1) { string text = ((object)(LevelWeatherType)(ref moon.level.currentWeather)).ToString(); if (lammOS.WeatherColors.ContainsKey(text)) { text = "<color=" + lammOS.WeatherColors[text] + ">" + text + "</color>"; } return " (" + text + ") " + (moon.level.spawnEnemiesAndScrap ? "" : ("(" + (int)(StartOfRound.Instance.companyBuyingRate * 100f) + "%) ")); } if (!moon.level.spawnEnemiesAndScrap) { return " (" + (int)(StartOfRound.Instance.companyBuyingRate * 100f) + "%) "; } return null; } public static string GenerateMoonIndexCost(global::lammOS.Variables.Variables.Moon moon) { int moonCost = global::lammOS.Variables.Variables.GetMoonCost(moon.id); if (moonCost == 0) { return null; } return moonCost.ToString(); } public static void GenerateMoonIndex(global::lammOS.Variables.Variables.Moon moon, List<List<string>> itemLists) { itemLists[0].Add((lammOS.ShowMinimumChars ? ("(" + moon.shortestChars + ") ") : "") + ((moon.name == "71 Gordion") ? "The Company building" : moon.shortName) + " "); itemLists[1].Add(GenerateMoonIndexWeather(moon)); itemLists[2].Add(GenerateMoonIndexCost(moon)); } public static string GenerateMoonsList(List<global::lammOS.Variables.Variables.Moon> moonsList) { List<List<string>> itemLists = new List<List<string>> { new List<string>(), new List<string>(), new List<string>() }; foreach (global::lammOS.Variables.Variables.Moon moons in moonsList) { GenerateMoonIndex(moons, itemLists); } return Command.HandleListPadding(itemLists, new List<string> { " * {ITEM}", "{ITEM}", " ${ITEM} " }, new List<string> { "", "", "right" }); } public override void Execute(Terminal terminal, string input) { List<global::lammOS.Variables.Variables.Moon> list = new List<global::lammOS.Variables.Variables.Moon>(); list.Add(global::lammOS.Variables.Variables.moons["company"]); SelectableLevel[] moonsCatalogueList = terminal.moonsCatalogueList; foreach (SelectableLevel val in moonsCatalogueList) { global::lammOS.Variables.Variables.Moon moon = null; foreach (global::lammOS.Variables.Variables.Moon value in global::lammOS.Variables.Variables.moons.Values) { if ((Object)(object)value.level == (Object)(object)val) { moon = value; break; } } if (moon == null) { lammOS.Logger.LogWarning((object)(">MOONS - Couldn't generate moon index for the moon '" + val.PlanetName + "'.")); } else { list.Add(moon); } } global::lammOS.NewTerminal.NewTerminal.SetTerminalText("Welcome to the exomoons catalogue.\nUse the MOON [Moon] command for more details regarding a moon, and use the ROUTE <Moon> command to route the autopilot to a moon of your choice.\n" + GenerateMoonsList(list)); } } public class MoonCommand : Command { public MoonCommand() { category = "Moons"; base.id = "moon"; description = "View information about a moon."; AddShortcut("m", base.id); args = "[Moon]"; } public static string GeneratePercentageOrRarity(int rarity, int totalRarity) { if (lammOS.ShowPercentagesOrRarity == "Percentage") { return (float)(rarity * 100) / (float)totalRarity + "%"; } return rarity + "/" + totalRarity; } public static string GenerateDetailedWeather(global::lammOS.Variables.Variables.Moon moon) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 string text = "\n\nTypes of Weather:"; bool flag = false; RandomWeatherWithVariables[] randomWeathers = moon.level.randomWeathers; foreach (RandomWeatherWithVariables val in randomWeathers) { if ((int)val.weatherType != -1) { text = text + "\n * " + ((object)(LevelWeatherType)(ref val.weatherType)).ToString(); flag = true; } } if (!flag) { text += "\n * None"; } return text; } public static string GenerateDetailedIndoors(global::lammOS.Variables.Variables.Moon moon) { string text = "\n\nIndoor Size Multiplier: x" + moon.level.factorySizeMultiplier + "\n\nIndoor Type Rarities:"; if (moon.level.dungeonFlowTypes.Length == 0) { return text + "\n * 0: " + GeneratePercentageOrRarity(1, 1); } int num = 0; IntWithRarity[] dungeonFlowTypes = moon.level.dungeonFlowTypes; foreach (IntWithRarity val in dungeonFlowTypes) { num += val.rarity; } dungeonFlowTypes = moon.level.dungeonFlowTypes; foreach (IntWithRarity val2 in dungeonFlowTypes) { if (val2.rarity != 0) { text = text + "\n * " + val2.id + ": " + GeneratePercentageOrRarity(val2.rarity, num); } } return text; } public static string GenerateDetailedScrap(global::lammOS.Variables.Variables.Moon moon) { List<List<string>> list = new List<List<string>> { new List<string>(), new List<string>() }; int num = 0; foreach (SpawnableItemWithRarity item in moon.level.spawnableScrap) { if (item.rarity != 0) { num += item.rarity; } } foreach (SpawnableItemWithRarity item2 in moon.level.spawnableScrap) { if (item2.rarity != 0) { list[0].Add(item2.spawnableItem.itemName + " "); list[1].Add(GeneratePercentageOrRarity(item2.rarity, num)); } } return "\n\nMin/Max Scrap: " + moon.level.minScrap + "/" + moon.level.maxScrap + "\nMin/Max Scrap Value: " + moon.level.minTotalScrapValue + "/" + moon.level.maxTotalScrapValue + "\n\nSpawnable Scrap:\n" + Command.HandleListPadding(list, new List<string> { " * {ITEM}", " {ITEM} " }, new List<string> { "", "right" }, separator: false); } public static string GenerateDetailedEntityGroup(List<SpawnableEnemyWithRarity> entityList, string area) { if (entityList.Count == 0) { return "No " + area + " entities spawn on this moon."; } List<List<string>> list = new List<List<string>> { new List<string>(), new List<string>(), new List<string>(), new List<string>() }; int num = 0; foreach (SpawnableEnemyWithRarity entity in entityList) { if (entity.rarity != 0) { num += entity.rarity; } } foreach (SpawnableEnemyWithRarity entity2 in entityList) { if (entity2.rarity != 0) { list[0].Add(global::lammOS.Variables.Variables.entities[entity2.enemyType.enemyName].name + " "); list[1].Add(" (" + entity2.enemyType.PowerLevel); list[2].Add(entity2.enemyType.MaxCount + ") "); list[3].Add(GeneratePercentageOrRarity(entity2.rarity, num)); } } return Command.HandleListPadding(list, new List<string> { " * {ITEM}", "{ITEM} :", " {ITEM}", "{ITEM} " }, new List<string> { "", "left", "right", "right" }, separator: false); } public static string GenerateDetailedEntities(global::lammOS.Variables.Variables.Moon moon) { return "\n\nMax Entity Power:\n * Daytime: " + moon.level.maxDaytimeEnemyPowerCount + "\n * Indoor: " + moon.level.maxEnemyPowerCount + "\n * Outdoor: " + moon.level.maxOutsideEnemyPowerCount + "\n\nDaytime Entities: (Power : Max Amount)\n" + GenerateDetailedEntityGroup(moon.level.DaytimeEnemies, "daytime") + "\n\nIndoor Entities: (Power : Max Amount)\n" + GenerateDetailedEntityGroup(moon.level.Enemies, "indoor") + "\n\nOutdoor Entities: (Power : Max Amount)\n" + GenerateDetailedEntityGroup(moon.level.OutsideEnemies, "outdoor"); } public static string GenerateDetailedSafety(global::lammOS.Variables.Variables.Moon moon) { string text = ""; bool flag = false; bool flag2 = false; for (float num = 0f; num < 1f; num += 0.05f) { if (flag && flag2) { break; } if (!flag && moon.level.enemySpawnChanceThroughoutDay.Evaluate(num) > 0f) { float num2 = (num * 0.75f + 0.25f) * 24f; int num3 = (int)num2; string text2 = ((int)((num2 - (float)num3) * 60f)).ToString(); string text3 = "AM"; if (num3 >= 12) { num3 -= 12; text3 = "PM"; } text = text + "\n\nIndoors Safe Until Around: " + num3 + ":" + ((text2.Length == 1) ? "0" : "") + text2 + " " + text3; flag = true; } if (!flag2 && moon.level.outsideEnemySpawnChanceThroughDay.Evaluate(num) > 0f) { float num4 = (num * 0.75f + 0.25f) * 24f; int num5 = (int)num4; string text4 = ((int)((num4 - (float)num5) * 60f)).ToString(); string text5 = "AM"; if (num5 >= 12) { num5 -= 12; text5 = "PM"; } text = text + "\nOutdoors Safe Until Around: " + num5 + ":" + ((text4.Length == 1) ? "0" : "") + text4 + " " + text5; flag2 = true; } } return text; } public static string GenerateDetailedResult(global::lammOS.Variables.Variables.Moon moon) { return GenerateDetailedWeather(moon) + GenerateDetailedIndoors(moon) + GenerateDetailedScrap(moon) + GenerateDetailedEntities(moon) + GenerateDetailedSafety(moon); } public override void Execute(Terminal terminal, string input) { global::lammOS.Variables.Variables.Moon moon = null; if (input == "") { foreach (global::lammOS.Variables.Variables.Moon value in global::lammOS.Variables.Variables.moons.Values) { if ((Object)(object)value.level == (Object)(object)StartOfRound.Instance.currentLevel) { moon = value; break; } } } else { input = input.ToLower(); string text = null; foreach (string key in global::lammOS.Variables.Variables.moons.Keys) { if (key.StartsWith(input)) { moon = global::lammOS.Variables.Variables.moons[key]; text = key; break; } } if (moon == null) { Command.ErrorResponse("No moon goes by the name: '" + input + "'"); return; } if (Command.CheckNotEnoughChars(input.Length, text.Length)) { return; } } string text2 = MoonsCommand.GenerateMoonIndexCost(moon); string text3 = MoonsCommand.GenerateMoonIndexWeather(moon); string text4 = moon.styledName + (text3 ?? " ") + ((text2 == null) ? "" : ("$" + text2)) + "\n\n" + moon.level.LevelDescription; if (moon.level.spawnEnemiesAndScrap) { text4 += GenerateDetailedResult(moon); } global::lammOS.NewTerminal.NewTerminal.SetTerminalText(text4); } } public class RouteCommand : ConfirmationCommand { public global::lammOS.Variables.Variables.Moon moon; public RouteCommand() { category = "Moons"; base.id = "route"; description = "Travel to the specified moon."; AddShortcut("r", base.id); args = "<Moon>"; } public override void Execute(Terminal terminal, string input) { if (StartOfRound.Instance.isChallengeFile) { Command.ErrorResponse("You cannot route to another moon while on a challenge moon save file."); return; } if (input == "") { Command.ErrorResponse("Please enter a moon to route the autopilot to."); return; } input = input.ToLower(); global::lammOS.Variables.Variables.Moon moon = null; string text = null; foreach (string key in global::lammOS.Variables.Variables.moons.Keys) { if (key.StartsWith(input)) { moon = global::lammOS.Variables.Variables.moons[key]; text = key; break; } } if (moon == null) { Command.ErrorResponse("No moon goes by the name: '" + input + "'"); } else if (!Command.CheckNotEnoughChars(input.Length, text.Length)) { this.moon = moon; if (lammOS.ShowCommandConfirmations) { blockingLevel = BlockingLevel.UntilSubmission; global::lammOS.NewTerminal.NewTerminal.SetTerminalText("Would you like to route to " + moon.level.PlanetName + " for $" + global::lammOS.Variables.Variables.GetMoonCost(text) + "?\nType CONFIRM to confirm routing."); } else { Route(terminal); this.moon = null; } } } public void Route(Terminal terminal, bool confirmed = false) { if ((Object)(object)moon.level == (Object)(object)StartOfRound.Instance.currentLevel) { Command.ErrorResponse("You are already at that moon."); return; } if (!StartOfRound.Instance.inShipPhase) { Command.ErrorResponse("You are only able to route to a moon while in orbit."); return; } if (StartOfRound.Instance.travellingToNewLevel) { Command.ErrorResponse("You are already travelling elsewhere, please wait."); return; } if (terminal.useCreditsCooldown) { Command.ErrorResponse("You're on a credit usage cooldown."); return; } int moonCost = global::lammOS.Variables.Variables.GetMoonCost(moon.id); if (terminal.groupCredits < moonCost) { Command.ErrorResponse("You do not have enough credits to go to that moon."); return; } if (((NetworkBehaviour)terminal).IsHost) { StartOfRound.Instance.ChangeLevelServerRpc(moon.node.buyRerouteToMoon, terminal.groupCredits - moonCost); } else { terminal.groupCredits -= moonCost; StartOfRound.Instance.ChangeLevelServerRpc(moon.node.buyRerouteToMoon, terminal.groupCredits); } if (confirmed) { global::lammOS.NewTerminal.NewTerminal.AppendTerminalText("Routing autopilot to " + moon.styledName + "."); } else { global::lammOS.NewTerminal.NewTerminal.SetTerminalText("Routing autopilot to " + moon.styledName + "."); } } public override void Confirmed(Terminal terminal) { Route(terminal, confirmed: true); moon = null; } } public class StoreCommand : Command { public StoreCommand() { category = "Items"; base.id = "store"; description = "View the items available to buy."; AddShortcut("x", base.id); } public static string GeneratePurchasableItems() { List<List<string>> list = new List<List<string>> { new List<string>(), new List<string>(), new List<string>() }; foreach (global::lammOS.Variables.Variables.PurchasableItem value in global::lammOS.Variables.Variables.purchasableItems.Values) { list[0].Add((lammOS.ShowMinimumChars ? ("(" + value.shortestChars + ") ") : "") + value.item.itemName + " "); list[1].Add(global::lammOS.Variables.Variables.GetItemCost(value.item.itemName.ToLower(), includeSale: true).ToString()); list[2].Add((value.salePercentage == 100) ? null : (100 - value.salePercentage).ToString()); } return "Welcome to the Company store!\n" + global::lammOS.NewTerminal.NewTerminal.Terminal.numberOfItemsInDropship + "/" + global::lammOS.SyncedConfig.SyncedConfig.Instance.MaxDropshipItems + " items are in the dropship.\nUse the BUY command to buy any items listed here:\n" + Command.HandleListPadding(list, new List<string> { " * {ITEM}", " ${ITEM} ", "{ITEM}% OFF " }, new List<string> { "", "right", "right" }); } public static string GenerateUpgrades() { List<global::lammOS.Variables.Variables.PurchasableUnlockable> list = new List<global::lammOS.Variables.Variables.PurchasableUnlockable>(); foreach (global::lammOS.Variables.Variables.PurchasableUnlockable value in global::lammOS.Variables.Variables.purchasableUnlockables.Values) { if (value.unlockable.alwaysInStock && !value.unlockable.hasBeenUnlockedByPlayer && !value.unlockable.alreadyUnlocked) { list.Add(value); } } if (list.Count == 0) { return "\n\nShip Upgrades:\n+" + new string('-', "All ship upgrades have been purchased.".Length - 2) + "+\nAll ship upgrades have been purchased."; } List<List<string>> list2 = new List<List<string>> { new List<string>(), new List<string>() }; list.Sort((global::lammOS.Variables.Variables.PurchasableUnlockable x, global::lammOS.Variables.Variables.PurchasableUnlockable y) => global::lammOS.Variables.Variables.GetUnlockableCost(x.node.creatureName.ToLower()) - global::lammOS.Variables.Variables.GetUnlockableCost(y.node.creatureName.ToLower())); foreach (global::lammOS.Variables.Variables.PurchasableUnlockable item in list) { list2[0].Add((lammOS.ShowMinimumChars ? ("(" + item.shortestChars + ") ") : "") + item.node.creatureName + " "); list2[1].Add(global::lammOS.Variables.Variables.GetUnlockableCost(item.node.creatureName.ToLower()).ToString()); } return "\n\nShip Upgrades:\n" + Command.HandleListPadding(list2, new List<string> { " * {ITEM}", " ${ITEM} " }, new List<string> { "", "right" }); } public static string GenerateDecorSelection(Terminal terminal) { List<List<string>> list = new List<List<string>> { new List<string>(), new List<string>() }; foreach (TerminalNode item in terminal.ShipDecorSelection) { global::lammOS.Variables.Variables.PurchasableUnlockable purchasableUnlockable = global::lammOS.Variables.Variables.purchasableUnlockables[item.creatureName.ToLower()]; if (purchasableUnlockable != null && !purchasableUnlockable.unlockable.hasBeenUnlockedByPlayer && !purchasableUnlockable.unlockable.alreadyUnlocked) { list[0].Add((lammOS.ShowMinimumChars ? ("(" + purchasableUnlockable.shortestChars + ") ") : "") + purchasableUnlockable.node.creatureName + " "); list[1].Add(global::lammOS.Variables.Variables.GetUnlockableCost(purchasableUnlockable.node.creatureName.ToLower()).ToString()); } } if (list[0].Count == 0) { return "\n\nShip Decor:\n+" + new string('-', "No decor items available.".Length - 2) + "+\nNo decor items available."; } return "\n\nShip Decor:\n" + Command.HandleListPadding(list, new List<string> { " * {ITEM}", " ${ITEM} " }, new List<string> { "", "right" }); } public override void Execute(Terminal terminal, string input) { global::lammOS.NewTerminal.NewTerminal.SetTerminalText(GeneratePurchasableItems() + GenerateUpgrades() + GenerateDecorSelection(terminal)); } } public class Bu