mirror of
https://github.com/evennia/evennia.git
synced 2026-04-05 07:27:17 +02:00
Added the capability of evennia commands to consist of more than one word. So the examples.red_button parent can now be pressed with the command 'push button' instead of 'pushbutton' as before. The variable COMMAND_MAXLEN in the config defines how many words your commands may maximum contain (don't set it higher than needed for efficiency reasons).
The main drawback of multi-word commands are that they can not have any switches; they are intended for in-game use (in states and on objects). Use normal one-word commands for administration and more complex commands with many options. /Griatch
This commit is contained in:
parent
0c29d359f6
commit
a711e07b80
4 changed files with 115 additions and 53 deletions
|
|
@ -104,6 +104,6 @@ def class_factory(source_obj):
|
|||
"""
|
||||
button = RedButton(source_obj)
|
||||
# add the object-based commands to the button
|
||||
button.command_table.add_command("pushbutton", cmd_push_button)
|
||||
button.command_table.add_command("pullbutton", cmd_pull_button)
|
||||
button.command_table.add_command("push button", cmd_push_button)
|
||||
button.command_table.add_command("pull button", cmd_pull_button)
|
||||
return button
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ This is the command processing module. It is instanced once in the main
|
|||
server module and the handle() function is hit every time a player sends
|
||||
something.
|
||||
"""
|
||||
import time
|
||||
#import time
|
||||
from traceback import format_exc
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
import defines_global
|
||||
import cmdtable
|
||||
|
|
@ -13,6 +14,8 @@ import logger
|
|||
import comsys
|
||||
import alias_mgr
|
||||
|
||||
COMMAND_MAXLEN = settings.COMMAND_MAXLEN
|
||||
|
||||
class UnknownCommand(Exception):
|
||||
"""
|
||||
Throw this when a user enters an an invalid command.
|
||||
|
|
@ -47,6 +50,8 @@ class Command(object):
|
|||
command_switches = []
|
||||
# The un-parsed argument provided. IE: if input is "look dog", this is "dog".
|
||||
command_argument = None
|
||||
# list of tuples for possible multi-space commands and their arguments
|
||||
command_alternatives = None
|
||||
# A reference to the command function looked up in a command table.
|
||||
command_function = None
|
||||
# An optional dictionary that is passed through the command table as extra_vars.
|
||||
|
|
@ -66,45 +71,63 @@ class Command(object):
|
|||
Breaks the command up into the main command string, a list of switches,
|
||||
and a string containing the argument provided with the command. More
|
||||
specific processing is left up to the individual command functions.
|
||||
"""
|
||||
try:
|
||||
"""
|
||||
Break the command in half into command and argument. If the
|
||||
command string can't be parsed, it has no argument and is
|
||||
handled by the except ValueError block below.
|
||||
"""
|
||||
# Lop off the return at the end.
|
||||
self.raw_input = self.raw_input.strip('\r')
|
||||
# Break the command up into the root command and its arguments.
|
||||
(self.command_string, self.command_argument) = self.raw_input.split(' ', 1)
|
||||
# Yank off trailing and leading spaces.
|
||||
self.command_argument = self.command_argument.strip()
|
||||
self.command_string = self.command_string.strip()
|
||||
"""
|
||||
This is a really important behavior to note. If the user enters
|
||||
anything other than a string with some character in it, the value
|
||||
of the argument is None, not an empty string.
|
||||
"""
|
||||
if self.command_string == '':
|
||||
self.command_string = None
|
||||
if self.command_argument == '':
|
||||
self.command_argument = None
|
||||
|
||||
if self.command_string == None:
|
||||
"""
|
||||
This prevents any bad stuff from happening as a result of
|
||||
trying to further parse a None object.
|
||||
"""
|
||||
return
|
||||
except ValueError:
|
||||
"""
|
||||
No arguments. IE: look, who.
|
||||
"""
|
||||
self.command_string = self.raw_input
|
||||
|
||||
# Parse command_string for switches, regardless of what happens.
|
||||
self.parse_command_switches()
|
||||
|
||||
The command can come in two forms:
|
||||
command/switches arg
|
||||
command_with_spaces arg
|
||||
|
||||
The first form is the normal one, used for administration and other commands
|
||||
that benefit from the use of switches and options. The drawback is that it
|
||||
can only consist of one single word (no spaces).
|
||||
The second form, which does not accept switches, allows for longer command
|
||||
names (e.g. 'press button' instead of pressbutton) and is mainly useful for
|
||||
object-based commands for roleplay, puzzles etc.
|
||||
"""
|
||||
if not self.raw_input:
|
||||
return
|
||||
|
||||
# add a space after the raw input; this cause split() to always
|
||||
# create a list with at least two entries.
|
||||
raw = "%s " % self.raw_input
|
||||
cmd_words = raw.split()
|
||||
try:
|
||||
if '/' in cmd_words[0]:
|
||||
# if we have switches we directly go for the first command form.
|
||||
command_string, command_argument = \
|
||||
(inp.strip() for inp in raw.split(' ', 1))
|
||||
if command_argument:
|
||||
self.command_argument = command_argument
|
||||
if command_string:
|
||||
# we have a valid command, store and parse switches.
|
||||
self.command_string = command_string
|
||||
self.parse_command_switches()
|
||||
else:
|
||||
# no switches - we need to save a list of all possible command
|
||||
# names up to the max-length allowed.
|
||||
command_maxlen = min(COMMAND_MAXLEN, len(cmd_words))
|
||||
command_alternatives = []
|
||||
for spacecount in reversed(range(command_maxlen)):
|
||||
# store all space-separated possible command names
|
||||
# as tuples (commandname, args). They are stored with
|
||||
# the longest possible name first.
|
||||
try:
|
||||
command_alternatives.append( (" ".join(cmd_words[:spacecount+1]),
|
||||
" ".join(cmd_words[spacecount+1:])) )
|
||||
except IndexError:
|
||||
continue
|
||||
if command_alternatives:
|
||||
# store alternatives. Store the one-word command
|
||||
# as the default command name.
|
||||
one_word_command = command_alternatives.pop()
|
||||
self.command_string = one_word_command[0]
|
||||
self.command_argument = one_word_command[1]
|
||||
self.command_alternatives = command_alternatives
|
||||
except IndexError:
|
||||
# this SHOULD only happen if raw_input is malformed
|
||||
# (like containing only control characters).
|
||||
pass
|
||||
|
||||
|
||||
def __init__(self, source_object, raw_input, session=None):
|
||||
"""
|
||||
Instantiates the Command object and does some preliminary parsing.
|
||||
|
|
@ -179,6 +202,16 @@ def match_alias(command):
|
|||
command.command_string = alias_mgr.CMD_ALIAS_LIST.get(
|
||||
command.command_string,
|
||||
command.command_string)
|
||||
# Run aliasing on alternative command names (for commands with
|
||||
# spaces in them)
|
||||
if command.command_alternatives:
|
||||
command_alternatives = []
|
||||
for command_alternative in command.command_alternatives:
|
||||
command_alternatives.append( (alias_mgr.CMD_ALIAS_LIST.get(
|
||||
command_alternative[0],
|
||||
command_alternative[0]),
|
||||
command_alternative[1]) )
|
||||
command.command_alternatives = command_alternatives
|
||||
|
||||
def get_aliased_message():
|
||||
"""
|
||||
|
|
@ -201,7 +234,6 @@ def match_alias(command):
|
|||
elif first_char == ':':
|
||||
command.command_argument = get_aliased_message()
|
||||
command.command_string = "pose"
|
||||
# command.command_string = "emote"
|
||||
# Pose without space alias.
|
||||
elif first_char == ';':
|
||||
command.command_argument = get_aliased_message()
|
||||
|
|
@ -298,13 +330,35 @@ def command_table_lookup(command, command_table, eval_perms=True,
|
|||
evaluates the permissions tuple.
|
||||
The test flag only checks without manipulating the command
|
||||
neighbor (object) If this is supplied, we are looking at a object table and
|
||||
must check for locks.
|
||||
must check for locks.
|
||||
|
||||
In the case of one-word commands with switches, this is a
|
||||
quick look-up. For non-switch commands the command might
|
||||
however consist of several words separated by spaces up to
|
||||
a certain max number of words. We don't know beforehand if one
|
||||
of these match an entry in this particular command table. We search
|
||||
them in order longest to shortest before deferring to the normal,
|
||||
one-word assumption.
|
||||
"""
|
||||
# Get the command's function reference (Or False)
|
||||
cmdtuple = command_table.get_command_tuple(command.command_string)
|
||||
cmdtuple = None
|
||||
if command.command_alternatives:
|
||||
# we have command alternatives (due to spaces in command definition)
|
||||
for cmd_alternative in command.command_alternatives:
|
||||
# the alternatives are ordered longest -> shortest.
|
||||
cmdtuple = command_table.get_command_tuple(cmd_alternative[0])
|
||||
if cmdtuple:
|
||||
# we have a match, so this is the 'right' command to use
|
||||
# with this particular command table.
|
||||
command.command_string = cmd_alternative[0]
|
||||
command.command_argument = cmd_alternative[1]
|
||||
if not cmdtuple:
|
||||
# None of the alternatives match, go with the default one-word name
|
||||
cmdtuple = command_table.get_command_tuple(command.command_string)
|
||||
|
||||
if cmdtuple:
|
||||
# Check if this is just a test.
|
||||
# if we get here we have found a command match in the table
|
||||
if test:
|
||||
# Check if this is just a test.
|
||||
return True
|
||||
# Check locks
|
||||
if neighbor and not neighbor.scriptlink.use_lock(command.source_object):
|
||||
|
|
|
|||
|
|
@ -696,10 +696,10 @@ def cmd_setcmdalias(command):
|
|||
@setcmdalias - define shortcuts for commands
|
||||
|
||||
Usage:
|
||||
@setcmdalias[/switch] [command = ] alias
|
||||
@setcmdalias[/switch] alias [= command]
|
||||
|
||||
Switches:
|
||||
list - view all command aliases (default)
|
||||
list - view all command aliases
|
||||
add - add alias
|
||||
del - remove and existing alias
|
||||
|
||||
|
|
@ -713,22 +713,26 @@ def cmd_setcmdalias(command):
|
|||
args = command.command_argument
|
||||
switches = command.command_switches
|
||||
|
||||
if not args or 'list' in switches:
|
||||
if "list" in switches:
|
||||
# show all aliases
|
||||
string = "Command aliases defined:"
|
||||
aliases = CommandAlias.objects.all()
|
||||
if not aliases:
|
||||
string = "No command aliases defined."
|
||||
for alias in aliases:
|
||||
string += "\n %s = %s" % (alias.equiv_command, alias.user_input)
|
||||
string += "\n %s -> %s" % (alias.user_input, alias.equiv_command)
|
||||
source_object.emit_to(string)
|
||||
return
|
||||
|
||||
if not args:
|
||||
source_object.emit_to("Usage: @setcmdalias[/list/add/del] alias [= command]")
|
||||
return
|
||||
|
||||
equiv_command = ""
|
||||
user_input = ""
|
||||
# analyze args
|
||||
if '=' in args:
|
||||
equiv_command, user_input = [arg.strip() for arg in args.split("=",1)]
|
||||
user_input, equiv_command = [arg.strip() for arg in args.split("=",1)]
|
||||
else:
|
||||
user_input = args.strip()
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,14 @@ DATABASE_HOST = ''
|
|||
# Empty string defaults to localhost. Not used with sqlite3.
|
||||
DATABASE_PORT = ''
|
||||
|
||||
# How many words a single command name may have (e.g. 'push button' instead of 'pushbutton')
|
||||
# (commands with switches always accept only one word in the name, e.g. @sethelp/add)
|
||||
COMMAND_MAXLEN = 3
|
||||
|
||||
## Command aliases
|
||||
# These are convenient aliases set up when the game is started
|
||||
# for the very first time. You can add/delete aliases in-game using
|
||||
# the @cmdalias command.
|
||||
# the @setcmdalias command.
|
||||
COMMAND_ALIASES = {"@desc":"@describe",
|
||||
"@dest":"@destroy", "@nuke":"@destroy",
|
||||
"@tel":"@teleport",
|
||||
|
|
@ -78,7 +82,7 @@ COMMAND_ALIASES = {"@desc":"@describe",
|
|||
"ex":"examine",
|
||||
"sa":"say",
|
||||
"emote":"pose",
|
||||
"p":"page" }
|
||||
"p":"page"}
|
||||
|
||||
## Permissions
|
||||
## The variables in this section are used by each evennia subsystem to tell which permissions to define.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue