r2mods/ilspy_dump/ror2_csproj/RoR2/Console.cs

1299 lines
30 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using HG;
using HG.Reflection;
using RoR2.ConVar;
using UnityEngine;
using UnityEngine.Networking;
namespace RoR2;
public class Console : MonoBehaviour
{
public struct Log
{
public string message;
public string stackTrace;
public LogType logType;
}
public delegate void LogReceivedDelegate(Log log);
private class Lexer
{
private enum TokenType
{
Identifier,
NestedString
}
private string srcString;
private int readIndex;
private StringBuilder stringBuilder = new StringBuilder();
public Lexer(string srcString)
{
this.srcString = srcString;
readIndex = 0;
}
private static bool IsIgnorableCharacter(char character)
{
if (!IsSeparatorCharacter(character) && !IsQuoteCharacter(character) && !IsIdentifierCharacter(character))
{
return character != '/';
}
return false;
}
private static bool IsSeparatorCharacter(char character)
{
if (character != ';')
{
return character == '\n';
}
return true;
}
private static bool IsQuoteCharacter(char character)
{
if (character != '\'')
{
return character == '"';
}
return true;
}
private static bool IsIdentifierCharacter(char character)
{
if (!char.IsLetterOrDigit(character) && character != '_' && character != '.' && character != '-')
{
return character == ':';
}
return true;
}
private bool TrimComment()
{
if (readIndex >= srcString.Length)
{
return false;
}
if (srcString[readIndex] == '/')
{
if (readIndex + 1 < srcString.Length)
{
char c = srcString[readIndex + 1];
if (c == '/')
{
while (readIndex < srcString.Length)
{
if (srcString[readIndex] == '\n')
{
readIndex++;
return true;
}
readIndex++;
}
return true;
}
if (c == '*')
{
while (readIndex < srcString.Length - 1)
{
if (srcString[readIndex] == '*' && srcString[readIndex + 1] == '/')
{
readIndex += 2;
return true;
}
readIndex++;
}
return true;
}
}
readIndex++;
}
return false;
}
private void TrimWhitespace()
{
while (readIndex < srcString.Length && IsIgnorableCharacter(srcString[readIndex]))
{
readIndex++;
}
}
private void TrimUnused()
{
do
{
TrimWhitespace();
}
while (TrimComment());
}
private static int UnescapeNext(string srcString, int startPos, out char result)
{
result = '\\';
int num = startPos;
num++;
if (num < srcString.Length)
{
char c = srcString[num];
switch (c)
{
case '"':
case '\'':
case '\\':
result = c;
return 2;
case 'n':
result = '\n';
return 2;
}
}
return 1;
}
public string NextToken()
{
TrimUnused();
if (readIndex == srcString.Length)
{
return null;
}
TokenType tokenType = TokenType.Identifier;
char c = srcString[readIndex];
char c2 = '\0';
if (IsQuoteCharacter(c))
{
tokenType = TokenType.NestedString;
c2 = c;
readIndex++;
}
else if (IsSeparatorCharacter(c))
{
readIndex++;
return ";";
}
char result;
for (; readIndex < srcString.Length; stringBuilder.Append(result), readIndex++)
{
result = srcString[readIndex];
switch (tokenType)
{
case TokenType.Identifier:
if (IsIdentifierCharacter(result))
{
continue;
}
break;
case TokenType.NestedString:
if (result == '\\')
{
readIndex += UnescapeNext(srcString, readIndex, out result) - 1;
continue;
}
if (result != c2)
{
continue;
}
readIndex++;
break;
default:
continue;
}
break;
}
string result2 = stringBuilder.ToString();
stringBuilder.Length = 0;
return result2;
}
public Queue<string> GetTokens()
{
Queue<string> queue = new Queue<string>();
for (string text = NextToken(); text != null; text = NextToken())
{
queue.Enqueue(text);
}
queue.Enqueue(";");
return queue;
}
}
private class Substring
{
public string srcString;
public int startIndex;
public int length;
public int endIndex => startIndex + length;
public string str => srcString.Substring(startIndex, length);
public Substring nextToken => new Substring
{
srcString = srcString,
startIndex = startIndex + length,
length = 0
};
}
private class ConCommand
{
public ConVarFlags flags;
public ConCommandDelegate action;
public string helpText;
}
public delegate void ConCommandDelegate(ConCommandArgs args);
private class ConvarClass
{
public string containerAssemblyName;
public List<string> convars = new List<string>();
}
public readonly struct CmdSender
{
public readonly LocalUser localUser;
public readonly NetworkUser networkUser;
public CmdSender(LocalUser localUser)
{
this.localUser = localUser;
networkUser = localUser?.currentNetworkUser;
}
public CmdSender(NetworkUser networkUser)
{
localUser = networkUser?.localUser;
this.networkUser = networkUser;
}
public static implicit operator CmdSender(LocalUser localUser)
{
return new CmdSender(localUser);
}
public static implicit operator CmdSender(NetworkUser networkUser)
{
return new CmdSender(networkUser);
}
}
private enum SystemConsoleType
{
None,
Attach,
Alloc
}
public class AutoComplete
{
private struct MatchInfo
{
public string str;
public int similarity;
}
private List<string> searchableStrings = new List<string>();
private string searchString;
public List<string> resultsList = new List<string>();
public List<string> GetSearchableStrings => searchableStrings;
public AutoComplete(Console console)
{
HashSet<string> hashSet = new HashSet<string>();
for (int i = 0; i < userCmdHistory.Count; i++)
{
hashSet.Add(userCmdHistory[i]);
}
foreach (KeyValuePair<string, BaseConVar> allConVar in console.allConVars)
{
hashSet.Add(allConVar.Key);
}
foreach (KeyValuePair<string, ConCommand> item in console.concommandCatalog)
{
hashSet.Add(item.Key);
}
foreach (string item2 in hashSet)
{
searchableStrings.Add(item2);
}
searchableStrings.Sort();
}
public bool SetSearchString(string newSearchString)
{
newSearchString = newSearchString.ToLower(CultureInfo.InvariantCulture);
if (newSearchString == searchString)
{
return false;
}
searchString = newSearchString;
List<MatchInfo> list = new List<MatchInfo>();
for (int i = 0; i < searchableStrings.Count; i++)
{
string text = searchableStrings[i];
int num = Math.Min(text.Length, searchString.Length);
int j;
for (j = 0; j < num && char.ToLower(text[j]) == searchString[j]; j++)
{
}
if (j > 1)
{
list.Add(new MatchInfo
{
str = text,
similarity = j
});
}
}
list.Sort(delegate(MatchInfo a, MatchInfo b)
{
if (a.similarity == b.similarity)
{
return string.CompareOrdinal(a.str, b.str);
}
return (a.similarity <= b.similarity) ? 1 : (-1);
});
resultsList = new List<string>();
for (int k = 0; k < list.Count; k++)
{
resultsList.Add(list[k].str);
}
return true;
}
}
public class CheatsConVar : BaseConVar
{
public static readonly CheatsConVar instance = new CheatsConVar("cheats", ConVarFlags.ExecuteOnServer, "0", "Enable cheats. Achievements, unlock progression, and stat tracking will be disabled until the application is restarted.");
private bool _boolValue;
public bool boolValue
{
get
{
return _boolValue;
}
private set
{
if (_boolValue)
{
sessionCheatsEnabled = true;
}
}
}
public CheatsConVar(string name, ConVarFlags flags, string defaultValue, string helpText)
: base(name, flags, defaultValue, helpText)
{
}
public override void SetString(string newValue)
{
if (TextSerialization.TryParseInvariant(newValue, out int result))
{
boolValue = result != 0;
}
}
public override string GetString()
{
if (!boolValue)
{
return "0";
}
return "1";
}
}
public static List<Log> logs = new List<Log>();
private Dictionary<string, string> vstrs = new Dictionary<string, string>();
private Dictionary<string, ConCommand> concommandCatalog = new Dictionary<string, ConCommand>();
private Dictionary<string, BaseConVar> allConVars;
private List<BaseConVar> archiveConVars;
public static List<string> userCmdHistory = new List<string>();
private const int VK_RETURN = 13;
private const int WM_KEYDOWN = 256;
private static byte[] inputStreamBuffer = new byte[256];
private static Queue<string> stdInQueue = new Queue<string>();
private static Thread stdInReaderThread = null;
private static SystemConsoleType systemConsoleType = SystemConsoleType.None;
public static bool loadingIsComplete = false;
private int maxPassesBeforeYielding = 25;
private static readonly StringBuilder sharedStringBuilder = new StringBuilder();
private const string configFolder = "/Config/";
private const string archiveConVarsPath = "/Config/config.cfg";
private static IntConVar maxMessages = new IntConVar("max_messages", ConVarFlags.Archive, "25", "Maximum number of messages that can be held in the console log.");
public static Console instance { get; private set; }
public static bool sessionCheatsEnabled { get; private set; } = false;
public static event LogReceivedDelegate onLogReceived;
public static event Action onClear;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void RegisterLogHandler()
{
Application.logMessageReceived += HandleLog;
}
private static void HandleLog(string message, string stackTrace, LogType logType)
{
switch (logType)
{
case LogType.Error:
message = string.Format(CultureInfo.InvariantCulture, "<color=#FF0000>{0}</color>", message);
break;
case LogType.Warning:
message = string.Format(CultureInfo.InvariantCulture, "<color=#FFFF00>{0}</color>", message);
break;
}
Log log = default(Log);
log.message = message;
log.stackTrace = stackTrace;
log.logType = logType;
Log log2 = log;
logs.Add(log2);
if (maxMessages.value > 0)
{
while (logs.Count > maxMessages.value)
{
logs.RemoveAt(0);
}
}
if (Console.onLogReceived != null)
{
Console.onLogReceived(log2);
}
}
private string GetVstrValue(LocalUser user, string identifier)
{
if (user == null)
{
if (vstrs.TryGetValue(identifier, out var value))
{
return value;
}
return "";
}
return "";
}
public void CacheConVars()
{
_ = typeof(BaseConVar).Assembly;
List<ConvarClass> list = new List<ConvarClass>();
Type[] types = typeof(BaseConVar).Assembly.GetTypes();
foreach (Type type in types)
{
bool flag = false;
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (!fieldInfo.FieldType.IsSubclassOf(typeof(BaseConVar)))
{
continue;
}
if (fieldInfo.IsStatic)
{
BaseConVar conVar = (BaseConVar)fieldInfo.GetValue(null);
RegisterConVarInternal(conVar);
if (!flag)
{
flag = true;
list.Add(new ConvarClass
{
containerAssemblyName = type.FullName
});
}
list[list.Count - 1].convars.Add(fieldInfo.Name);
}
else if (CustomAttributeExtensions.GetCustomAttribute<CompilerGeneratedAttribute>(type) == null)
{
Debug.LogErrorFormat("ConVar defined as {0}.{1} could not be registered. ConVars must be static fields.", type.Name, fieldInfo.Name);
}
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (CustomAttributeExtensions.GetCustomAttribute<ConVarProviderAttribute>(methodInfo) == null)
{
continue;
}
Debug.LogErrorFormat("ConVarProviderAttribute on method {0}.{1}", type.Name, methodInfo.Name);
if (methodInfo.ReturnType != typeof(IEnumerable<BaseConVar>) || methodInfo.GetParameters().Length != 0)
{
Debug.LogErrorFormat("ConVar provider {0}.{1} does not match the signature \"static IEnumerable<ConVar.BaseConVar>()\".", type.Name, methodInfo.Name);
continue;
}
if (!methodInfo.IsStatic)
{
Debug.LogErrorFormat("ConVar provider {0}.{1} could not be invoked. Methods marked with the ConVarProvider attribute must be static.", type.Name, methodInfo.Name);
continue;
}
foreach (BaseConVar item in (IEnumerable<BaseConVar>)methodInfo.Invoke(null, Array.Empty<object>()))
{
RegisterConVarInternal(item);
}
}
}
if (list.Count <= 0)
{
return;
}
StreamWriter streamWriter = new StreamWriter(Application.streamingAssetsPath + "/ConVarNames.txt");
foreach (ConvarClass item2 in list)
{
streamWriter.WriteLine(item2.containerAssemblyName);
streamWriter.WriteLine(item2.convars.Count);
foreach (string convar in item2.convars)
{
streamWriter.WriteLine(convar);
}
}
streamWriter.Close();
}
private IEnumerator InternalInitConVarsCoroutine()
{
CacheConVars();
yield return null;
string path = Application.streamingAssetsPath + "/ConVarNames.txt";
string[] fileLines;
int curLine;
if (File.Exists(path))
{
fileLines = File.ReadAllLines(path);
curLine = 0;
StringBuilder sb = new StringBuilder(256);
string assemblyName = typeof(BaseConVar).Assembly.FullName;
int currentPass = 0;
while (!EndOfStream())
{
string text = ReadLine();
if (!string.IsNullOrEmpty(text))
{
int num = int.Parse(ReadLine());
sb.Clear();
sb.AppendFormat("{0}, {1}", text, assemblyName);
Type type = Type.GetType(sb.ToString());
if (type != null)
{
for (int i = 0; i < num; i++)
{
string text2 = ReadLine();
FieldInfo field = type.GetField(text2, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
BaseConVar conVar = (BaseConVar)field.GetValue(null);
RegisterConVarInternal(conVar);
}
else
{
Debug.LogError("Failed to find convar " + text2);
}
}
}
else
{
Debug.LogErrorFormat("Failed to get type {0} (Full name: {1})", text, sb.ToString());
for (int j = 0; j < num; j++)
{
ReadLine();
}
}
}
currentPass++;
if (currentPass >= maxPassesBeforeYielding)
{
currentPass = 0;
yield return null;
}
}
}
else
{
Debug.LogError("ERROR: Failed to load StreamingAssets/ConVarNames.txt");
}
bool EndOfStream()
{
return curLine >= fileLines.Length;
}
string ReadLine()
{
return fileLines[curLine++];
}
}
private void InternalInitConVars()
{
string path = Application.streamingAssetsPath + "/ConVarNames.txt";
string[] fileLines;
int curLine;
if (File.Exists(path))
{
fileLines = File.ReadAllLines(path);
curLine = 0;
StringBuilder stringBuilder = new StringBuilder(256);
string fullName = typeof(BaseConVar).Assembly.FullName;
while (!EndOfStream())
{
string text = ReadLine();
if (string.IsNullOrEmpty(text))
{
continue;
}
int num = int.Parse(ReadLine());
stringBuilder.Clear();
stringBuilder.AppendFormat("{0}, {1}", text, fullName);
Type type = Type.GetType(stringBuilder.ToString());
if (type != null)
{
for (int i = 0; i < num; i++)
{
string text2 = ReadLine();
FieldInfo field = type.GetField(text2, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
BaseConVar conVar = (BaseConVar)field.GetValue(null);
RegisterConVarInternal(conVar);
}
else
{
Debug.LogError("Failed to find convar " + text2);
}
}
}
else
{
Debug.LogErrorFormat("Failed to get type {0} (Full name: {1})", text, stringBuilder.ToString());
for (int j = 0; j < num; j++)
{
ReadLine();
}
}
}
}
else
{
Debug.LogError("ERROR: Failed to load StreamingAssets/ConVarNames.txt");
}
bool EndOfStream()
{
return curLine >= fileLines.Length;
}
string ReadLine()
{
return fileLines[curLine++];
}
}
public IEnumerator InitConVarsCoroutine()
{
allConVars = new Dictionary<string, BaseConVar>();
archiveConVars = new List<BaseConVar>();
yield return InternalInitConVarsCoroutine();
int currentPass = 0;
foreach (KeyValuePair<string, BaseConVar> allConVar in allConVars)
{
try
{
BaseConVar value = allConVar.Value;
if ((value.flags & ConVarFlags.Engine) != 0)
{
value.defaultValue = value.GetString();
}
else if (value.defaultValue != null)
{
value.AttemptSetString(value.defaultValue);
}
}
catch (Exception message)
{
Debug.LogError(message);
}
currentPass++;
if (currentPass >= maxPassesBeforeYielding)
{
currentPass = 0;
yield return null;
}
}
}
public void InitConVars()
{
allConVars = new Dictionary<string, BaseConVar>();
archiveConVars = new List<BaseConVar>();
InternalInitConVars();
foreach (KeyValuePair<string, BaseConVar> allConVar in allConVars)
{
try
{
BaseConVar value = allConVar.Value;
if ((value.flags & ConVarFlags.Engine) != 0)
{
value.defaultValue = value.GetString();
}
else if (value.defaultValue != null)
{
value.AttemptSetString(value.defaultValue);
}
}
catch (Exception message)
{
Debug.LogError(message);
}
}
}
private void RegisterConVarInternal(BaseConVar conVar)
{
if (conVar == null)
{
Debug.LogWarning("Attempted to register null ConVar");
return;
}
allConVars[conVar.name] = conVar;
if ((conVar.flags & ConVarFlags.Archive) != 0)
{
archiveConVars.Add(conVar);
}
}
public BaseConVar FindConVar(string name)
{
if (allConVars.TryGetValue(name, out var value))
{
return value;
}
return null;
}
public void SubmitCmd(NetworkUser sender, string cmd, bool recordSubmit = false)
{
SubmitCmd((CmdSender)sender, cmd, recordSubmit);
}
public void SubmitCmd(CmdSender sender, string cmd, bool recordSubmit = false)
{
if (recordSubmit)
{
Log log = default(Log);
log.message = string.Format(CultureInfo.InvariantCulture, "<color=#C0C0C0>] {0}</color>", cmd);
log.stackTrace = "";
log.logType = LogType.Log;
Log log2 = log;
logs.Add(log2);
if (Console.onLogReceived != null)
{
Console.onLogReceived(log2);
}
userCmdHistory.Add(cmd);
}
Queue<string> tokens = new Lexer(cmd).GetTokens();
List<string> list = new List<string>();
bool flag = false;
while (tokens.Count != 0)
{
string text = tokens.Dequeue();
if (text == ";")
{
flag = false;
if (list.Count > 0)
{
string concommandName = list[0].ToLower(CultureInfo.InvariantCulture);
list.RemoveAt(0);
RunCmd(sender, concommandName, list);
list.Clear();
}
}
else
{
if (flag)
{
text = GetVstrValue(sender.localUser, text);
flag = false;
}
if (text == "vstr")
{
flag = true;
}
else
{
list.Add(text);
}
}
}
}
private void ForwardCmdToServer(ConCommandArgs args)
{
if ((bool)args.sender)
{
args.sender.CallCmdSendConsoleCommand(args.commandName, args.userArgs.ToArray());
}
}
public void RunClientCmd(NetworkUser sender, string concommandName, string[] args)
{
RunCmd(sender, concommandName, new List<string>(args));
}
private void RunCmd(CmdSender sender, string concommandName, List<string> userArgs)
{
bool flag = !(sender.networkUser?.isLocalPlayer ?? true);
ConVarFlags conVarFlags = ConVarFlags.None;
ConCommand value = null;
BaseConVar baseConVar = null;
if (concommandCatalog.TryGetValue(concommandName, out value))
{
conVarFlags = value.flags;
}
else
{
baseConVar = FindConVar(concommandName);
if (baseConVar == null)
{
Debug.LogFormat("\"{0}\" is not a recognized ConCommand or ConVar.", concommandName);
return;
}
conVarFlags = baseConVar.flags;
}
bool flag2 = (conVarFlags & ConVarFlags.ExecuteOnServer) != 0;
if (!NetworkServer.active && flag2)
{
ForwardCmdToServer(new ConCommandArgs
{
sender = sender.networkUser,
commandName = concommandName,
userArgs = userArgs
});
return;
}
if (flag && (conVarFlags & ConVarFlags.SenderMustBeServer) != 0)
{
Debug.LogFormat("Blocked server-only command {0} from remote user {1}.", concommandName, sender.networkUser.userName);
return;
}
if (flag && !flag2)
{
Debug.LogFormat("Blocked non-transmittable command {0} from remote user {1}.", concommandName, sender.networkUser.userName);
return;
}
if ((conVarFlags & ConVarFlags.Cheat) != 0 && !CheatsConVar.instance.boolValue)
{
Debug.LogFormat("Command \"{0}\" cannot be used while cheats are disabled.", concommandName);
return;
}
if (value != null)
{
try
{
value.action(new ConCommandArgs
{
sender = sender.networkUser,
localUserSender = sender.localUser,
commandName = concommandName,
userArgs = userArgs
});
return;
}
catch (ConCommandException ex)
{
Debug.LogFormat("Command \"{0}\" failed: {1}", concommandName, ex.Message);
return;
}
}
if (baseConVar != null)
{
if (userArgs.Count > 0)
{
baseConVar.AttemptSetString(userArgs[0]);
return;
}
Debug.LogFormat("\"{0}\" = \"{1}\"\n{2}", concommandName, baseConVar.GetString(), baseConVar.helpText);
}
}
[DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[DllImport("kernel32.dll")]
private static extern bool FreeConsole();
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int processId);
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
private static string ReadInputStream()
{
if (stdInQueue.Count > 0)
{
return stdInQueue.Dequeue();
}
return null;
}
private static void ThreadedInputQueue()
{
string item;
while (systemConsoleType != 0 && (item = System.Console.ReadLine()) != null)
{
stdInQueue.Enqueue(item);
}
}
private static void SetupSystemConsole()
{
bool flag = false;
bool flag2 = false;
string[] commandLineArgs = Environment.GetCommandLineArgs();
for (int i = 0; i < commandLineArgs.Length; i++)
{
if (commandLineArgs[i] == "-console")
{
flag = flag || true;
}
if (commandLineArgs[i] == "-console_detach")
{
flag2 = flag2 || true;
}
}
if (flag)
{
systemConsoleType = SystemConsoleType.Attach;
if (flag2)
{
systemConsoleType = SystemConsoleType.Alloc;
}
}
switch (systemConsoleType)
{
case SystemConsoleType.Attach:
AttachConsole(-1);
break;
case SystemConsoleType.Alloc:
AllocConsole();
break;
}
if (systemConsoleType != 0)
{
System.Console.SetIn(new StreamReader(System.Console.OpenStandardInput()));
stdInReaderThread = new Thread(ThreadedInputQueue);
stdInReaderThread.Start();
}
}
private void Awake()
{
instance = this;
loadingIsComplete = false;
StartCoroutine(AwakeCoroutine());
}
private IEnumerator AwakeCoroutine()
{
SetupSystemConsole();
yield return InitConVarsCoroutine();
List<HG.Reflection.SearchableAttribute> instances = HG.Reflection.SearchableAttribute.GetInstances<ConCommandAttribute>();
int currentPass = 0;
foreach (ConCommandAttribute item in instances)
{
concommandCatalog[item.commandName.ToLower(CultureInfo.InvariantCulture)] = new ConCommand
{
flags = item.flags,
action = (ConCommandDelegate)Delegate.CreateDelegate(typeof(ConCommandDelegate), item.target as MethodInfo),
helpText = item.helpText
};
currentPass++;
if (currentPass >= maxPassesBeforeYielding)
{
currentPass = 0;
yield return null;
}
}
string[] commandLineArgs = Environment.GetCommandLineArgs();
StringBuilder stringBuilder = HG.StringBuilderPool.RentStringBuilder();
stringBuilder.AppendLine("Launch Parameters: ");
for (int i = 0; i < commandLineArgs.Length; i++)
{
stringBuilder.Append(" arg[").AppendInt(i).Append("]=\"")
.Append(commandLineArgs[i])
.Append("\"")
.AppendLine();
}
HG.StringBuilderPool.ReturnStringBuilder(stringBuilder);
MPEventSystemManager.availability.CallWhenAvailable(LoadStartupConfigs);
loadingIsComplete = true;
}
private void LoadStartupConfigs()
{
try
{
SubmitCmd(null, "exec config");
SubmitCmd(null, "exec autoexec");
}
catch (Exception message)
{
Debug.LogError(message);
}
}
private void Update()
{
string cmd;
while ((cmd = ReadInputStream()) != null)
{
SubmitCmd(null, cmd, recordSubmit: true);
}
}
private void OnDestroy()
{
if (stdInReaderThread != null)
{
stdInReaderThread = null;
}
if (systemConsoleType != 0)
{
systemConsoleType = SystemConsoleType.None;
IntPtr consoleWindow = GetConsoleWindow();
if (consoleWindow != IntPtr.Zero)
{
PostMessage(consoleWindow, 256u, 13, 0);
}
if (stdInReaderThread != null)
{
stdInReaderThread.Join();
stdInReaderThread = null;
}
FreeConsole();
}
}
private static string LoadConfig(string fileName)
{
string text = sharedStringBuilder.Clear().Append("/Config/").Append(fileName)
.Append(".cfg")
.ToString();
try
{
return PlatformSystems.textDataManager.GetConfFile(fileName, text);
}
catch (IOException ex)
{
Debug.LogFormat("Could not load config {0}: {1}", text, ex.Message);
}
return null;
}
public void SaveArchiveConVars()
{
using MemoryStream memoryStream = new MemoryStream();
using TextWriter textWriter = new StreamWriter(memoryStream, Encoding.UTF8);
for (int i = 0; i < archiveConVars.Count; i++)
{
BaseConVar baseConVar = archiveConVars[i];
textWriter.Write(baseConVar.name);
textWriter.Write(" ");
textWriter.Write(baseConVar.GetString());
textWriter.Write(";\r\n");
}
textWriter.Write("echo \"Loaded archived convars.\";");
textWriter.Flush();
RoR2Application.fileSystem.CreateDirectory("/Config/");
try
{
using Stream stream = RoR2Application.fileSystem.OpenFile("/Config/config.cfg", FileMode.Create, FileAccess.Write);
if (stream != null)
{
stream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
stream.Close();
}
}
catch (IOException ex)
{
Debug.LogFormat("Failed to write archived convars: {0}", ex.Message);
}
}
[ConCommand(commandName = "set_vstr", flags = ConVarFlags.None, helpText = "Sets the specified vstr to the specified value.")]
private static void CCSetVstr(ConCommandArgs args)
{
args.CheckArgumentCount(2);
instance.vstrs.Add(args[0], args[1]);
}
[ConCommand(commandName = "exec", flags = ConVarFlags.None, helpText = "Executes a named config from the \"Config/\" folder.")]
private static void CCExec(ConCommandArgs args)
{
if (args.Count > 0)
{
string text = LoadConfig(args[0]);
if (text != null)
{
instance.SubmitCmd(args.sender, text);
}
}
}
[ConCommand(commandName = "echo", flags = ConVarFlags.None, helpText = "Echoes the given text to the console.")]
private static void CCEcho(ConCommandArgs args)
{
if (args.Count <= 0)
{
ShowHelpText(args.commandName);
}
}
[ConCommand(commandName = "cvarlist", flags = ConVarFlags.None, helpText = "Print all available convars and concommands.")]
private static void CCCvarList(ConCommandArgs args)
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, BaseConVar> allConVar in instance.allConVars)
{
list.Add(allConVar.Key);
}
foreach (KeyValuePair<string, ConCommand> item in instance.concommandCatalog)
{
list.Add(item.Key);
}
list.Sort();
}
[ConCommand(commandName = "help", flags = ConVarFlags.None, helpText = "Show help text for the named convar or concommand.")]
private static void CCHelp(ConCommandArgs args)
{
if (args.Count == 0)
{
instance.SubmitCmd(args.sender, "find \"*\"");
}
else
{
ShowHelpText(args[0]);
}
}
[ConCommand(commandName = "find", flags = ConVarFlags.None, helpText = "Find all concommands and convars with the specified substring.")]
private static void CCFind(ConCommandArgs args)
{
if (args.Count == 0)
{
ShowHelpText("find");
}
else
{
Find(args[0].ToLower(CultureInfo.InvariantCulture));
}
}
private static string Find(string searchString)
{
bool flag = searchString == "*";
List<string> list = new List<string>();
foreach (KeyValuePair<string, BaseConVar> allConVar in instance.allConVars)
{
if (flag || allConVar.Key.ToLower(CultureInfo.InvariantCulture).Contains(searchString) || allConVar.Value.helpText.ToLower(CultureInfo.InvariantCulture).Contains(searchString))
{
list.Add(allConVar.Key);
}
}
foreach (KeyValuePair<string, ConCommand> item in instance.concommandCatalog)
{
if (flag || item.Key.ToLower(CultureInfo.InvariantCulture).Contains(searchString) || item.Value.helpText.ToLower(CultureInfo.InvariantCulture).Contains(searchString))
{
list.Add(item.Key);
}
}
list.Sort();
string[] array = new string[list.Count];
for (int i = 0; i < list.Count; i++)
{
array[i] = GetHelpText(list[i]);
}
return string.Join("\n", array);
}
[ConCommand(commandName = "clear", flags = ConVarFlags.None, helpText = "Clears the console output.")]
private static void CCClear(ConCommandArgs args)
{
logs.Clear();
Console.onClear?.Invoke();
}
private static string GetHelpText(string commandName)
{
if (instance.concommandCatalog.TryGetValue(commandName, out var value))
{
return string.Format(CultureInfo.InvariantCulture, "<color=#FF7F7F>\"{0}\"</color>\n- {1}", commandName, value.helpText);
}
BaseConVar baseConVar = instance.FindConVar(commandName);
if (baseConVar != null)
{
return string.Format(CultureInfo.InvariantCulture, "<color=#FF7F7F>\"{0}\" = \"{1}\"</color>\n - {2}", commandName, baseConVar.GetString(), baseConVar.helpText);
}
return Find(commandName) + "\nExact Match not found. Use `find \"" + commandName + "\" instead";
}
public static void ShowHelpText(string commandName)
{
}
}