using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SubTerminalEX.Features;
using SubTerminalEX.Patches;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SubTerminalEX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+422894232f07cd9dce1715bc8dd658395520a2fc")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("SubTerminalEX")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.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]
[Microsoft.CodeAnalysis.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]
[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 SubTerminalEX
{
internal static class PLog
{
private static ManualLogSource? _log;
private static bool _init;
public static void InitLog(ManualLogSource logSource)
{
if (!_init)
{
_log = logSource;
_init = true;
}
}
public static void Inf(string msg)
{
ManualLogSource? log = _log;
if (log != null)
{
log.LogInfo((object)msg);
}
}
public static void Err(string msg)
{
ManualLogSource? log = _log;
if (log != null)
{
log.LogError((object)msg);
}
}
public static void Dbg(string msg)
{
if (Plugin.pluginInstance.DebugMode)
{
ManualLogSource? log = _log;
if (log != null)
{
log.LogInfo((object)msg);
}
}
}
public static void Wrn(string msg)
{
ManualLogSource? log = _log;
if (log != null)
{
log.LogWarning((object)msg);
}
}
}
[BepInPlugin("com.ozzzzy.subterex", "SubTerminalEX", "1.1.0")]
internal sealed class Plugin : BaseUnityPlugin
{
internal static Harmony? _harmony;
internal static Plugin pluginInstance;
internal static bool GameStarted;
internal bool DebugMode;
internal bool FastTerminalBoot;
internal bool EnableAutoload;
internal string AutoloadTargetFile = string.Empty;
internal int ticks;
internal const string ConfigAliasSection = "Alias Settings";
internal const string ConfigTerminalSection = "Terminal Settings";
internal static MonoBehaviour Interpreter => (MonoBehaviour)(object)TerminalManager.instance.interpreter;
private void Awake()
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
pluginInstance = this;
if (_harmony != null)
{
_harmony.UnpatchSelf();
_harmony = null;
}
SetupConfig();
CacheConfig();
PLog.InitLog(((BaseUnityPlugin)this).Logger);
PLog.Inf("Loaded successfully - version: 1.1.0");
_harmony = new Harmony("com.ozzzzy.subterex");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
Startup();
}
private void OnDestroy()
{
if (_harmony != null)
{
PLog.Wrn("SubTerminalEX is destroyed!, terminating all feature and patches...");
_harmony.UnpatchSelf();
_harmony = null;
}
}
private void FixedUpdate()
{
if (GameStarted)
{
if (ticks < 10)
{
ticks++;
return;
}
ticks = 0;
TerminalCommandManager.Update();
}
}
private void Startup()
{
ExtraTerminalCommand.Register();
}
internal void OnGameStartup()
{
TerminalCommandManager.UpdateToGame();
GameStarted = true;
if (EnableAutoload)
{
string text = Path.Combine(Environment.CurrentDirectory, AutoloadTargetFile.ToUpper() + ".txt");
long length = new FileInfo(text).Length;
if (length <= 1073741824 && File.Exists(text))
{
ExtraTerminalCommand._palias_path = text;
ExtraTerminalCommand._palias_size = (int)length;
((MonoBehaviour)this).StartCoroutine(ExtraTerminalCommand.ProcessAliasFile());
}
}
}
internal static T GetValueFromConfigEntry<T>(ConfigEntryBase entry)
{
if (entry.BoxedValue == null)
{
return (T)entry.DefaultValue;
}
return (T)entry.BoxedValue;
}
internal void CacheConfig()
{
DebugMode = GetValueFromConfigEntry<bool>(((BaseUnityPlugin)this).Config["Debug", "Debug Mode"]);
FastTerminalBoot = GetValueFromConfigEntry<bool>(((BaseUnityPlugin)this).Config["Terminal Settings", "Skip Bootup Text"]);
EnableAutoload = GetValueFromConfigEntry<bool>(((BaseUnityPlugin)this).Config["Alias Settings", "Enable Autoload"]);
AutoloadTargetFile = GetValueFromConfigEntry<string>(((BaseUnityPlugin)this).Config["Alias Settings", "Autoload File"]);
}
internal void SetupConfig()
{
((BaseUnityPlugin)this).Config.Bind<bool>("Alias Settings", "Enable Autoload", false, "Allow this mod to automatically load your alias definition upon game start");
((BaseUnityPlugin)this).Config.Bind<string>("Alias Settings", "Autoload File", "aliasAutoLoad", "The target file name to load from");
((BaseUnityPlugin)this).Config.Bind<bool>("Terminal Settings", "Skip Bootup Text", true, "Skip terminal bootup text");
((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Debug Mode", false, "Turn on debug mode for mods developer");
((BaseUnityPlugin)this).Config.Save();
}
}
public static class Shared
{
public static int LevDist(string s1, string s2)
{
int[,] array = new int[s1.Length + 1, s2.Length + 1];
for (int i = 0; i <= s1.Length; i++)
{
array[i, 0] = i;
}
for (int j = 0; j <= s2.Length; j++)
{
array[0, j] = j;
}
for (int k = 1; k <= s1.Length; k++)
{
for (int l = 1; l <= s2.Length; l++)
{
int num = ((s1[k - 1] != s2[l - 1]) ? 1 : 0);
array[k, l] = Mathf.Min(Mathf.Min(array[k - 1, l] + 1, array[k, l - 1] + 1), array[k - 1, l - 1] + num);
}
}
return array[s1.Length, s2.Length];
}
public static string? GetClosestCommand(string inputCommand)
{
string inputCommand2 = inputCommand;
int num = int.MaxValue;
string result = null;
foreach (var item3 in from <>h__TransparentIdentifier0 in Enumerable.Select(TerminalCommandManager._cdict, delegate(KeyValuePair<string, TerminalCommandEX> pair)
{
string s = inputCommand2;
KeyValuePair<string, TerminalCommandEX> keyValuePair = pair;
return new
{
pair = pair,
num2 = LevDist(s, keyValuePair.Key)
};
})
where <>h__TransparentIdentifier0.num2 < num
select (<>h__TransparentIdentifier0.pair, <>h__TransparentIdentifier0.num2))
{
KeyValuePair<string, TerminalCommandEX> item = item3.Item1;
int item2 = item3.Item2;
num = item2;
result = item.Key;
}
return result;
}
}
public struct STEHookData
{
public Action<List<string>> Func { get; set; }
public STEHookTarget Target { get; internal set; }
public STEHookPriority Priority { get; internal set; }
public string TargetCommand { get; internal set; }
internal STEHookData(Action<List<string>> func, string command, STEHookTarget target, STEHookPriority prio)
{
Func = func;
Target = target;
Priority = prio;
TargetCommand = command;
}
}
public enum STEHookPriority
{
Last = 0,
ExtremelyLow = 100,
VeryLow = 250,
Low = 400,
Default = 500,
High = 600,
VeryHigh = 750,
ExtremelyHigh = 900,
First = 1000
}
public enum STEHookTarget
{
Before = 0,
After = 1,
Default = 1
}
internal static class SubterexInfo
{
internal const string PLUG_GUID = "com.ozzzzy.subterex";
internal const string PLUG_NAME = "SubTerminalEX";
internal const string PLUG_VER = "1.1.0";
}
public class TerminalCommandEX : ScriptableObject
{
public string Command = string.Empty;
internal string? _alias_original = string.Empty;
public int NumArgs;
public string Description = string.Empty;
public string ParameterDescription = string.Empty;
public string Example = string.Empty;
public string[] ArgTips = Array.Empty<string>();
internal string actionMethodName = string.Empty;
public Func<List<string>, IEnumerator>? ActionMethod;
public Action<string, List<string>, STEHookTarget>? HookMethod;
public bool ArgsOptional = true;
public bool Hidden;
public bool ForceExactArgument = true;
internal bool CheckArgs(List<string> args)
{
if (ForceExactArgument)
{
return args.Count - 1 == NumArgs;
}
return args.Count - 1 >= NumArgs;
}
internal TerminalCommandEX()
{
}
internal static TerminalCommandEX Create()
{
return ScriptableObject.CreateInstance<TerminalCommandEX>();
}
public static implicit operator TerminalCommandEX(TerminalCommand cmd)
{
TerminalCommandEX terminalCommandEX = Create();
terminalCommandEX.Command = cmd.command;
terminalCommandEX.NumArgs = cmd.numArgs;
terminalCommandEX.Description = cmd.description;
terminalCommandEX.ParameterDescription = cmd.parameterDescription;
terminalCommandEX.Example = cmd.example;
terminalCommandEX.ArgTips = cmd.argTips;
terminalCommandEX.actionMethodName = cmd.actionMethod;
terminalCommandEX.ArgsOptional = cmd.argsOptional;
terminalCommandEX.Hidden = cmd.hidden;
return terminalCommandEX;
}
public static implicit operator TerminalCommand(TerminalCommandEX tex)
{
TerminalCommand obj = ScriptableObject.CreateInstance<TerminalCommand>();
obj.command = tex.Command;
obj.numArgs = tex.NumArgs;
obj.description = tex.Description;
obj.parameterDescription = tex.ParameterDescription;
obj.example = tex.Example;
obj.argTips = tex.ArgTips;
obj.actionMethod = tex.actionMethodName;
obj.argsOptional = tex.ArgsOptional;
obj.hidden = tex.Hidden;
return obj;
}
}
public static class TerminalCommandManager
{
internal static readonly Dictionary<string, TerminalCommandEX> _cdict = new Dictionary<string, TerminalCommandEX>();
internal static readonly List<TerminalCommandEX> _clist = new List<TerminalCommandEX>();
internal static readonly List<TerminalCommandEX> _cextra = new List<TerminalCommandEX>();
internal static readonly Dictionary<string, LinkedList<STEHookData>[]> _chook = new Dictionary<string, LinkedList<STEHookData>[]>();
internal static bool _lastModified = false;
internal static void Update(bool force = false)
{
if (_lastModified || force)
{
UpdateToGame();
}
}
internal static void CacheVanillaCommand(TerminalCommand[] list)
{
foreach (TerminalCommand val in list)
{
if (!_cdict.ContainsKey(val.command))
{
_cdict.Add(val.command, val);
_clist.Add(val);
}
}
}
public static bool RemoveCommand(string command)
{
if (_cdict.ContainsKey(command))
{
TerminalCommandEX terminalCommandEX = _cdict[command];
_cdict.Remove(command);
_clist.Remove(terminalCommandEX);
_cextra.Remove(terminalCommandEX);
Object.Destroy((Object)(object)terminalCommandEX);
return true;
}
return false;
}
internal static void UpdateToGame()
{
TerminalCommand[] commands = TerminalManager.instance.commands;
CacheVanillaCommand(commands);
int num = commands.Length;
int num2 = _clist.Count + _cextra.Count;
if (num2 == num)
{
_lastModified = false;
return;
}
TerminalCommand[] array = (TerminalCommand[])(object)new TerminalCommand[num2];
int count = _clist.Count;
int count2 = _cextra.Count;
for (int i = 0; i < count; i++)
{
array[i] = _clist[i];
}
for (int j = 0; j < count2; j++)
{
array[j + count] = _cextra[j];
}
_lastModified = false;
TerminalManager.instance.commands = array;
}
public static bool AddNoArgumentCommand(string command, Func<List<string>, IEnumerator> onInvoke, string name = "", string description = "", string example = "", bool hidden = false)
{
command = command.ToUpper();
if (_cdict.ContainsKey(command))
{
return false;
}
TerminalCommandEX terminalCommandEX = TerminalCommandEX.Create();
terminalCommandEX.Hidden = hidden;
((Object)terminalCommandEX).name = name;
terminalCommandEX.Description = description;
terminalCommandEX.Command = command;
terminalCommandEX.ActionMethod = onInvoke;
terminalCommandEX.Example = example;
terminalCommandEX.actionMethodName = "";
terminalCommandEX.ForceExactArgument = false;
terminalCommandEX.ArgsOptional = true;
terminalCommandEX.NumArgs = 0;
terminalCommandEX.ParameterDescription = string.Empty;
terminalCommandEX.ArgTips = Array.Empty<string>();
_cdict.Add(command, terminalCommandEX);
_cextra.Add(terminalCommandEX);
_lastModified = true;
return true;
}
public static bool AddCommand(string command, Func<List<string>, IEnumerator> onInvoke, string name = "", string description = "", int argAmount = 0, bool forceExactArgumentCount = false, bool argOptional = true, string parameterDesc = "", string[]? argumentTips = null, string example = "", bool hidden = false)
{
command = command.ToUpper();
if (_cdict.ContainsKey(command))
{
return false;
}
TerminalCommandEX terminalCommandEX = TerminalCommandEX.Create();
terminalCommandEX.Hidden = hidden;
((Object)terminalCommandEX).name = name;
terminalCommandEX.Description = description;
terminalCommandEX.Command = command;
terminalCommandEX.NumArgs = argAmount;
terminalCommandEX.ParameterDescription = parameterDesc;
terminalCommandEX.ActionMethod = onInvoke;
terminalCommandEX.actionMethodName = "";
terminalCommandEX.ArgsOptional = argOptional;
terminalCommandEX.ArgTips = argumentTips ?? new string[1] { "" };
terminalCommandEX.Example = example;
terminalCommandEX.ForceExactArgument = forceExactArgumentCount;
_cdict.Add(command, terminalCommandEX);
_cextra.Add(terminalCommandEX);
_lastModified = true;
return true;
}
public static bool AliasCommand(string oldCommand, string newAlias)
{
oldCommand = oldCommand.ToUpper();
newAlias = newAlias.ToUpper();
if (!_cdict.ContainsKey(oldCommand))
{
return false;
}
if (_cdict.ContainsKey(newAlias))
{
return false;
}
TerminalCommandEX terminalCommandEX = _cdict[oldCommand];
TerminalCommandEX terminalCommandEX2 = TerminalCommandEX.Create();
terminalCommandEX2.Command = newAlias;
terminalCommandEX2._alias_original = oldCommand;
terminalCommandEX2.Hidden = terminalCommandEX.Hidden;
((Object)terminalCommandEX2).name = ((Object)terminalCommandEX).name;
terminalCommandEX2.Description = terminalCommandEX.Description;
terminalCommandEX2.NumArgs = terminalCommandEX.NumArgs;
terminalCommandEX2.ParameterDescription = terminalCommandEX.ParameterDescription;
terminalCommandEX2.ActionMethod = terminalCommandEX.ActionMethod;
terminalCommandEX2.actionMethodName = terminalCommandEX.actionMethodName;
terminalCommandEX2.ArgsOptional = terminalCommandEX.ArgsOptional;
terminalCommandEX2.ArgTips = terminalCommandEX.ArgTips;
terminalCommandEX2.Example = terminalCommandEX.Example;
if (!string.IsNullOrWhiteSpace(terminalCommandEX.actionMethodName))
{
terminalCommandEX2.ForceExactArgument = true;
}
_cdict.Add(newAlias, terminalCommandEX2);
_cextra.Add(terminalCommandEX2);
_lastModified = true;
return true;
}
public static bool OverrideCommand(string oldCommand, Func<List<string>, IEnumerator> onInvoke, string? name = null, string? description = null, int? argAmount = null, bool? argOptional = null, string? parameterDesc = null, string[]? argumentTips = null, string? example = null, bool? hidden = null)
{
oldCommand = oldCommand.ToUpper();
if (!_cdict.ContainsKey(oldCommand))
{
return false;
}
TerminalCommandEX terminalCommandEX = _cdict[oldCommand];
terminalCommandEX.Hidden = hidden ?? terminalCommandEX.Hidden;
((Object)terminalCommandEX).name = name ?? ((Object)terminalCommandEX).name;
terminalCommandEX.Description = description ?? terminalCommandEX.Description;
terminalCommandEX.NumArgs = argAmount ?? terminalCommandEX.NumArgs;
terminalCommandEX.ParameterDescription = parameterDesc ?? terminalCommandEX.ParameterDescription;
terminalCommandEX.ActionMethod = onInvoke;
terminalCommandEX.actionMethodName = string.Empty;
terminalCommandEX.ForceExactArgument = false;
terminalCommandEX.ArgsOptional = argOptional ?? terminalCommandEX.ArgsOptional;
terminalCommandEX.ArgTips = argumentTips ?? terminalCommandEX.ArgTips;
terminalCommandEX.Example = example ?? terminalCommandEX.Example;
return true;
}
public static bool HookCommand(string targetCommand, Action<List<string>> func, STEHookTarget hookTarget = STEHookTarget.After, STEHookPriority priority = STEHookPriority.Default)
{
targetCommand = targetCommand.ToUpper();
if (!_cdict.ContainsKey(targetCommand))
{
return false;
}
if (_chook.TryGetValue(targetCommand, out LinkedList<STEHookData>[] value))
{
LinkedList<STEHookData> linkedList = value[(int)hookTarget];
STEHookData value2 = new STEHookData(func, targetCommand, hookTarget, priority);
LinkedListNode<STEHookData> linkedListNode = linkedList.First;
if (linkedListNode == null)
{
linkedList.AddFirst(value2);
return true;
}
while (true)
{
if (linkedListNode.Value.Priority < priority)
{
linkedList.AddBefore(linkedListNode, value2);
}
if (linkedListNode.Next == null)
{
break;
}
linkedListNode = linkedListNode.Next;
}
linkedList.AddAfter(linkedListNode, value2);
return true;
}
_cdict[targetCommand].HookMethod = delegate(string cmd, List<string> args, STEHookTarget executeTarget)
{
if (_chook.TryGetValue(cmd, out LinkedList<STEHookData>[] value3))
{
for (LinkedListNode<STEHookData> linkedListNode2 = value3[(int)executeTarget].First; linkedListNode2 != null; linkedListNode2 = linkedListNode2.Next)
{
try
{
linkedListNode2.Value.Func(args);
}
catch
{
PLog.Err("Exception caught upon executing hook of \"" + linkedListNode2.Value.TargetCommand + "\" command");
if (Plugin.pluginInstance.DebugMode)
{
throw;
}
}
}
}
};
value = new LinkedList<STEHookData>[2];
LinkedList<STEHookData> linkedList2 = new LinkedList<STEHookData>();
LinkedList<STEHookData> linkedList3 = new LinkedList<STEHookData>();
value[0] = linkedList2;
value[1] = linkedList3;
value[(int)hookTarget].AddFirst(new STEHookData(func, targetCommand, hookTarget, priority));
_chook.Add(targetCommand, value);
return true;
}
}
}
namespace SubTerminalEX.Patches
{
[HarmonyPatch(typeof(NetworkManager), "OnJoinedRoom")]
internal class NetworkManagerOnJoinedRoomPatches
{
[HarmonyPostfix]
[HarmonyWrapSafe]
internal static void Postfix()
{
Plugin.pluginInstance.OnGameStartup();
}
}
[HarmonyPatch(typeof(TerminalInterpreter), "Interpret")]
internal static class TerminalInterpreterInterpretPatches
{
internal static bool _fieldCached;
internal static FieldRef<TerminalInterpreter, List<string>> tiArgs;
internal static AudioClip errorClip;
internal static AudioClip buyClip;
internal static TerminalInterpreter instance;
private static void Cache(TerminalInterpreter term)
{
tiArgs = AccessTools.FieldRefAccess<TerminalInterpreter, List<string>>("args");
errorClip = term.errorClip;
buyClip = term.buyClip;
instance = term;
_fieldCached = true;
}
[HarmonyPrefix]
[HarmonyPriority(800)]
[HarmonyWrapSafe]
public static bool Prefix(ref string userInput, ref TerminalInterpreter __instance)
{
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
//IL_037e: Unknown result type (might be due to invalid IL or missing references)
//IL_0384: Unknown result type (might be due to invalid IL or missing references)
//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0403: Unknown result type (might be due to invalid IL or missing references)
//IL_0435: Unknown result type (might be due to invalid IL or missing references)
//IL_0324: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
if (!_fieldCached)
{
Cache(__instance);
}
PLog.Dbg("Running: " + userInput);
ref List<string> reference = ref tiArgs.Invoke(__instance);
reference.Clear();
string[] array = userInput.TrimStart(Array.Empty<char>()).Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (array.Length == 0)
{
return false;
}
if (array[0].StartsWith("\""))
{
TerminalManager.instance.QueueTextLine("ERROR: command can not start with \" character", default(Vector2), 0.075f, (AudioClip)null, 0f);
return false;
}
reference.Add(array[0]);
int i = 1;
int num = array.Length;
StringBuilder stringBuilder = new StringBuilder();
for (; i < num; i++)
{
if (array[i].StartsWith("\""))
{
string text = array[i];
stringBuilder.Append(text.Substring(1));
stringBuilder.Append(' ');
bool flag = false;
while (i < num)
{
i++;
text = array[i];
if (text.EndsWith("\""))
{
stringBuilder.Append(text.Substring(0, text.Length - 1));
reference.Add(stringBuilder.ToString());
stringBuilder.Clear();
flag = true;
break;
}
stringBuilder.Append(text);
stringBuilder.Append(' ');
}
if (!flag)
{
TerminalManager.instance.QueueTextLine("ERROR: never ending string argument detected!", default(Vector2), 0.075f, (AudioClip)null, 0f);
return false;
}
}
else
{
reference.Add(array[i]);
}
}
reference[0] = reference[0].Replace("\\", "").Replace("/", "");
string text2 = reference[0];
if (!(text2 == "Y"))
{
if (text2 == "N")
{
reference[0] = "NO";
}
}
else
{
reference[0] = "YES";
}
if ((int)__instance.currentPrompt != 0 && reference[0] != "NO" && reference[0] != "YES")
{
__instance.currentPrompt = (Prompts)0;
}
PLog.Dbg("Args: ");
foreach (string item in reference)
{
PLog.Dbg(item);
}
string text3 = reference[0];
if (!TerminalCommandManager._cdict.TryGetValue(text3, out TerminalCommandEX value))
{
string closestCommand = Shared.GetClosestCommand(reference[0]);
if (closestCommand != null)
{
TerminalManager.instance.QueueTextLine("Command not recognized. Did you mean " + closestCommand + "?", new Vector2(1f, 1f), 0.075f, (AudioClip)null, 0f);
return false;
}
closestCommand = Shared.GetClosestCommand(userInput);
if (closestCommand != null)
{
TerminalManager.instance.QueueTextLine("Command not recognized. Did you mean " + closestCommand + "?", new Vector2(1f, 1f), 0.075f, (AudioClip)null, 0f);
return false;
}
TerminalManager.instance.QueueTextLine("Command not recognized. Use \"HELP\" for a list of commands.", new Vector2(1f, 1f), 0.075f, (AudioClip)null, 0f);
return false;
}
PLog.Dbg("Command " + text3 + " is valid, running it action method keyed " + value.Command);
if (!value.ArgsOptional && !value.CheckArgs(reference))
{
TerminalManager.instance.QueueTextLine("Incorrect use of parameters. Use \"HELP\" for more info.", default(Vector2), 0.075f, (AudioClip)null, 0f);
TerminalManager.instance.QueueTextLine("Expected parameters and usage example:", new Vector2(1f, 1f), 0.075f, (AudioClip)null, 0f);
TerminalManager.instance.QueueTextLine(value.Command, default(Vector2), 0.075f, (AudioClip)null, 0f);
TerminalManager.instance.QueueTextLine(" Parameters: " + value.ParameterDescription, default(Vector2), 0.075f, (AudioClip)null, 0f);
TerminalManager.instance.QueueTextLine(" Example: " + value.Example, new Vector2(0f, 1f), 0.075f, (AudioClip)null, 0f);
return false;
}
reference.RemoveAt(0);
if (value.ForceExactArgument && reference.Count > value.NumArgs)
{
reference.RemoveRange(value.NumArgs, reference.Count);
}
value.HookMethod?.Invoke(value.Command, reference, STEHookTarget.Before);
if (value.ActionMethod != null)
{
((MonoBehaviour)__instance).StartCoroutine(value.ActionMethod(reference));
}
if (!string.IsNullOrWhiteSpace(value.actionMethodName))
{
((MonoBehaviour)__instance).StartCoroutine(value.actionMethodName);
}
value.HookMethod?.Invoke(value.Command, reference, STEHookTarget.After);
return false;
}
}
[HarmonyPatch(typeof(TerminalManager), "Awake")]
internal static class TerminalManagerAwakePatches
{
[HarmonyPostfix]
[HarmonyWrapSafe]
internal static void Postfix(ref TerminalManager __instance)
{
if (Plugin.pluginInstance.FastTerminalBoot)
{
__instance.skipBoot = true;
}
}
}
}
namespace SubTerminalEX.Features
{
internal static class ExtraTerminalCommand
{
internal static FieldRef<TerminalManager, int> _TerminalManager_lastDestroyedLine;
internal static readonly HashSet<string> _aliasList = new HashSet<string>();
internal static string _palias_path = string.Empty;
internal static int _palias_size = 0;
internal static MethodInfo _hatlist;
internal static MethodInfo _hatbuy;
internal static MethodInfo _upgradelist;
internal static MethodInfo _upgradebuy;
internal static void ChangeLastDestroyedLine(TerminalManager term)
{
_TerminalManager_lastDestroyedLine.Invoke(term) = 0;
}
internal static IEnumerator CommandClear(List<string> _)
{
TerminalManager instance = TerminalManager.instance;
foreach (Transform item in instance.messageList.transform)
{
Transform val = item;
if (((Object)val).name != "UserInputLine")
{
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
instance.messageList.GetComponent<RectTransform>().sizeDelta = new Vector2(1920f, 160f);
instance.response.Clear();
ChangeLastDestroyedLine(instance);
instance.EnableInput();
yield break;
}
internal static IEnumerator ProcessAliasFile()
{
int zt = 0;
string[] str;
if (_palias_size < 33554432)
{
str = File.ReadAllText(_palias_path, Encoding.UTF8).Split(new char[2] { '\n', ',' }, StringSplitOptions.RemoveEmptyEntries);
if (_palias_size > 16777216)
{
yield return (object)new WaitForEndOfFrame();
}
}
else
{
StringBuilder sb = new StringBuilder();
FileStream std = File.Open(_palias_path, FileMode.Open, FileAccess.Read, FileShare.None);
byte[] arr = new byte[4096];
while (true)
{
int num = std.Read(arr, 0, 4096);
for (int i = 0; i < num; i++)
{
sb.Append(arr[i]);
}
Array.Clear(arr, 0, num);
if (num < 4096)
{
break;
}
zt++;
if (zt >= 10)
{
zt = 0;
yield return (object)new WaitForEndOfFrame();
}
}
str = sb.ToString().Split(new char[2] { '\n', ',' }, StringSplitOptions.RemoveEmptyEntries);
sb.Clear();
std.Dispose();
yield return (object)new WaitForEndOfFrame();
}
zt = 0;
string[] array = str;
foreach (string item in array)
{
if (zt >= 100)
{
zt = 0;
yield return (object)new WaitForEndOfFrame();
}
if (string.IsNullOrWhiteSpace(item))
{
continue;
}
string[] array2 = item.Split(new char[1] { ' ' });
if (array2.Length >= 2)
{
int num2 = ((array2[0] == " ") ? 1 : 0);
_ = array2[num2];
_ = array2[num2 + 1];
if (TerminalCommandManager.AliasCommand(array2[num2], array2[num2 + 1]))
{
_aliasList.Add(array2[num2 + 1]);
}
zt++;
}
}
TerminalManager instance = TerminalManager.instance;
instance.QueueTextLine("Successfully loaded alias file", default(Vector2), 0.075f, (AudioClip)null, 0f);
instance.EnableInput();
}
internal static IEnumerator CommandAlias(List<string> args)
{
string text = args[0];
TerminalManager instance = TerminalManager.instance;
switch (text)
{
case "SET":
case "MAP":
{
if (args.Count < 3)
{
instance.QueueTextLine($"ERROR: mapping command require 2 argument, received {args.Count - 1}", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
string text2 = args[1];
string text3 = args[2];
if (!TerminalCommandManager._cdict.ContainsKey(text2))
{
instance.QueueTextLine("ERROR: Can not map to non-existences command \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
if (TerminalCommandManager.AliasCommand(text2, text3))
{
_aliasList.Add(text3);
}
instance.QueueTextLine("Successfully map \"" + text3 + "\" to \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
case "REM":
case "REMOVE":
case "RM":
{
if (args.Count < 2)
{
instance.QueueTextLine("ERROR: remove mapped alias command require 1 argument, received 0", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
string text2 = args[1];
if (!_aliasList.Contains(text2))
{
instance.QueueTextLine("ERROR: Can not remove non-existences alias \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
_aliasList.Remove(text2);
TerminalCommandManager.RemoveCommand(text2);
instance.QueueTextLine("Successfully removed alias \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
case "CLEAR":
case "RESET":
{
if (_aliasList.Count <= 0)
{
instance.QueueTextLine("ERROR: Can not clear alias because none exists", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
int num = _aliasList.Where((string item) => TerminalCommandManager.RemoveCommand(item)).Count();
instance.QueueTextLine($"Successfully removed {num} mapped alias", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
case "GEN":
case "GENERATE":
{
if (args.Count < 2)
{
instance.QueueTextLine("ERROR: generate alias file require 1 argument, received 0", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
string text2 = args[1];
string text4 = Path.Combine(Environment.CurrentDirectory, text2 + ".txt");
FileStream fileStream = File.Open(text4, FileMode.Create, FileAccess.Write, FileShare.None);
StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.UTF8);
foreach (string alias in _aliasList)
{
string alias_original = TerminalCommandManager._cdict[alias]._alias_original;
streamWriter.Write(alias_original);
streamWriter.Write(' ');
streamWriter.Write(alias);
streamWriter.Write(',');
streamWriter.Flush();
}
fileStream.SetLength(fileStream.Length - 1);
fileStream.Flush();
streamWriter.Close();
instance.QueueTextLine("Successfully wrote to " + text2 + ".txt", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
case "LOAD":
{
if (args.Count < 2)
{
instance.QueueTextLine("ERROR: load alias file require 1 argument, received 0", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
string text2 = args[1];
string text4 = Path.Combine(Environment.CurrentDirectory, text2 + ".txt");
if (!File.Exists(text4))
{
instance.QueueTextLine("ERROR: Can not load non-existence alias file", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
long length = new FileInfo(text4).Length;
if (length > 1073741824)
{
instance.QueueTextLine("ERROR: Will not load alias file larger than 1GB", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
if (_aliasList.Count > 0)
{
foreach (string alias2 in _aliasList)
{
TerminalCommandManager.RemoveCommand(alias2);
}
}
instance.QueueTextLine("Loading pre-defined alias text file named: " + text2 + ".txt", default(Vector2), 0.075f, (AudioClip)null, 0f);
instance.QueueTextLine("WARN: This operation may took a long time", default(Vector2), 0.075f, (AudioClip)null, 0f);
_palias_path = text4;
_palias_size = (int)length;
Plugin.Interpreter.StartCoroutine(ProcessAliasFile());
instance.inputEnabled = false;
break;
}
default:
{
if (args.Count < 2)
{
instance.QueueTextLine($"ERROR: mapping command require 2 argument, received {args.Count}", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
string text2 = args[0];
string text3 = args[1];
if (!TerminalCommandManager._cdict.ContainsKey(text2))
{
instance.QueueTextLine("ERROR: Can not map to non-existences command \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
if (TerminalCommandManager.AliasCommand(text2, text3))
{
_aliasList.Add(text3);
}
instance.QueueTextLine("Successfully map \"" + text3 + "\" to \"" + text2 + "\"", default(Vector2), 0.075f, (AudioClip)null, 0f);
break;
}
}
yield break;
}
internal static IEnumerator HatShop(List<string> arg)
{
return (IEnumerator)_hatlist.Invoke(TerminalInterpreterInterpretPatches.instance, null);
}
internal static IEnumerator HatBuy(List<string> arg)
{
return (IEnumerator)_hatbuy.Invoke(TerminalInterpreterInterpretPatches.instance, null);
}
internal static IEnumerator UpgradeShop(List<string> arg)
{
return (IEnumerator)_upgradelist.Invoke(TerminalInterpreterInterpretPatches.instance, null);
}
internal static IEnumerator UpgradeBuy(List<string> arg)
{
return (IEnumerator)_upgradebuy.Invoke(TerminalInterpreterInterpretPatches.instance, null);
}
internal static void Register()
{
TerminalCommandManager.AddNoArgumentCommand("clear", CommandClear, "Clear terminal", "Clear the terminal");
TerminalCommandManager.AliasCommand("clear", "cls");
_TerminalManager_lastDestroyedLine = AccessTools.FieldRefAccess<TerminalManager, int>("lastDestroyedLine");
TerminalCommandManager.AddCommand("alias", CommandAlias, "Alias system", "Create terminal alias", 1, forceExactArgumentCount: false, argOptional: false, "[kind] [args]", new string[1] { "" }, "alias set view_cam vcam");
_hatlist = AccessTools.Method("TerminalInterpreter:OpenHatShopCommand", (Type[])null, (Type[])null);
_hatbuy = AccessTools.Method("TerminalInterpreter:BuyHatCommand", (Type[])null, (Type[])null);
_upgradelist = AccessTools.Method("TerminalInterpreter:OpenUpgradeShopCommand", (Type[])null, (Type[])null);
_upgradebuy = AccessTools.Method("TerminalInterpreter:BuyUpgradeCommand", (Type[])null, (Type[])null);
TerminalCommandManager.AddCommand("hats", HatShop);
TerminalCommandManager.AddCommand("buy_hat", HatBuy, "", "", 1, forceExactArgumentCount: true);
TerminalCommandManager.AddCommand("upgrades", UpgradeShop);
TerminalCommandManager.AddCommand("buy_upgrade", UpgradeBuy, "", "", 1, forceExactArgumentCount: true);
}
}
}