using System.Net.Sockets; using System.Reflection; using System.Text.Json; using DX86; namespace Server; public class CommandManager { private readonly Dictionary _commands = new(); public CommandManager() { LoadCommands(); } private void LoadCommands() { var methods = Assembly.GetExecutingAssembly() .GetTypes() .SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Static)) .Where(m => m.GetCustomAttribute() != null); foreach (var method in methods) { var attr = method.GetCustomAttribute()!; _commands[attr.Name.ToLower()] = method; Program.messageSender.Log($"[COMMANDMANAGER] Registered command: {attr.Name}"); } } public void ExecuteCommand(string executor, TcpClient? client = null, TcpServer? clientSocket = null, string cid = "", params string[] args) { // — ensure args is never null — args ??= Array.Empty(); if (_commands.TryGetValue(executor.ToLower(), out var method)) { try { var parameters = method.GetParameters(); var arguments = new object?[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { var param = parameters[i]; if (param.ParameterType == typeof(string[])) arguments[i] = args; else if (param.ParameterType == typeof(TcpClient)) arguments[i] = client; else if (param.ParameterType == typeof(TcpServer)) arguments[i] = clientSocket; else { Program.messageSender.Warn( $"[COMMANDMANAGER] Unknown parameter type '{param.ParameterType.Name}' in '{executor}'. Defaulting that argument to null." ); arguments[i] = null; } } Program.messageSender.Debug($"[COMMANDMANAGER] Executing command '{executor}'…"); var rawResult = method.Invoke(null, arguments); // invoke the static command method string result = rawResult?.ToString() ?? ""; // **Log the returned string before sending** Program.messageSender.Debug($"[COMMANDMANAGER] Command '{executor}' returned: \"{result}\""); var returnMessage = new Library.Server.JsonResponse { Id = cid, Response = result }; var sendClientMessage = JsonSerializer.Serialize(returnMessage); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); Program.messageSender.Debug($"[COMMANDMANAGER] Response sent to client."); } // If your command threw a CommandException, catch it here: catch (TargetInvocationException ex) when (ex.InnerException is CommandException cmdEx) { Program.messageSender.Warn($"[COMMANDMANAGER] Command '{executor}' failed: {cmdEx.Message}"); var returnMessage = new Library.Server.JsonResponse { Id = cid, Response = $"Error: {cmdEx.Message}" }; var sendClientMessage = JsonSerializer.Serialize(returnMessage); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); } // Any other exception inside the invoked method catch (TargetInvocationException ex) { var actualError = ex.InnerException?.Message ?? ex.Message; Program.messageSender.Error( $"[COMMANDMANAGER] Unexpected error in command '{executor}': {actualError}" ); Program.messageSender.Debug( $"[COMMANDMANAGER] Stack Trace: {ex.InnerException?.StackTrace ?? ex.StackTrace}" ); } // Anything else thrown before or during Invoke() catch (Exception ex) { Program.messageSender.Error($"[COMMANDMANAGER] Failed to invoke command '{executor}': {ex.Message}"); } } else { Program.messageSender.Warn($"[COMMANDMANAGER] Unknown command '{executor}' received."); } } }