230 lines
7.1 KiB
C#
230 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using RebootKit.Engine.Foundation;
|
|
using UnityEngine;
|
|
using Logger = RebootKit.Engine.Foundation.Logger;
|
|
|
|
namespace RebootKit.Engine.Services.Console {
|
|
public interface IConsoleCommand {
|
|
string Name { get; }
|
|
string Description { get; }
|
|
void Execute(string[] args);
|
|
}
|
|
|
|
public class HelpCommand : IConsoleCommand {
|
|
public string Name { get; } = "help";
|
|
public string Description { get; } = "Prints available commands/cvars and their descriptions.";
|
|
|
|
public void Execute(string[] args) {
|
|
RR.Console.PrintHelp();
|
|
}
|
|
}
|
|
|
|
public class PrintCVarsCommand : IConsoleCommand {
|
|
public string Name { get; } = "print_cvars";
|
|
public string Description { get; } = "Prints all cvars and their values.";
|
|
|
|
public void Execute(string[] args) {
|
|
RR.Console.PrintCVars();
|
|
}
|
|
}
|
|
|
|
public class ConsoleService : IService {
|
|
static readonly Logger s_logger = new(nameof(ConsoleService));
|
|
|
|
readonly List<IConsoleCommand> m_ConsoleCommands = new();
|
|
|
|
FileStream m_LogFileStream;
|
|
TextWriter m_LogFileWriter;
|
|
|
|
bool m_IsLoading;
|
|
|
|
public ConsoleService() {
|
|
ConfigVar.StateChanged += OnCVarStateChanged;
|
|
|
|
m_LogFileStream = new FileStream(Application.persistentDataPath + "/rr_logs.txt", FileMode.Append, FileAccess.Write);
|
|
m_LogFileWriter = new StreamWriter(m_LogFileStream);
|
|
|
|
m_LogFileWriter.WriteLine("============================");
|
|
m_LogFileWriter.WriteLine("Starting new log");
|
|
m_LogFileWriter.WriteLine($" > Game: {Application.productName}");
|
|
m_LogFileWriter.WriteLine($" > Version: {Application.version}");
|
|
m_LogFileWriter.WriteLine($" > Date: {DateTime.Now}");
|
|
m_LogFileWriter.WriteLine("============================");
|
|
m_LogFileWriter.Flush();
|
|
|
|
s_logger.Info("Waking up");
|
|
|
|
Load();
|
|
|
|
RegisterCommand(new PrintCVarsCommand());
|
|
RegisterCommand(new HelpCommand());
|
|
}
|
|
|
|
public void Dispose() {
|
|
s_logger.Info("Shutting down");
|
|
|
|
ConfigVar.StateChanged -= OnCVarStateChanged;
|
|
|
|
m_LogFileWriter.Dispose();
|
|
m_LogFileStream.Dispose();
|
|
|
|
m_LogFileStream = null;
|
|
m_LogFileWriter = null;
|
|
}
|
|
|
|
void OnCVarStateChanged(ConfigVar cvar) {
|
|
if (m_IsLoading) {
|
|
return;
|
|
}
|
|
|
|
if (!cvar.flags.HasFlag(CVarFlags.ReadOnly)) {
|
|
Save();
|
|
}
|
|
}
|
|
|
|
public event Action<string> OnOutputMessage = _ => { };
|
|
|
|
public void WriteToOutput(string message) {
|
|
if (m_LogFileWriter != null) {
|
|
m_LogFileWriter.WriteLine(message);
|
|
m_LogFileWriter.Flush();
|
|
}
|
|
|
|
OnOutputMessage?.Invoke(message);
|
|
}
|
|
|
|
string[] ParseCommandInputArguments(string text) {
|
|
if (text.Length == 0) {
|
|
return Array.Empty<string>();
|
|
}
|
|
|
|
return new[] {text};
|
|
}
|
|
|
|
public void Execute(string input) {
|
|
if (input.Length == 0) {
|
|
return;
|
|
}
|
|
|
|
string commandName = input;
|
|
if (input.IndexOf(' ') != -1) {
|
|
commandName = input.Substring(0, input.IndexOf(' '));
|
|
}
|
|
|
|
string[] arguments = ParseCommandInputArguments(input.Substring(commandName.Length));
|
|
|
|
foreach (IConsoleCommand command in m_ConsoleCommands) {
|
|
if (command.Name.Equals(commandName)) {
|
|
command.Execute(arguments);
|
|
return;
|
|
}
|
|
}
|
|
|
|
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
|
if (cvar.name.Equals(commandName)) {
|
|
if (arguments.Length == 1) {
|
|
cvar.ParseFromString(arguments[0]);
|
|
}
|
|
|
|
WriteToOutput($"<b>{cvar.name}</b> - {cvar}\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
WriteToOutput($"ERROR: Command/CVar `{commandName}` not found.");
|
|
}
|
|
|
|
public void RegisterCommand(IConsoleCommand command) {
|
|
if (m_ConsoleCommands.Any(t => t.Name.Equals(command.Name))) {
|
|
s_logger.Error($"`{command.Name}` command is already registered");
|
|
return;
|
|
}
|
|
|
|
m_ConsoleCommands.Add(command);
|
|
s_logger.Info($"Registered command: {command.Name}");
|
|
}
|
|
|
|
public void PrintHelp() {
|
|
StringBuilder message = new();
|
|
|
|
message.AppendLine("Available commands:");
|
|
foreach (IConsoleCommand command in m_ConsoleCommands) {
|
|
message.Append(" ");
|
|
message.Append(command.Name);
|
|
message.Append(" - ");
|
|
message.Append(command.Description);
|
|
message.AppendLine();
|
|
}
|
|
|
|
message.AppendLine("Available cvars:");
|
|
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
|
message.Append(" ");
|
|
message.Append(cvar.name);
|
|
message.Append(" - ");
|
|
message.Append(cvar.description);
|
|
message.AppendLine();
|
|
}
|
|
|
|
WriteToOutput(message.ToString());
|
|
}
|
|
|
|
public void PrintCVars() {
|
|
StringBuilder message = new();
|
|
|
|
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
|
message.AppendLine($"{cvar.name} - {cvar}");
|
|
}
|
|
|
|
WriteToOutput(message.ToString());
|
|
}
|
|
|
|
void Save() {
|
|
string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename;
|
|
|
|
s_logger.Info("Saving cvars to file: " + path);
|
|
|
|
StringBuilder sb = new();
|
|
|
|
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
|
if (!cvar.flags.HasFlag(CVarFlags.ReadOnly)) {
|
|
sb.AppendFormat("{0} {1}\n", cvar.name, cvar);
|
|
}
|
|
}
|
|
|
|
File.WriteAllText(path, sb.ToString());
|
|
}
|
|
|
|
void Load() {
|
|
string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename;
|
|
if (!File.Exists(path)) {
|
|
s_logger.Info("CVar file not found, skipping load");
|
|
return;
|
|
}
|
|
|
|
m_IsLoading = true;
|
|
ExecuteFile(path);
|
|
m_IsLoading = false;
|
|
}
|
|
|
|
bool ExecuteFile(string path) {
|
|
if (!File.Exists(path)) {
|
|
s_logger.Error($"Cannot load file '{path}', file not found");
|
|
return false;
|
|
}
|
|
|
|
s_logger.Info($"Executing file '{path}'");
|
|
|
|
string[] lines = File.ReadAllLines(path);
|
|
foreach (string line in lines) {
|
|
WriteToOutput(path + " > " + line);
|
|
Execute(line);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
} |