Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PowerTerminalOS v1.0.0
BepInEx\plugins\PowerTerminalOS\PowerTerminalOS.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PowerTerminalOS")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PowerTerminalOS")] [assembly: AssemblyTitle("PowerTerminalOS")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PowerTerminalOS { [BepInPlugin("anton.powerterminalos", "PowerTerminalOS", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "anton.powerterminalos"; public const string Name = "PowerTerminalOS"; public const string Version = "1.0.0"; internal static Plugin Instance; private Harmony harmony; private ConfigEntry<string> accent; private ConfigEntry<bool> hostOnly; internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger; private void Awake() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown Instance = this; accent = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "AccentColor", "00D7FF", "Terminal accent color as an RGB hex value."); hostOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Security", "HostOnlyControlCommands", true, "Only the host may run commands that alter the world."); harmony = new Harmony("anton.powerterminalos"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"PowerTerminalOS 1.0.0 loaded. Type pwsh or ps-help in the terminal."); } internal void Style(Terminal terminal) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) try { Color val = default(Color); if (!ColorUtility.TryParseHtmlString("#" + accent.Value.TrimStart('#'), ref val)) { ((Color)(ref val))..ctor(0f, 0.84f, 1f); } terminal.screenText.textComponent.color = val; terminal.screenText.textComponent.fontStyle = (FontStyles)0; terminal.screenText.caretColor = Color.white; terminal.screenText.selectionColor = new Color(val.r, val.g, val.b, 0.35f); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)ex); } } internal bool TryExecute(Terminal terminal, string raw, out TerminalNode node) { node = null; string text = Normalize(raw); if (text.Length == 0) { return false; } string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string text2 = array[0].ToLowerInvariant(); string[] args = array.Skip(1).ToArray(); if (new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "pwsh", "ps-help" }, { "help-ps", "ps-help" }, { "status", "get-shipstatus" }, { "moon", "get-moon" }, { "crew", "get-crew" }, { "scan", "scan-map" }, { "lights", "set-lights" }, { "turrets", "set-turrets" }, { "doors", "set-doors" }, { "teleport", "invoke-teleporter" }, { "launch", "start-ship" }, { "clear", "clear-host" } }.TryGetValue(text2, out var value)) { text2 = value; } bool clearPreviousText = false; string text3; switch (text2) { case "ps-help": text3 = Help(); break; case "get-shipstatus": text3 = ShipStatus(); break; case "get-moon": text3 = MoonStatus(); break; case "get-crew": text3 = CrewStatus(); break; case "scan-map": text3 = MapScan(); break; case "get-weather": text3 = MoonStatus(); break; case "get-scrap": text3 = ScrapScan(); break; case "set-lights": text3 = Control(args, "lights"); break; case "set-turrets": text3 = Control(args, "turrets"); break; case "set-doors": text3 = Control(args, "doors"); break; case "invoke-teleporter": text3 = Control(args, "teleporter"); break; case "start-ship": text3 = Control(args, "ship"); break; case "clear-host": text3 = Banner("SESSION CLEARED"); clearPreviousText = true; break; default: return false; } node = ScriptableObject.CreateInstance<TerminalNode>(); node.clearPreviousText = clearPreviousText; node.acceptAnything = false; node.displayText = text3 + "\n\nPS LC:\\Ship> "; node.maxCharactersToType = 16000; return true; } private string Control(string[] args, string system) { if (hostOnly.Value && (Object)(object)NetworkManager.Singleton != (Object)null && !NetworkManager.Singleton.IsHost) { return Error("ACCESS DENIED", "Control commands are host-only."); } string text = ((args.Length == 0) ? "toggle" : args[0].ToLowerInvariant()); try { switch (system) { case "lights": { object obj = AccessTools.Field(typeof(StartOfRound), "shipRoomLights")?.GetValue(StartOfRound.Instance); if (obj == null) { return Error("NOT AVAILABLE", "Ship light controller was not found."); } bool flag3 = text == "on" || (text == "toggle" && !ReadBool(obj, "areLightsOn", "lightsOn")); bool flag4 = InvokeBest(obj, new string[2] { "SetShipLightsBoolean", "SetShipLights" }, flag3); if (!flag4) { flag4 = InvokeBest(obj, (!flag3) ? new string[2] { "SetShipLightsOff", "TurnOffLights" } : new string[2] { "SetShipLightsOn", "TurnOnLights" }); } if (!flag4) { InvokeBest(obj, new string[1] { "ToggleShipLights" }); } return Success("SHIP LIGHTS", flag3 ? "ONLINE" : "OFFLINE"); } case "turrets": { bool flag = text == "on" || text == "enable"; int num = 0; foreach (Object item in FindByTypeName("Turret")) { SetMember(item, flag, "turretActive", "turretEnabled"); InvokeBest(item, new string[2] { "ToggleTurretEnabled", "SetTurretMode" }, flag); num++; } return Success("TURRET NETWORK", string.Format("{0} turret(s) {1}", num, flag ? "ENABLED" : "DISABLED")); } case "doors": { bool flag2 = text == "open" || text == "on"; int num2 = 0; foreach (Object item2 in FindByTypeName("TerminalAccessibleObject")) { if (item2.name.ToLowerInvariant().Contains("door")) { if (!InvokeBest(item2, new string[2] { "SetDoorOpen", "SetDoorOpenServerRpc" }, flag2) && ReadBool(item2, "isDoorOpen") != flag2) { InvokeBest(item2, new string[1] { "CallFunctionFromTerminal" }); } num2++; } } return Success("FACILITY DOORS", string.Format("{0} door(s) commanded {1}", num2, flag2 ? "OPEN" : "CLOSED")); } case "teleporter": { Object val = FindByTypeName("ShipTeleporter").FirstOrDefault(); if (val == (Object)null) { return Error("NOT INSTALLED", "No ship teleporter was found."); } InvokeBest(val, new string[2] { "PressTeleportButtonOnLocalClient", "beamUpPlayer" }); return Success("TELEPORTER", "Beam sequence requested"); } case "ship": if ((Object)(object)StartOfRound.Instance == (Object)null) { return Error("NOT READY", "Round controller was not found."); } InvokeBest(StartOfRound.Instance, new string[2] { "EndGameServerRpc", "StartGameServerRpc" }); return Success("AUTOPILOT", "Ship sequence requested"); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); return Error("COMMAND FAILED", ex.GetType().Name); } return Error("INVALID ACTION", "Use on/off, enable/disable, or open/close."); } private string ShipStatus() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return Error("OFFLINE", "No active ship controller."); } bool flag = ReadBool(instance, "shipHasLanded"); bool flag2 = ReadBool(instance, "inShipPhase"); return Panel("SHIP STATUS", new string[5] { Row("State", flag ? "LANDED" : (flag2 ? "IN ORBIT" : "IN TRANSIT")), Row("Crew", ActivePlayers().Count.ToString()), Row("Host", IsHost() ? "LOCAL" : "REMOTE"), Row("Moon", CurrentMoon()), Row("Time", TimeText()) }); } private string MoonStatus() { string value = GetMember(((Object)(object)StartOfRound.Instance == (Object)null) ? null : GetMember(StartOfRound.Instance, "currentLevel"), "currentWeather")?.ToString() ?? "Unknown"; return Panel("MOON TELEMETRY", new string[5] { Row("Moon", CurrentMoon()), Row("Weather", value), Row("Time", TimeText()), Row("Enemies", FindByBaseType("EnemyAI").Count.ToString()), Row("Scrap", ScrapObjects().Count.ToString()) }); } private string CrewStatus() { List<string> list = new List<string>(); foreach (object item in ActivePlayers()) { string key = GetMember(item, "playerUsername")?.ToString() ?? "Unknown"; bool flag = ReadBool(item, "isPlayerDead"); bool flag2 = ReadBool(item, "isInsideFactory"); list.Add(Row(key, flag ? "DECEASED" : (flag2 ? "FACILITY" : "SURFACE/SHIP"))); } return Panel("CREW MANIFEST", list); } private string MapScan() { return Panel("LOCAL SENSOR ARRAY", new string[5] { Row("Hostiles", FindByBaseType("EnemyAI").Count.ToString()), Row("Turrets", FindByTypeName("Turret").Count.ToString()), Row("Landmines", FindByTypeName("Landmine").Count.ToString()), Row("Powered doors", FindByTypeName("TerminalAccessibleObject").Count.ToString()), Row("Scrap objects", ScrapObjects().Count.ToString()) }); } private string ScrapScan() { return Panel("SCRAP MANIFEST", new string[2] { Row("Detected", ScrapObjects().Count.ToString()), Row("Scanner", "LOCAL RANGE") }); } private static string Help() { return Banner("POWERSHELL SHIP OS 1.0") + "\n INFORMATION\n Get-ShipStatus Ship, crew, moon and time\n Get-Moon Weather and moon telemetry\n Get-Crew Player status and location\n Scan-Map Enemies, hazards and scrap\n Get-Scrap Local scrap scan\n\n CONTROL (HOST)\n Set-Lights on|off|toggle\n Set-Turrets enable|disable\n Set-Doors open|close\n Invoke-Teleporter\n Start-Ship\n\n Aliases: status, moon, crew, scan, lights,\n turrets, doors, teleport, launch, clear"; } private static string Normalize(string value) { value = value.Replace("\r", "").Trim(); int num = value.LastIndexOf('>'); if (num >= 0) { value = value.Substring(num + 1).Trim(); } return value; } private static string CurrentMoon() { object target = (((Object)(object)StartOfRound.Instance == (Object)null) ? null : GetMember(StartOfRound.Instance, "currentLevel")); return GetMember(target, "PlanetName")?.ToString() ?? GetMember(target, "name")?.ToString() ?? "Unknown"; } private static string TimeText() { if (!(GetMember(Type.GetType("TimeOfDay, Assembly-CSharp")?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null), "normalizedTimeOfDay") is float num)) { return "Unknown"; } return $"{(int)(6f + num * 12f):00}:{(int)(num * 12f % 1f * 60f):00}"; } private static List<object> ActivePlayers() { if (!(GetMember(StartOfRound.Instance, "allPlayerScripts") is IEnumerable source)) { return new List<object>(); } return (from object p in source where p != null && ReadBool(p, "isPlayerControlled") select p).ToList(); } private static List<Object> ScrapObjects() { return (from o in FindByBaseType("GrabbableObject") where ReadBool(o, "itemProperties.isScrap", "isScrap") select o).ToList(); } private static List<Object> FindByTypeName(string name) { Type type = Type.GetType(name + ", Assembly-CSharp"); if (!(type == null)) { return Object.FindObjectsOfType(type).Cast<Object>().ToList(); } return new List<Object>(); } private static List<Object> FindByBaseType(string name) { return FindByTypeName(name); } private static bool IsHost() { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { return NetworkManager.Singleton.IsHost; } return true; } private static object? GetMember(object? target, string name) { if (target == null) { return null; } Type type = target.GetType(); object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target); if (obj == null) { PropertyInfo? property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property == null) { return null; } obj = property.GetValue(target); } return obj; } private static bool ReadBool(object? target, params string[] names) { foreach (string text in names) { object obj = (text.Contains(".") ? text.Split('.').Aggregate(target, GetMember) : GetMember(target, text)); if (obj is bool) { return (bool)obj; } } return false; } private static void SetMember(object target, object value, params string[] names) { foreach (string name in names) { FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType.IsInstanceOfType(value)) { field.SetValue(target, value); break; } } } private static bool InvokeBest(object target, string[] names, params object[] args) { foreach (string name in names) { MethodInfo methodInfo = target.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == name && m.GetParameters().Length == args.Length); if (!(methodInfo == null)) { try { methodInfo.Invoke(target, args); return true; } catch { } } } return false; } private static string Banner(string title) { return "\n+------------------------------------------------+\n| " + title.PadRight(44).Substring(0, 44) + " |\n+------------------------------------------------+"; } private static string Panel(string title, IEnumerable<string> rows) { return Banner(title) + "\n" + string.Join("\n", rows); } private static string Row(string key, string value) { return " " + key.PadRight(18) + " " + value; } private static string Success(string title, string text) { return Panel(title, new string[2] { Row("Result", text), Row("Status", "OK") }); } private static string Error(string title, string text) { return Panel(title, new string[2] { Row("Error", text), Row("Status", "FAILED") }); } } [HarmonyPatch(typeof(Terminal), "BeginUsingTerminal")] internal static class BeginUsingTerminalPatch { private static void Postfix(Terminal __instance) { Plugin.Instance.Style(__instance); } } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] internal static class ParsePlayerSentencePatch { private static void Postfix(Terminal __instance, ref TerminalNode __result) { try { int textAdded = __instance.textAdded; string text = __instance.screenText.text; string raw = ((textAdded > 0 && textAdded <= text.Length) ? text.Substring(text.Length - textAdded) : text); if (Plugin.Instance.TryExecute(__instance, raw, out TerminalNode node)) { __result = node; } } catch (Exception ex) { Plugin.Instance.Log.LogError((object)ex); } } } }