Please disclose if your mod was created primarily 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 KroesTerminal v1.0.10
KroesTerminal.dll
Decompiled 3 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using KroesTerminal.Patches; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("KroesTerminal")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("KroesTerminal")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("37420e05-2d4b-4fcd-a09f-844ba6ff45aa")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace KroesTerminal { internal class ConfigControl { private ConfigEntry<bool> QuotaUICfg; private ConfigEntry<bool> QuotaNotifCfg; private ConfigEntry<bool> KScanCfg; private ConfigEntry<bool> KItemsCfg; private ConfigEntry<bool> KEnemyCfg; private ConfigEntry<bool> KEnemyPeacefulCfg; private ConfigEntry<bool> KPlayersCfg; private ConfigEntry<bool> InsideJokesCfg; internal bool enableQuotaUI { get { return QuotaUICfg.Value; } set { QuotaUICfg.Value = value; } } internal bool QuotaNotif { get { return QuotaNotifCfg.Value; } set { QuotaNotifCfg.Value = value; } } internal bool KScan { get { return KScanCfg.Value; } set { KScanCfg.Value = value; } } internal bool KItems { get { return KItemsCfg.Value; } set { KItemsCfg.Value = value; } } internal bool KEnemy { get { return KEnemyCfg.Value; } set { KEnemyCfg.Value = value; } } internal bool EnemyPeaceful { get { return KEnemyPeacefulCfg.Value; } set { KEnemyPeacefulCfg.Value = value; } } internal bool KPlayers { get { return KPlayersCfg.Value; } set { KPlayersCfg.Value = value; } } internal bool InsideJokes { get { return InsideJokesCfg.Value; } set { InsideJokesCfg.Value = value; } } public ConfigControl(ConfigFile config) { QuotaUICfg = config.Bind<bool>("Features", "Enable Quota UI", true, (ConfigDescription)null); QuotaNotifCfg = config.Bind<bool>("Features", "Enable Quota notification", true, (ConfigDescription)null); KScanCfg = config.Bind<bool>("Terminal Commands", "Allow KSCAN command", true, (ConfigDescription)null); KItemsCfg = config.Bind<bool>("Terminal Commands", "Allow KITEMS command", true, (ConfigDescription)null); KEnemyCfg = config.Bind<bool>("Terminal Commands", "Allow KENEMY command", true, (ConfigDescription)null); KEnemyPeacefulCfg = config.Bind<bool>("Terminal Commands", "List non-hostile enemies", true, (ConfigDescription)null); KPlayersCfg = config.Bind<bool>("Terminal Commands", "Allow KPLAYERS command", true, (ConfigDescription)null); InsideJokesCfg = config.Bind<bool>("Extra", "Enable Inside Jokes", false, "A part of the mod which enables inside jokes for my friends."); } } [BepInPlugin("com.kroes.kroesterminal", "KroesTerminal", "1.0.10")] public class KroesPlugin : BaseUnityPlugin { private const string GUID = "com.kroes.kroesterminal"; private const string NAME = "KroesTerminal"; private const string VERSION = "1.0.10"; internal static ManualLogSource Log; internal static ConfigControl Configuration; private Harmony harmony = new Harmony("com.kroes.kroesterminal"); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Configuration = new ConfigControl(((BaseUnityPlugin)this).Config); harmony.PatchAll(typeof(TerminalPatch)); if (Configuration.enableQuotaUI || Configuration.QuotaNotif) { harmony.PatchAll(typeof(HUDManagerPatch)); } if (Configuration.InsideJokes) { harmony.PatchAll(typeof(EnemyAIPatch)); } Log.LogInfo((object)"Loaded succesfully!"); } } internal class TextJumpAnimation : MonoBehaviour { private TextMeshProUGUI text; private float jumpTime; private const float jumpDuration = 0.2f; private const float jumpScale = 1.5f; private readonly Vector3 originalScale = new Vector3(1f, 1f, 1f); public void StartJump(TextMeshProUGUI target) { text = target; jumpTime = 0.2f; } private void Update() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)text == (Object)null) && jumpTime > 0f) { float num = 1f - jumpTime / 0.2f; float num2 = Mathf.Sin(num * (float)Math.PI) * 0.5f + 1f; ((TMP_Text)text).transform.localScale = originalScale * num2; jumpTime -= Time.deltaTime; if (jumpTime <= 0f) { ((TMP_Text)text).transform.localScale = originalScale; Object.Destroy((Object)(object)this); } } } } internal class Utilities { public static TextMeshProUGUI QuotaText; public static GameObject ship; public static bool reachedQuota = false; public static int totalShipLoot; internal static readonly HashSet<string> nonHostileEnemies = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "docile locust bees", "manticoil", "tulip snake" }; internal static TerminalNode CreateTerminalNode(string name) { TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); val.displayText = "[" + name + "]"; val.terminalEvent = ""; val.clearPreviousText = true; val.maxCharactersToType = 35; val.buyItemIndex = -1; val.buyVehicleIndex = -1; val.isConfirmationNode = false; val.buyRerouteToMoon = -1; val.displayPlanetInfo = -1; val.shipUnlockableID = -1; val.buyUnlockable = false; val.returnFromStorage = false; val.itemCost = 0; val.creatureFileID = -1; val.creatureName = ""; val.storyLogFileID = -1; val.overrideOptions = false; val.acceptAnything = false; val.terminalOptions = Array.Empty<CompatibleNoun>(); val.playSyncedClip = -1; val.loadImageSlowly = false; val.persistentImage = false; return val; } internal static void OnSubmitEnd(Terminal terminal) { terminal.screenText.ActivateInputField(); ((Selectable)terminal.screenText).Select(); } internal static bool ShouldListItem(GrabbableObject item) { if (!item.itemProperties.isScrap) { return false; } StunGrenadeItem val = (StunGrenadeItem)(object)((item is StunGrenadeItem) ? item : null); if (val != null) { return !val.hasExploded; } return true; } internal static string KScanDisplayText() { string text = ""; int num = 0; GrabbableObject[] source = Object.FindObjectsOfType<GrabbableObject>(); GrabbableObject[] array = (from obj in source where ShouldListItem(obj) && !obj.isInShipRoom && !obj.isInElevator orderby obj.itemProperties.itemName select obj).ToArray(); if (array.Length == 0) { return "\n\n\nNo objects were found.\n\n"; } GrabbableObject[] array2 = array; foreach (GrabbableObject val in array2) { text += $"\n* {val.itemProperties.itemName} // ${val.scrapValue}"; num += val.scrapValue; } return $"\n\n\nThere are {array.Length} objects outside the ship, totalling a value of ${num}.\n{text}\n\n"; } internal static string KItemsDisplayText() { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; int num8 = 0; GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>(); GrabbableObject[] array2 = array; foreach (GrabbableObject val in array2) { if (ShouldListItem(val)) { if (val.isInShipRoom) { num3++; num4 += val.scrapValue; } else if (val.isHeld) { num7++; num8 += val.scrapValue; } else if (val.isInElevator) { num5++; num6 += val.scrapValue; } else { num++; num2 += val.scrapValue; } } } return $"\n\n\n[Items on moon] {num} : ${num2}\n[Items in ship] {num3} : ${num4}\n[Items being held] {num7} : ${num8}\n[Items on elevator/ship edge] {num5} : ${num6}\n\n"; } private static bool ShouldListEnemy(EnemyAI enemy) { if (enemy.isEnemyDead) { return false; } if (!KroesPlugin.Configuration.EnemyPeaceful && nonHostileEnemies.Contains(enemy.enemyType.enemyName)) { return false; } return true; } internal static string KEnemyDisplayText() { string text = ""; string text2 = ""; EnemyAI[] source = Object.FindObjectsOfType<EnemyAI>(); EnemyAI[] array = (from enemy in source where !enemy.isOutside && ShouldListEnemy(enemy) orderby enemy.enemyType.enemyName select enemy).ToArray(); EnemyAI[] array2 = (from enemy in source where enemy.isOutside && ShouldListEnemy(enemy) orderby enemy.enemyType.enemyName select enemy).ToArray(); if (array.Length == 0 && array2.Length == 0) { return "\n\n\nNo enemies were found.\n\n"; } EnemyAI[] array3 = array; foreach (EnemyAI val in array3) { string text3 = "???"; DressGirlAI val2 = (DressGirlAI)(object)((val is DressGirlAI) ? val : null); text3 = ((val2 == null) ? val.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>()?.headerText : ((Object)val2).name); text += $"\n* {text3} : {val.enemyHP}HP"; } EnemyAI[] array4 = array2; foreach (EnemyAI val3 in array4) { string text4 = "???"; DressGirlAI val4 = (DressGirlAI)(object)((val3 is DressGirlAI) ? val3 : null); text4 = ((val4 == null) ? val3.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>()?.headerText : ((Object)val4).name); text2 += $"\n* {text4} : {val3.enemyHP}HP"; } int num = array.Length + array2.Length; string text5 = $"\n\n\nThere are {num} enemies out there.\n"; if (array.Length != 0) { text5 = text5 + "\n[Inside]" + text + "\n"; } if (array2.Length != 0) { text5 = text5 + "\n[Outside]" + text2 + "\n"; } return text5 + "\n"; } internal static int calculateShipLootTotal() { List<GrabbableObject> source = (from obj in ship.GetComponentsInChildren<GrabbableObject>() where obj.itemProperties.isScrap && !(obj is RagdollGrabbableObject) select obj).ToList(); return source.Sum((GrabbableObject scrap) => scrap.scrapValue); } public static void TriggerJump() { TextMeshProUGUI quotaText = QuotaText; if (!((Object)(object)quotaText == (Object)null)) { TextJumpAnimation textJumpAnimation = ((Component)quotaText).gameObject.AddComponent<TextJumpAnimation>(); textJumpAnimation.StartJump(quotaText); } } internal static string ConfigPermissionDisplayText(string command) { return "\n\n\n[" + command + "] is disabled in the mod config file.\n\n"; } internal static string KroesDisplayText() { string text = "\n\n\nThanks for using KroesTerminal!\n\n"; if (KroesPlugin.Configuration.KScan) { text += ">KSCAN\nTo see a detailed scan of all scrap.\n\n"; } if (KroesPlugin.Configuration.KItems) { text += ">KITEMS\nTo see a count of all scrap.\n\n"; } if (KroesPlugin.Configuration.KEnemy) { text += ">KENEMY\nTo see a scan of all enemies.\n\n"; } if (KroesPlugin.Configuration.KPlayers) { text += ">KPLAYERS\nTo see a list of all player items.\n\n"; } return text; } internal static string PlayersDisplayText() { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; PlayerControllerB[] array = allPlayerScripts.Where((PlayerControllerB player) => player.isPlayerControlled && !player.isPlayerDead).ToArray(); int num = array.Length; string text = $"\n\n\nThere are {num} players alive:\n"; PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { text = text + "\n[" + val.playerUsername + "]\n"; GrabbableObject[] itemSlots = val.ItemSlots; GrabbableObject[] array3 = itemSlots; foreach (GrabbableObject val2 in array3) { if ((Object)(object)val2 != (Object)null) { text = text + "- " + val2.itemProperties.itemName + "\n"; } } } return text + "\n"; } } } namespace KroesTerminal.Patches { [HarmonyPatch(typeof(EnemyAI))] internal class EnemyAIPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void Postfix(EnemyAI __instance) { ScanNodeProperties componentInChildren = __instance.enemyType.enemyPrefab.GetComponentInChildren<ScanNodeProperties>(); if (__instance is FlowermanAI) { componentInChildren.headerText = "Mammoet Mevrouw"; } if (__instance is ClaySurgeonAI) { componentInChildren.headerText = "Fes de Barber"; } } } [HarmonyPatch(typeof(HUDManager))] internal class HUDManagerPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePostfix(HUDManager __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) if (KroesPlugin.Configuration.enableQuotaUI) { GameObject val = new GameObject("myHotbarUI"); val.transform.SetParent(__instance.HUDContainer.transform, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = new Vector2(0f, 1f); val2.anchorMax = new Vector2(0f, 1f); val2.pivot = new Vector2(0f, 1f); val2.anchoredPosition = new Vector2(60f, -10f); GameObject val3 = new GameObject("QuotaText"); val3.transform.SetParent(val.transform, false); TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>(); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(50f, 20f); component.sizeDelta = new Vector2(300f, 50f); ((TMP_Text)val4).font = ((TMP_Text)__instance.controlTipLines[0]).font; ((TMP_Text)val4).fontSize = 20f; ((TMP_Text)val4).fontStyle = (FontStyles)1; ((TMP_Text)val4).text = "-placeholder-"; ((Graphic)val4).color = Color.white; ((TMP_Text)val4).alignment = (TextAlignmentOptions)513; ((TMP_Text)val4).enableWordWrapping = true; ((TMP_Text)val4).overflowMode = (TextOverflowModes)0; Utilities.QuotaText = val4; } Utilities.ship = GameObject.Find("/Environment/HangarShip"); } [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(HUDManager __instance) { int num = Utilities.calculateShipLootTotal(); int profitQuota = TimeOfDay.Instance.profitQuota; if (KroesPlugin.Configuration.enableQuotaUI) { if (num != Utilities.totalShipLoot) { Utilities.totalShipLoot = num; Utilities.TriggerJump(); } ((TMP_Text)Utilities.QuotaText).text = $"[QUOTA] {Utilities.totalShipLoot} : {profitQuota}"; } if (KroesPlugin.Configuration.QuotaNotif) { if (!Utilities.reachedQuota && num >= profitQuota) { Utilities.reachedQuota = true; KroesPlugin.Log.LogInfo((object)"sending quota notif..."); __instance.globalNotificationAnimator.SetTrigger("TriggerNotif"); ((TMP_Text)__instance.globalNotificationText).text = "Quota has been reached!"; __instance.UIAudio.PlayOneShot(__instance.globalNotificationSFX); } else if (Utilities.reachedQuota && num < profitQuota) { Utilities.reachedQuota = false; } } } } [HarmonyPatch(typeof(Terminal))] internal class TerminalPatch { [HarmonyPatch("OnSubmit")] [HarmonyPrefix] private static bool OnSubmitPrefix(Terminal __instance) { string text = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded); switch (text.ToLower()) { case "kscan": { KroesPlugin.Log.LogInfo((object)"Custom Command: kscan"); TerminalNode val5 = Utilities.CreateTerminalNode("kscan"); __instance.LoadNewNode(val5); return false; } case "kitems": { KroesPlugin.Log.LogInfo((object)"Custom Command: kitems"); TerminalNode val4 = Utilities.CreateTerminalNode("kitems"); __instance.LoadNewNode(val4); return false; } case "kenemy": { KroesPlugin.Log.LogInfo((object)"Custom Command: kenemy"); TerminalNode val3 = Utilities.CreateTerminalNode("kenemy"); __instance.LoadNewNode(val3); return false; } case "kroes": { KroesPlugin.Log.LogInfo((object)"Custom Command: kroes"); TerminalNode val2 = Utilities.CreateTerminalNode("kroes"); __instance.LoadNewNode(val2); return false; } case "kplayers": { KroesPlugin.Log.LogInfo((object)"Custom Command: kplayers"); TerminalNode val = Utilities.CreateTerminalNode("kplayers"); __instance.LoadNewNode(val); return false; } default: return true; } } [HarmonyPatch("TextPostProcess")] [HarmonyPrefix] private static bool TextPostProcessPrefix(ref string modifiedDisplayText, TerminalNode node, ref string __result, Terminal __instance) { string text = modifiedDisplayText.Trim(); if (text.Contains("[kscan]")) { if (!KroesPlugin.Configuration.KScan) { KroesPlugin.Log.LogInfo((object)"[kscan] not permitted."); __result = Utilities.ConfigPermissionDisplayText("kscan"); Utilities.OnSubmitEnd(__instance); return false; } KroesPlugin.Log.LogInfo((object)"Processing [kscan]..."); __result = Utilities.KScanDisplayText(); Utilities.OnSubmitEnd(__instance); return false; } if (text.Contains("[kitems]")) { if (!KroesPlugin.Configuration.KItems) { KroesPlugin.Log.LogInfo((object)"[kitems] not permitted."); __result = Utilities.ConfigPermissionDisplayText("kitems"); Utilities.OnSubmitEnd(__instance); return false; } KroesPlugin.Log.LogInfo((object)"Processing [kitems]..."); __result = Utilities.KItemsDisplayText(); Utilities.OnSubmitEnd(__instance); return false; } if (text.Contains("[kenemy]")) { if (!KroesPlugin.Configuration.KEnemy) { KroesPlugin.Log.LogInfo((object)"[kenemy] not permitted."); __result = Utilities.ConfigPermissionDisplayText("kenemy"); Utilities.OnSubmitEnd(__instance); return false; } KroesPlugin.Log.LogInfo((object)"Processing [kenemy]..."); __result = Utilities.KEnemyDisplayText(); Utilities.OnSubmitEnd(__instance); return false; } if (text.Contains("[kroes]")) { KroesPlugin.Log.LogInfo((object)"Processing [kroes]..."); __result = Utilities.KroesDisplayText(); Utilities.OnSubmitEnd(__instance); return false; } if (text.Contains("[kplayers]")) { if (!KroesPlugin.Configuration.KPlayers) { KroesPlugin.Log.LogInfo((object)"[kplayers] not permitted."); __result = Utilities.ConfigPermissionDisplayText("kplayers"); Utilities.OnSubmitEnd(__instance); return false; } KroesPlugin.Log.LogInfo((object)"Processing [kplayers]..."); __result = Utilities.PlayersDisplayText(); Utilities.OnSubmitEnd(__instance); return false; } return true; } } }