public void InitializeHandlers(Action <string, CommandHandlerAttribute> globalCommandRegister) { foreach (var(method, cmdAttr, parserType) in ResolveHandlers()) { // Get a safe command name to take command duplicate situation var safeCommandName = cmdAttr.Command; var cmdIndex = 0; while (commandHandlers.ContainsKey(safeCommandName)) { safeCommandName = $"{safeCommandName}{++cmdIndex}"; } if (cmdIndex > 0) { Logger.LogWarning($"Command {safeCommandName} was duplicated! Rename to '{safeCommandName}'"); } // Add command handlers to dictionary var commandHandlerInfo = new CommandHandlerInfo { CommandHandler = method, IsAwaitable = method.ReturnType.GetMethods().Any((method) => method.Name == "GetAwaiter"), }; // Add parser instance to dictionary // Check parser assignable if (!typeof(IParser).IsAssignableFrom(parserType)) { Logger.LogWarning($"Command handler parser type not implement IParse interface!"); } // Add 'commandHandler' as Parser if (parserType == CommandContainerType) { parsers.Add(parserType, CommandContainer as IParser); } // Create new parser instance in Arrtibute else if (parserType != typeof(DefaultParser) && !parsers.ContainsKey(parserType)) { parsers.Add(parserType, Activator.CreateInstance(parserType) as IParser); } // Associate command and parser commandHandlerInfo.HandlerParserType = parserType; commandHandlers.Add(safeCommandName, commandHandlerInfo); // if command has CommandAlias attribute, register as global command if (method.GetCustomAttribute <CommandAliasAttribute>() is CommandAliasAttribute attr) { globalCommandRegister(attr.Alias, cmdAttr); } } }
/// <inheritdoc /> public Task ExecuteAsync(IServerCommand serverCommand, CancellationToken cancellationToken) { var serverCommandType = serverCommand.GetType(); if (!_serverCommandHandlerInfo.TryGetValue(serverCommandType, out var commandHandlerInfo)) { var handlerType = typeof(IServerCommandHandler <>).MakeGenericType(serverCommandType); var executeAsyncMethod = handlerType.GetRuntimeMethod("ExecuteAsync", new[] { serverCommandType, typeof(CancellationToken) }); var handler = _ftpConnectionAccessor.FtpConnection.ConnectionServices.GetRequiredService(handlerType); commandHandlerInfo = new CommandHandlerInfo(handler, executeAsyncMethod); _serverCommandHandlerInfo.Add(serverCommandType, commandHandlerInfo); } return((Task)commandHandlerInfo.ExecuteMethodInfo.Invoke( commandHandlerInfo.CommandHandler, new object[] { serverCommand, cancellationToken })); }
public static void Handle(ClientMessage clientMessage, Session session) { var message = clientMessage.Payload.ReadString16L(); if (message.StartsWith("@")) { string commandRaw = message.Remove(0, 1); CommandHandlerResponse response = CommandHandlerResponse.InvalidCommand; CommandHandlerInfo commandHandler = null; string command = null; string[] parameters = null; try { CommandManager.ParseCommand(message.Remove(0, 1), out command, out parameters); } catch (Exception ex) { log.Error($"Exception while parsing command: {commandRaw}", ex); return; } try { response = CommandManager.GetCommandHandler(session, command, parameters, out commandHandler); } catch (Exception ex) { log.Error($"Exception while getting command handler for: {commandRaw}", ex); } if (response == CommandHandlerResponse.Ok) { try { if (commandHandler.Attribute.IncludeRaw) { parameters = CommandManager.StuffRawIntoParameters(message.Remove(0, 1), command, parameters); } ((CommandHandler)commandHandler.Handler).Invoke(session, parameters); } catch (Exception ex) { log.Error($"Exception while invoking command handler for: {commandRaw}", ex); } } else if (response == CommandHandlerResponse.SudoOk) { string[] sudoParameters = new string[parameters.Length - 1]; for (int i = 1; i < parameters.Length; i++) { sudoParameters[i - 1] = parameters[i]; } try { if (commandHandler.Attribute.IncludeRaw) { parameters = CommandManager.StuffRawIntoParameters(message.Remove(0, 1), command, parameters); } ((CommandHandler)commandHandler.Handler).Invoke(session, sudoParameters); } catch (Exception ex) { log.Error($"Exception while invoking command handler for: {commandRaw}", ex); } } else { switch (response) { case CommandHandlerResponse.InvalidCommand: session.Network.EnqueueSend(new GameMessageSystemChat($"Unknown command: {command}", ChatMessageType.Help)); break; case CommandHandlerResponse.InvalidParameterCount: session.Network.EnqueueSend(new GameMessageSystemChat($"Invalid parameter count, got {parameters.Length}, expected {commandHandler.Attribute.ParameterCount}!", ChatMessageType.Help)); session.Network.EnqueueSend(new GameMessageSystemChat($"@{commandHandler.Attribute.Command} - {commandHandler.Attribute.Description}", ChatMessageType.Broadcast)); session.Network.EnqueueSend(new GameMessageSystemChat($"Usage: @{commandHandler.Attribute.Command} {commandHandler.Attribute.Usage}", ChatMessageType.Broadcast)); break; default: break; } } } else { // We only want to handle @commands, thank you very much! // session.Player.HandleActionTalk(message); } }