This commit is contained in:
rfi
2024-02-18 18:08:40 +07:00
5 changed files with 178 additions and 7 deletions

View File

@@ -0,0 +1,105 @@
using BLHX.Server.Common.Utils;
using System.Reflection;
namespace BLHX.Server.Game.Commands;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class commandHandler : Attribute
{
public string Name { get; }
public string Description { get; }
public string Example { get; }
public commandHandler(string commandName, string description, string example)
{
Name = commandName;
Description = description;
Example = example;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class ArgumentAttribute : Attribute
{
public string Key { get; }
public ArgumentAttribute(string key)
{
Key = key;
}
}
public abstract class Command
{
readonly Dictionary<string, PropertyInfo> argsProperties;
public Command()
{
argsProperties = GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => Attribute.IsDefined(x, typeof(ArgumentAttribute)))
.ToDictionary(x => ((ArgumentAttribute)Attribute.GetCustomAttribute(x, typeof(ArgumentAttribute))!).Key, StringComparer.OrdinalIgnoreCase);
}
public virtual void Execute(Dictionary<string, string> args)
{
foreach (var arg in args)
{
if (argsProperties.TryGetValue(arg.Key, out var prop))
prop.SetValue(this, arg.Value);
}
}
}
public static class CommandHandler
{
public static readonly List<Command> Commands = new List<Command>();
static readonly Dictionary<string, Action<Dictionary<string, string>>> commandFunctions;
static CommandHandler()
{
commandFunctions = new Dictionary<string, Action<Dictionary<string, string>>>(StringComparer.OrdinalIgnoreCase);
RegisterCommands(Assembly.GetExecutingAssembly());
}
public static void RegisterCommands(Assembly assembly)
{
var commandTypes = assembly.GetTypes()
.Where(t => Attribute.IsDefined(t, typeof(commandHandler)) && typeof(Command).IsAssignableFrom(t));
foreach (var commandType in commandTypes)
{
var commandAttribute = (commandHandler)Attribute.GetCustomAttribute(commandType, typeof(commandHandler));
if (commandAttribute != null)
{
var commandInstance = (Command)Activator.CreateInstance(commandType);
commandFunctions[commandAttribute.Name] = commandInstance.Execute;
Commands.Add(commandInstance);
}
}
}
public static void HandleCommand(string commandLine)
{
var parts = commandLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
return;
if (!commandFunctions.TryGetValue(parts[0], out var command))
{
Logger.c.Warn($"Unknown command: {parts[0]}");
return;
}
var arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
for (var i = 1; i < parts.Length; i++)
{
var argParts = parts[i].Split('=', 2);
if (argParts.Length == 2)
arguments[argParts[0]] = argParts[1];
}
command(arguments);
}
}

View File

@@ -0,0 +1,32 @@
using System.Reflection;
using System.Text;
namespace BLHX.Server.Game.Commands;
[commandHandler("help", "Print out all commands with their description and example", "help")]
public class HelpCommand : Command
{
static readonly Dictionary<Type, commandHandler?> commandAttributes = new Dictionary<Type, commandHandler?>();
public override void Execute(Dictionary<string, string> args)
{
base.Execute(args);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Available Commands: ");
foreach (var command in CommandHandler.Commands)
{
if (!commandAttributes.TryGetValue(command.GetType(), out var attr))
{
attr = command.GetType().GetCustomAttribute(typeof(commandHandler)) as commandHandler;
commandAttributes[command.GetType()] = attr;
}
if (attr != null)
sb.AppendLine($" {attr.Name} - {attr.Description} (Example: {attr.Example})");
}
Console.Write(sb.ToString());
}
}

View File

@@ -0,0 +1,15 @@
using BLHX.Server.Common.Utils;
namespace BLHX.Server.Game.Commands;
[commandHandler("save", "Save the current state", "save")]
public class SaveCommand : Command
{
public override void Execute(Dictionary<string, string> args)
{
base.Execute(args);
Logger.c.Log("Saving...");
Logger.c.Log("Saved!");
}
}

View File

@@ -0,0 +1,18 @@
using BLHX.Server.Game.Commands;
namespace BLHX.Server.Game;
public static class InputSystem
{
public static void Start()
{
while (true)
{
var command = Console.ReadLine();
if (string.IsNullOrEmpty(command)) continue;
CommandHandler.HandleCommand(command);
}
}
}