working on multiplayer
This commit is contained in:
291
Runtime/Engine/Code/Console/ConsoleService.cs
Normal file
291
Runtime/Engine/Code/Console/ConsoleService.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Main;
|
||||
using UnityEngine;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class RCCMD : Attribute {
|
||||
public string name;
|
||||
public string description;
|
||||
|
||||
public RCCMD(string name, string description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsoleService : IService {
|
||||
static readonly Logger s_logger = new Logger(nameof(ConsoleService));
|
||||
|
||||
public struct ConsoleCommand {
|
||||
public string name;
|
||||
public string description;
|
||||
public Action<string[]> action;
|
||||
}
|
||||
|
||||
readonly List<ConsoleCommand> m_ConsoleCommands = new List<ConsoleCommand>();
|
||||
|
||||
FileStream m_LogFileStream;
|
||||
TextWriter m_LogFileWriter;
|
||||
|
||||
bool m_IsLoading;
|
||||
|
||||
public ConsoleService() {
|
||||
ConfigVar.StateChanged += OnCVarStateChanged;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string logFilePath = Application.persistentDataPath + "/rr_logs_editor.txt";
|
||||
#else
|
||||
string logFilePath = Application.persistentDataPath + "/rr_logs.txt";
|
||||
#endif
|
||||
|
||||
m_LogFileStream = new FileStream(logFilePath, 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();
|
||||
|
||||
RegisterCommands();
|
||||
}
|
||||
|
||||
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[] ParseCommandInput(string text) {
|
||||
return text.Split(' ');
|
||||
}
|
||||
|
||||
// @NOTE: Input must be in format: "command arg1 arg2 arg3", one command = one call
|
||||
public void Execute(string input) {
|
||||
if (input.Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
string[] arguments = ParseCommandInput(input);
|
||||
if (arguments.Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
string commandName = arguments[0];
|
||||
|
||||
foreach (ConsoleCommand command in m_ConsoleCommands) {
|
||||
if (command.name.Equals(commandName)) {
|
||||
command.action(arguments);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
||||
if (cvar.name.Equals(commandName)) {
|
||||
if (arguments.Length == 2) {
|
||||
cvar.ParseFromString(arguments[1]);
|
||||
}
|
||||
|
||||
WriteToOutput($"<b>{cvar.name}</b> - {cvar}\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WriteToOutput($"ERROR: Command/CVar `{commandName}` not found.");
|
||||
}
|
||||
|
||||
public void RegisterCommand(string name, string description, Action<string[]> action) {
|
||||
if (IsCommandRegistered(name)) {
|
||||
s_logger.Error($"`{name}` command is already registered");
|
||||
return;
|
||||
}
|
||||
|
||||
m_ConsoleCommands.Add(new ConsoleCommand {
|
||||
name = name,
|
||||
description = description,
|
||||
action = action
|
||||
});
|
||||
s_logger.Info($"Registered command: {name}");
|
||||
}
|
||||
|
||||
public static ConsoleCommand[] GenerateCommandsToRegister() {
|
||||
IEnumerable<MethodInfo> methods = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.SelectMany(type => type.GetMethods(BindingFlags.NonPublic |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.Static))
|
||||
.Where(method => method.GetCustomAttributes(typeof(RCCMD), false)
|
||||
.Length >
|
||||
0);
|
||||
|
||||
List<ConsoleCommand> commands = new List<ConsoleCommand>();
|
||||
foreach (MethodInfo method in methods) {
|
||||
RCCMD attribute = (RCCMD) method.GetCustomAttributes(typeof(RCCMD), false)[0];
|
||||
|
||||
if (!method.IsStatic) {
|
||||
s_logger.Error($"Command `{attribute.name}` is not static, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.GetParameters().Length != 1) {
|
||||
s_logger.Error($"Command `{attribute.name}` has invalid number of parameters, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.GetParameters()[0].ParameterType != typeof(string[])) {
|
||||
s_logger.Error($"Command `{attribute.name}` has invalid parameter type, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
Action<string[]> action = (Action<string[]>) Delegate.CreateDelegate(typeof(Action<string[]>), method);
|
||||
|
||||
commands.Add(new ConsoleCommand {
|
||||
name = attribute.name,
|
||||
description = attribute.description,
|
||||
action = action
|
||||
});
|
||||
}
|
||||
|
||||
return commands.ToArray();
|
||||
}
|
||||
|
||||
public void RegisterCommands() {
|
||||
ConsoleCommand[] commands = GenerateCommandsToRegister();
|
||||
foreach (ConsoleCommand command in commands) {
|
||||
RegisterCommand(command.name, command.description, command.action);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCommandRegistered(string name) {
|
||||
foreach (ConsoleCommand command in m_ConsoleCommands) {
|
||||
if (command.name.Equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[RCCMD("help", "Prints help message with all commands and cvars")]
|
||||
public static void PrintHelpCommand(string[] args) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
|
||||
message.AppendLine("Available commands:");
|
||||
foreach (ConsoleCommand command in RR.Console.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();
|
||||
}
|
||||
|
||||
RR.Console.WriteToOutput(message.ToString());
|
||||
}
|
||||
|
||||
[RCCMD("cvars", "Prints all cvars")]
|
||||
public static void PrintCVars(string[] args) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
|
||||
foreach (ConfigVar cvar in ConfigVarsContainer.All()) {
|
||||
message.AppendLine($"{cvar.name} - {cvar}");
|
||||
}
|
||||
|
||||
RR.Console.WriteToOutput(message.ToString());
|
||||
}
|
||||
|
||||
void Save() {
|
||||
string path = Application.persistentDataPath + "/" + RConsts.k_CVarsFilename;
|
||||
|
||||
s_logger.Info("Saving cvars to file: " + path);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Console/ConsoleService.cs.meta
Normal file
3
Runtime/Engine/Code/Console/ConsoleService.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b841238f225048e88d8d8d89cfeafaa7
|
||||
timeCreated: 1740884588
|
||||
15
Runtime/Engine/Code/Console/ConsoleServiceAsset.cs
Normal file
15
Runtime/Engine/Code/Console/ConsoleServiceAsset.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using UnityEngine;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[CreateAssetMenu(menuName = RConsts.k_ServiceAssetMenu + "Console")]
|
||||
public class ConsoleServiceAsset : ServiceAsset<ConsoleService> {
|
||||
static readonly Logger s_logger = new Logger(nameof(ConsoleServiceAsset));
|
||||
|
||||
public override ConsoleService Create() {
|
||||
ConsoleService service = new ConsoleService();
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/Engine/Code/Console/ConsoleServiceAsset.cs.meta
Normal file
2
Runtime/Engine/Code/Console/ConsoleServiceAsset.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 577b018c25510774aaccba06137e264d
|
||||
Reference in New Issue
Block a user