using Common.Utils; using System.Reflection; using PemukulPaku.GameServer.Game; namespace PemukulPaku.GameServer.Commands { /// /// What methods should be overriden based on CommandType: /// All, Handler should override all virtual methods in Command. /// Console, Handler should override Run method with string[] args. /// Player, Handler should override Run method with Player / Session args. /// When making non console command please call the Run overload with Player from Session overload. /// public abstract class Command { public static readonly Logger c = new("Command", ConsoleColor.Cyan, false); public string Name = string.Empty; public string Description = string.Empty; public string[] Examples = Array.Empty(); public CommandType CmdType = CommandType.Player; /// /// Call this when player is online or have active session. /// /// The Session instance /// public virtual void Run(Session session, string[] args) { throw new NotImplementedException(); } /// /// Only call this when player have no session. /// /// The Player instance /// public virtual void Run(Player player, string[] args) { throw new NotImplementedException(); } /// /// Please only call this on ReadLine. /// /// public virtual void Run(string[] args) { throw new NotImplementedException(); } } /// /// Command types used to defines what action should be taken by command interpreter or handler. /// public enum CommandType { All, Console, Player }; [AttributeUsage(AttributeTargets.Class)] public class CommandHandler : Attribute { public string Name { get; } public string Description { get; } public string[] Examples { get; } public CommandType CmdType { get; } public CommandHandler(string name, string description, CommandType type = CommandType.Player, params string[] examples) { Name = name; Description = description; CmdType = type; Examples = examples; } } public static class CommandFactory { public static readonly List Commands = new(); static readonly Logger c = new("Factory", ConsoleColor.Yellow); public static void LoadCommandHandlers() { c.Log("Loading Command Handlers..."); IEnumerable classes = from t in Assembly.GetExecutingAssembly().GetTypes() select t; foreach ((Type t, CommandHandler attr) in from Type? t in classes.ToList() let attrs = (Attribute[])t.GetCustomAttributes(typeof(CommandHandler), false) where attrs.Length > 0 let attr = (CommandHandler)attrs[0] select (t, attr)) { Command? cmd = (Command)Activator.CreateInstance(t)!; if (cmd is not null) { cmd.Name = attr.Name; cmd.Description = attr.Description; cmd.CmdType = attr.CmdType; cmd.Examples = attr.Examples; Commands.Add(cmd); #if DEBUG c.Log($"Loaded Command Handler {t.Name} for Command \"{cmd.Name}\""); #endif } } c.Log("Finished loading Commands"); } } }