When a MU client sends text to the game’s telnet port, several things happen:
Command
object.Command
object is added to the Dispatcher’s dispatch queue.on_command
in the handler and then stop asking other plugins if they want the command.Table of Contents
If a plugin wants to handle and event, it must implement the get_cmd_handler
method in its plugin module. This method is given a command object and and can return either nil (if the plugin doesn’t want the event) or an event handler class (if it does).
Most plugins have a case statement based on the root command, and ten a second case statement based on the switch. For example:
module AresMUSH
module Events
def self.get_cmd_handler(client, cmd, enactor)
case cmd.root
when "event"
case cmd.switch
when nil
if (cmd.args)
return EventDetailCmd
else
return EventsCmd
end
when "create"
return EventCreateCmd
...
end
nil
end
end
end
If you want to extend or override commands, you can do so by modifying the command handler in the Custom plugin. Commands are given to Custom before any other plugin, giving you the opportunity to inject a custom command handler. For example, here we have overridden the “note” command with our own, and added a new switch to the “event” command.
module AresMUSH
module Custom
def self.get_cmd_handler(client, cmd, enactor)
case cmd.root
when "note"
return MyCustomNoteCmd
when "event"
case cmd.switch
when "limit"
return MyNewEventLimitCmd
else
return nil
end
end
nil
end
end
end
The Command
class embodies a player’s typed command. Commands are interpreted based on a standard format:
[prefix]root[page][/switch] [args]
All components except the root are optional, so valid commands might include:
input | prefix | root | page | switch | args |
---|---|---|---|---|---|
mail Faraday=Subj/Msg | Faraday=Subj/Msg | ||||
help2 | help | 2 | |||
bbs/new | bbs | new | |||
+ch Hiya. | + | ch | Hiya. | ||
+bbs/post 1=Subj/Msg | + | bbs | post | 1=Subj/Msg |
The Command
class provides easy access to these components through methods like cmd.root
and cmd.args
.
In all the tutorials thus far, we’ve never talked about on_command
- it’s always been parse_args
and handle
and things like that. That’s because all Ares commands use the CommandHandler
class.
CommandHandler
defines the on_command
method for you, and breaks it up into steps with their own individual methods:
It also provides useful utilities like variables for enactor
and enactor_room
and the Arg Parsers.
To utilize the CommandHandler
functionality, just include it in your command class and implement a handle
method. The rest of the methods are optional:
module AresMUSH
module Mail
class MailSendCmd
include CommandHandler
def handle
...
end
end
end
end
By default, Ares logs all non-sensitive commands. This aids in troubleshooting and also is a security safeguard to track who did what.
For sensitive commands, you can disable logging in your command handler just by overriding the log method. For example, the mail command just logs the fact that you sent mail - it doesn’t log the contents of the message.
class MailSendCmd
...
def log_command
# Don't log full command for message privacy
Global.logger.debug("#{self.class.name} #{client} sending mail.")
end
end
The page command logs nothing at all:
class PageCmd
...
def log_command
# Don't log pages
end
end
The parse_args
method is the place where you can parse the command string into its individual args. See Arg Parsers for more information.
attr_accessor :num
def parse_args
self.num = integer_arg(cmd.args)
end
Error checkers allow you to detect errors before you begin handling the command. They run after argument parsing but before the handle
method. There are several built-in error checkers that you’ll see used throughout the Ares code, and you can make your own just by giving the method a name starting with check_
. For example:
def check_can_view
return nil if enactor.has_permission("view_bgs")
return "You don't have permission to view that."
end
See Error Checkers for more information.
The handle
method is where the ‘guts’ of your command go. 99% of handle methods will end with an emit to the client.
def handle
# Do something, then...
client.emit_success "Done!"
end
Don’t forget that you can emit in multiple ways depending on the type of message. See emits.