Looking through our command code after a long hiatus, I realized that it was pretty much awful. So here's part 1 of the command interpreter overhaul.

- The command handler has been drastically simplified. We were doing way too much processing in the handler that should have been done in the individual command functions themselves.
- The 'cdat' dict we were previously passing around has been replaced with a Command object that has useful methods for performing some of the parsing command functions will probably want to do from time to time.
- All commands were updated to use the new Command object, tested, and cleaned up in general.
- A lot of formatting was cleaned up.
- A lot of previously un-found bugs and limitations were fixed.
- The 'page' command has been broken out into its own file, since it's going to have a number of functions that would otherwise clutter commands/general.py.

Expect a commit (probably later today) that will clean up the second half of cmdhandler.py.
This commit is contained in:
Greg Taylor 2008-12-14 20:21:02 +00:00
parent 37d66093cc
commit d58f4eb517
16 changed files with 818 additions and 698 deletions

View file

@ -75,9 +75,11 @@ class ObjectManager(models.Manager):
else:
o_query = self.filter(name__icontains=ostring)
return o_query.exclude(type=defines_global.OTYPE_GARBAGE)
return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE,
defines_global.OTYPE_GOING])
def list_search_object_namestr(self, searchlist, ostring, dbref_only=False, limit_types=False, match_type="fuzzy"):
def list_search_object_namestr(self, searchlist, ostring, dbref_only=False,
limit_types=False, match_type="fuzzy"):
"""
Iterates through a list of objects and returns a list of
name matches.
@ -98,7 +100,9 @@ class ObjectManager(models.Manager):
return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)]
def standard_plr_objsearch(self, session, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
def standard_plr_objsearch(self, session, ostring, search_contents=True,
search_location=True, dbref_only=False,
limit_types=False):
"""
Perform a standard object search via a player session, handling multiple
results and lack thereof gracefully.
@ -107,7 +111,11 @@ class ObjectManager(models.Manager):
ostring: (str) The string to match object names against.
"""
pobject = session.get_pobject()
results = self.local_and_global_search(pobject, ostring, search_contents=search_contents, search_location=search_location, dbref_only=dbref_only, limit_types=limit_types)
results = self.local_and_global_search(pobject, ostring,
search_contents=search_contents,
search_location=search_location,
dbref_only=dbref_only,
limit_types=limit_types)
if len(results) > 1:
session.msg("More than one match found (please narrow target):")
@ -136,14 +144,14 @@ class ObjectManager(models.Manager):
def player_alias_search(self, searcher, ostring):
"""
Search players by alias. Returns a list of objects whose "ALIAS" attribute
exactly (not case-sensitive) matches ostring.
Search players by alias. Returns a list of objects whose "ALIAS"
attribute exactly (not case-sensitive) matches ostring.
searcher: (Object) The object doing the searching.
ostring: (string) The alias string to search for.
"""
search_query = ''.join(ostring)
Attribute = ContentType.objects.get(app_label="objects", model="attribute").get_model()
Attribute = ContentType.objects.get(app_label="objects",
model="attribute").model_class()
results = Attribute.objects.select_related().filter(attr_name__exact="ALIAS").filter(attr_value__iexact=ostring)
return [prospect.get_object() for prospect in results if prospect.get_object().is_player()]
@ -171,11 +179,17 @@ class ObjectManager(models.Manager):
except IndexError:
return None
def is_dbref(self, dbstring):
"""
Is the input a well-formed dbref number?
"""
util_object.is_dbref(dbstring)
def dbref_search(self, dbref_string, limit_types=False):
"""
Searches for a given dbref.
dbref_number: (string) The dbref to search for
dbref_number: (string) The dbref to search for. With # sign.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
if not util_object.is_dbref(dbref_string):
@ -192,7 +206,9 @@ class ObjectManager(models.Manager):
except IndexError:
return None
def local_and_global_search(self, searcher, ostring, search_contents=True, search_location=True, dbref_only=False, limit_types=False):
def local_and_global_search(self, searcher, ostring, search_contents=True,
search_location=True, dbref_only=False,
limit_types=False):
"""
Searches an object's location then globally for a dbref or name match.
@ -203,14 +219,13 @@ class ObjectManager(models.Manager):
dbref_only: (bool) Only compare dbrefs.
limit_types: (list of int) A list of Object type numbers to filter by.
"""
search_query = ''.join(ostring)
search_query = ostring
# This is a global dbref search. Not applicable if we're only searching
# searcher's contents/locations, dbref comparisons for location/contents
# searches are handled by list_search_object_namestr() below.
if util_object.is_dbref(ostring):
search_num = search_query[1:]
dbref_match = dbref_search(search_num, limit_types)
dbref_match = self.dbref_search(search_query, limit_types)
if dbref_match is not None:
return [dbref_match]
@ -224,7 +239,7 @@ class ObjectManager(models.Manager):
if search_query[0] == "*":
# Player search- gotta search by name or alias
search_target = search_query[1:]
player_match = player_name_search(search_target)
player_match = self.player_name_search(search_target)
if player_match is not None:
return [player_match]
@ -232,9 +247,11 @@ class ObjectManager(models.Manager):
# Handle our location/contents searches. list_search_object_namestr() does
# name and dbref comparisons against search_query.
if search_contents:
local_matches += list_search_object_namestr(searcher.get_contents(), search_query, limit_types)
local_matches += self.list_search_object_namestr(searcher.get_contents(),
search_query, limit_types)
if search_location:
local_matches += list_search_object_namestr(searcher.get_location().get_contents(), search_query, limit_types=limit_types)
local_matches += self.list_search_object_namestr(searcher.get_location().get_contents(),
search_query, limit_types=limit_types)
return local_matches
def get_user_from_email(self, uemail):
@ -264,7 +281,9 @@ class ObjectManager(models.Manager):
* home: Reference to another object to home to. If not specified, use
location key for home.
"""
next_dbref = get_nextfree_dbnum()
next_dbref = self.get_nextfree_dbnum()
Object = ContentType.objects.get(app_label="objects",
model="object").model_class()
new_object = Object()
new_object.id = next_dbref
@ -301,27 +320,25 @@ class ObjectManager(models.Manager):
return new_object
def create_user(self, cdat, uname, email, password):
def create_user(self, command, uname, email, password):
"""
Handles the creation of new users.
"""
session = cdat['session']
server = cdat['server']
session = command.session
server = command.server
start_room = int(ConfigValue.objects.get_configvalue('player_dbnum_start'))
start_room_obj = get_object_from_dbref(start_room)
start_room_obj = self.get_object_from_dbref(start_room)
# The user's entry in the User table must match up to an object
# on the object table. The id's are the same, we need to figure out
# the next free unique ID to use and make sure the two entries are
# the same number.
uid = get_nextfree_dbnum()
print 'UID', uid
uid = self.get_nextfree_dbnum()
# If this is an object, we know to recycle it since it's garbage. We'll
# pluck the user ID from it.
if not str(uid).isdigit():
uid = uid.id
print 'UID2', uid
user = User.objects.create_user(uname, email, password)
# It stinks to have to do this but it's the only trivial way now.
@ -337,8 +354,12 @@ class ObjectManager(models.Manager):
user = User.objects.get(id=uid)
# Create a player object of the same ID in the Objects table.
odat = {"id": uid, "name": uname, "type": 1, "location": start_room_obj, "owner": None}
user_object = create_object(odat)
odat = {"id": uid,
"name": uname,
"type": 1,
"location": start_room_obj,
"owner": None}
user_object = self.create_object(odat)
# Activate the player's session and set them loose.
session.login(user)

View file

@ -413,7 +413,8 @@ class Object(models.Model):
uobj.is_active = False
uobj.save()
except:
functions_general.log_errmsg('Destroying object %s but no matching player.' % (self,))
functions_general.log_errmsg('Destroying object %s but no matching player.'
% (self,))
# Set the object type to GOING
self.type = 5
@ -490,7 +491,7 @@ class Object(models.Model):
obj.emit_to("You seem to have found a place that does not exist.")
# If home is still None, it goes to a null location.
obj.move_to(home, True)
obj.move_to(home)
obj.save()
def set_attribute(self, attribute, new_value):
@ -538,7 +539,8 @@ class Object(models.Model):
attrs = Attribute.objects.filter(attr_object=self)
# Compile a regular expression that is converted from the user's
# wild-carded search string.
match_exp = re.compile(functions_general.wildcard_to_regexp(searchstr), re.IGNORECASE)
match_exp = re.compile(functions_general.wildcard_to_regexp(searchstr),
re.IGNORECASE)
# If the regular expression search returns a match object, add to results.
if exclude_noset:
return [attr for attr in attrs if match_exp.search(attr.get_name()) and not attr.is_hidden() and not attr.is_noset()]
@ -707,22 +709,34 @@ class Object(models.Model):
except:
return None
def move_to(self, target, quiet=False):
def move_to(self, target, quiet=False, force_look=True):
"""
Moves the object to a new location.
target: (Object) Reference to the object to move to.
quiet: (bool) If true, don't emit left/arrived messages.
force_look: (bool) If true and target is a player, make them 'look'.
"""
if not quiet:
if self.get_location():
self.get_location().emit_to_contents("%s has left." % (self.get_name(),), exclude=self)
location = self.get_location()
if location:
location.emit_to_contents("%s has left." %
(self.get_name(),), exclude=self)
if location.is_player():
location.emit_to("%s has left your inventory." %
(self.get_name()))
self.location = target
self.save()
if not quiet:
self.get_location().emit_to_contents("%s has arrived." % (self.get_name(),), exclude=self)
arrival_message = "%s has arrived." % (self.get_name())
self.get_location().emit_to_contents(arrival_message, exclude=self)
if self.location.is_player():
self.location.emit_to("%s is now in your inventory." % (self.get_name()))
if force_look and self.is_player():
self.get_session().execute_cmd('look')
def dbref_match(self, oname):
"""
@ -750,7 +764,7 @@ class Object(models.Model):
NOTE: A 'name' can be a dbref or the actual name of the object. See
dbref_match for an exclusively name-based match.
"""
if oname[0] == '#':
if util_object.is_dbref(oname):
# First character is a pound sign, looks to be a dbref.
return self.dbref_match(oname)
elif match_type == "exact":

View file

@ -10,6 +10,8 @@ def is_dbref(dbstring):
number = int(dbstring[1:])
except ValueError:
return False
except TypeError:
return False
if not dbstring.startswith("#"):
return False

View file

@ -17,89 +17,104 @@ class UnknownCommand(Exception):
"""
Throw this when a user enters an an invalid command.
"""
pass
class Command(object):
# Reference to the master server object.
server = None
# The player session that the command originated from.
session = None
# The entire raw, un-parsed command.
raw_input = None
# Just the root command. IE: if input is "look dog", this is just "look".
command_string = None
# A list of switches in the form of strings.
command_switches = []
# The un-parsed argument provided. IE: if input is "look dog", this is "dog".
command_argument = None
def parse_command_switches(self):
"""
Splits any switches out of a command_string into the command_switches
list, and yanks the switches out of the original command_string.
"""
splitted_command = self.command_string.split('/')
self.command_switches = splitted_command[1:]
self.command_string = splitted_command[0]
def parse_command(self):
"""
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.
"""
(self.command_string, self.command_argument) = self.raw_input.split(' ', 1)
self.command_argument = self.command_argument.strip()
if self.command_argument == '':
self.command_argument = None
except ValueError:
"""
No arguments. IE: look, who.
"""
self.command_string = self.raw_input
finally:
# Parse command_string for switches, regardless of what happens.
self.parse_command_switches()
def __init__(self, raw_input, server=None, session=None):
self.server = server
self.raw_input = raw_input
self.session = session
self.parse_command()
def arg_has_target(self):
"""
Returns true if the argument looks to be target-style. IE:
page blah=hi
kick ball=north
"""
return "=" in self.command_argument
def get_arg_targets(self, delim=','):
"""
Returns a list of targets from the argument. These happen before
the '=' sign and may be separated by a delimiter.
"""
# Make sure we even have a target (= sign).
if not self.arg_has_target():
return None
target = self.command_argument.split('=', 1)[0]
return [targ.strip() for targ in target.split(delim)]
def get_arg_target_value(self):
"""
In a case of something like: page bob=Hello there, the target is "bob",
while the value is "Hello there". This function returns the portion
of the command that takes place after the first equal sign.
"""
# Make sure we even have a target (= sign).
if not self.arg_has_target():
return None
return self.command_argument.split('=', 1)[1]
def match_exits(pobject, searchstr):
"""
See if we can find an input match to exits.
"""
exits = pobject.get_location().get_contents(filter_type=4)
return Object.objects.list_search_object_namestr(exits, searchstr, match_type="exact")
exits = pobject.get_location().get_contents(filter_type=defines_global.OTYPE_EXIT)
return Object.objects.list_search_object_namestr(exits,
searchstr,
match_type="exact")
def parse_command(command_string):
"""
Tries to handle the most common command strings and returns a dictionary with various data.
Common command types:
- Complex:
@pemit[/option] <target>[/option]=<data>
- Simple:
look
look <target>
I'm not married to either of these terms, but I couldn't think of anything
better. If you can, lets change it :)
The only cases that I haven't handled is if someone enters something like:
@pemit <target> <target>/<switch>=<data>
- Ends up considering both targets as one with a space between them,
and the switch as a switch.
@pemit <target>/<switch> <target>=<data>
- Ends up considering the first target a target, and the second
target as part of the switch.
"""
# Each of the bits of data starts off as None, except for the raw, original
# command
parsed_command = dict(
raw_command=command_string,
data=None,
original_command=None,
original_targets=None,
base_command=None,
command_switches=None,
targets=None,
target_switches=None
)
try:
# If we make it past this next statement, then this is what we
# consider a complex command
(command_parts, data) = command_string.split('=', 1)
parsed_command['data'] = data
# First we deal with the command part of the command and break it
# down into the base command, along with switches
# If we make it past the next statement, then they must have
# entered a command like:
# p =<data>
# So we should probably just let it get caught by the ValueError
# again and consider it a simple command
(total_command, total_targets) = command_parts.split(' ', 1)
parsed_command['original_command'] = total_command
parsed_command['original_targets'] = total_targets
split_command = total_command.split('/')
parsed_command['base_command'] = split_command[0]
parsed_command['command_switches'] = split_command[1:]
# Now we move onto the target data
try:
# Look for switches- if they give target switches, then we don't
# accept multiple targets
(target, switch_string) = total_targets.split('/', 1)
parsed_command['targets'] = [target]
parsed_command['target_switches'] = switch_string.split('/')
except ValueError:
# Alright, no switches, so lets consider multiple targets
parsed_command['targets'] = total_targets.split()
except ValueError:
# Ok, couldn't find an =, so not a complex command
try:
(command, data) = command_string.split(' ', 1)
parsed_command['base_command'] = command
parsed_command['data'] = data
except ValueError:
# No arguments
# ie:
# - look
parsed_command['base_command'] = command_string
return parsed_command
def handle(cdat):
def handle(command):
"""
Use the spliced (list) uinput variable to retrieve the correct
command, or return an invalid command error.
@ -108,32 +123,22 @@ def handle(cdat):
their input on to 'cmd_' and looking it up in the GenCommands
class.
"""
session = cdat['session']
server = cdat['server']
session = command.session
server = command.server
try:
# TODO: Protect against non-standard characters.
if cdat['uinput'] == '':
if command.raw_input == '':
# Nothing sent in of value, ignore it.
return
parsed_input = {}
parsed_input['parsed_command'] = parse_command(cdat['uinput'])
# First we split the input up by spaces.
parsed_input['splitted'] = cdat['uinput'].split()
# Now we find the root command chunk (with switches attached).
parsed_input['root_chunk'] = parsed_input['splitted'][0].split('/')
# And now for the actual root command. It's the first entry in root_chunk.
parsed_input['root_cmd'] = parsed_input['root_chunk'][0].lower()
# Keep around the full, raw input in case a command needs it
cdat['raw_input'] = cdat['uinput']
# Now we'll see if the user is using an alias. We do a dictionary lookup,
# if the key (the player's root command) doesn't exist on the dict, we
# don't replace the existing root_cmd. If the key exists, its value
# replaces the previously splitted root_cmd. For example, sa -> say.
alias_list = server.cmd_alias_list
parsed_input['root_cmd'] = alias_list.get(parsed_input['root_cmd'],parsed_input['root_cmd'])
# if the key (the player's command_string) doesn't exist on the dict,
# just keep the command_string the same. If the key exists, its value
# replaces the command_string. For example, sa -> say.
command.command_string = server.cmd_alias_list.get(
command.command_string,
command.command_string)
# This will hold the reference to the command's function.
cmd = None
@ -143,7 +148,7 @@ def handle(cdat):
session.cmd_last = time.time()
# Lets the users get around badly configured NAT timeouts.
if parsed_input['root_cmd'] == 'idle':
if command.command_string == 'idle':
return
# Increment our user's command counter.
@ -152,55 +157,34 @@ def handle(cdat):
session.cmd_last_visible = time.time()
# Just in case. Prevents some really funky-case crashes.
if len(parsed_input['root_cmd']) == 0:
if len(command.command_string) == 0:
raise UnknownCommand
# Shortened say alias.
if parsed_input['root_cmd'][0] == '"':
parsed_input['splitted'].insert(0, "say")
parsed_input['splitted'][1] = parsed_input['splitted'][1][1:]
parsed_input['root_cmd'] = 'say'
# Shortened pose alias.
elif parsed_input['root_cmd'][0] == ':':
parsed_input['splitted'].insert(0, "pose")
parsed_input['splitted'][1] = parsed_input['splitted'][1][1:]
parsed_input['root_cmd'] = 'pose'
# Pose without space alias.
elif parsed_input['root_cmd'][0] == ';':
parsed_input['splitted'].insert(0, "pose/nospace")
parsed_input['root_chunk'] = ['pose', 'nospace']
parsed_input['splitted'][1] = parsed_input['splitted'][1][1:]
parsed_input['root_cmd'] = 'pose'
# Channel alias match.
elif comsys.plr_has_channel(session,
parsed_input['root_cmd'],
alias_search=True,
return_muted=True):
if comsys.plr_has_channel(session, command.command_string,
alias_search=True, return_muted=True):
calias = parsed_input['root_cmd']
calias = command.command_string
cname = comsys.plr_cname_from_alias(session, calias)
cmessage = ' '.join(parsed_input['splitted'][1:])
if cmessage == "who":
if command.command_argument == "who":
comsys.msg_cwho(session, cname)
return
elif cmessage == "on":
elif command.command_argument == "on":
comsys.plr_chan_on(session, calias)
return
elif cmessage == "off":
elif command.command_argument == "off":
comsys.plr_chan_off(session, calias)
return
elif cmessage == "last":
elif command.command_argument == "last":
comsys.msg_chan_hist(session, cname)
return
second_arg = "%s=%s" % (cname, cmessage)
parsed_input['splitted'] = ["@cemit/sendername", second_arg]
parsed_input['root_chunk'] = ['@cemit', 'sendername', 'quiet']
parsed_input['root_cmd'] = '@cemit'
second_arg = "%s=%s" % (cname, command.command_argument)
command.command_string = "@cemit"
command.command_switches = ["sendername", "quiet"]
# Get the command's function reference (Or False)
cmdtuple = cmdtable.GLOBAL_CMD_TABLE.get_command_tuple(parsed_input['root_cmd'])
cmdtuple = cmdtable.GLOBAL_CMD_TABLE.get_command_tuple(command.command_string)
if cmdtuple:
# If there is a permissions element to the entry, check perms.
if cmdtuple[1]:
@ -212,7 +196,7 @@ def handle(cdat):
else:
# Not logged in, look through the unlogged-in command table.
cmdtuple = cmdtable.GLOBAL_UNCON_CMD_TABLE.get_command_tuple(parsed_input['root_cmd'])
cmdtuple = cmdtable.GLOBAL_UNCON_CMD_TABLE.get_command_tuple(command.command_string)
if cmdtuple:
cmd = cmdtuple[0]
@ -221,9 +205,8 @@ def handle(cdat):
#session.msg("SPLIT: %s" % (parsed_input['splitted'],))
if callable(cmd):
cdat['uinput'] = parsed_input
try:
cmd(cdat)
cmd(command)
except:
session.msg("Untrapped error, please file a bug report:\n%s" % (format_exc(),))
logger.log_errmsg("Untrapped error, evoker %s: %s" %
@ -233,12 +216,10 @@ def handle(cdat):
if session.logged_in:
# If we're not logged in, don't check exits.
pobject = session.get_pobject()
exit_matches = match_exits(pobject, ' '.join(parsed_input['splitted']))
exit_matches = match_exits(pobject, command.command_string)
if exit_matches:
targ_exit = exit_matches[0]
if targ_exit.get_home():
cdat['uinput'] = parsed_input
if targ_exit.get_home():
# SCRIPT: See if the player can traverse the exit
if not targ_exit.scriptlink.default_lock({
"pobject": pobject

View file

@ -10,6 +10,7 @@ privilege checking in the command function), use None in place of the
permissions tuple.
"""
import commands.general
import commands.paging
import commands.privileged
import commands.comsys
import commands.unloggedin
@ -54,7 +55,7 @@ GLOBAL_CMD_TABLE.add_command("help", commands.general.cmd_help),
GLOBAL_CMD_TABLE.add_command("idle", commands.general.cmd_idle),
GLOBAL_CMD_TABLE.add_command("inventory", commands.general.cmd_inventory),
GLOBAL_CMD_TABLE.add_command("look", commands.general.cmd_look),
GLOBAL_CMD_TABLE.add_command("page", commands.general.cmd_page),
GLOBAL_CMD_TABLE.add_command("page", commands.paging.cmd_page),
GLOBAL_CMD_TABLE.add_command("pose", commands.general.cmd_pose),
GLOBAL_CMD_TABLE.add_command("quit", commands.general.cmd_quit),
GLOBAL_CMD_TABLE.add_command("say", commands.general.cmd_say),
@ -80,7 +81,7 @@ GLOBAL_CMD_TABLE.add_command("@dig", commands.objmanip.cmd_dig,
priv_tuple=("genperms.builder")),
GLOBAL_CMD_TABLE.add_command("@emit", commands.general.cmd_emit,
priv_tuple=("genperms.announce")),
#GLOBAL_CMD_TABLE.add_command("@pemit", commands.general.cmd_pemit, None),
#GLOBAL_CMD_TABLE.add_command("@pemit", commands.general.cmd_pemit),
GLOBAL_CMD_TABLE.add_command("@find", commands.objmanip.cmd_find,
priv_tuple=("genperms.builder")),
GLOBAL_CMD_TABLE.add_command("@link", commands.objmanip.cmd_link,

View file

@ -11,32 +11,26 @@ from src import defines_global
from src import ansi
from src.util import functions_general
def cmd_addcom(cdat):
def cmd_addcom(command):
"""
addcom
Adds an alias for a channel.
addcom foo=Bar
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
server = command.server
eq_args = command.command_argument.split('=', 1)
if len(args) == 0:
if not command.command_argument:
session.msg("You need to specify a channel alias and name.")
return
eq_args = args[0].split('=')
if len(eq_args) < 2:
session.msg("You need to specify a channel name.")
return
chan_alias = eq_args[0]
chan_name = eq_args[1]
if len(chan_name) == 0:
if len(eq_args) < 2 or len(chan_name) == 0:
session.msg("You need to specify a channel name.")
return
@ -59,40 +53,38 @@ def cmd_addcom(cdat):
else:
session.msg("Could not find channel %s." % (chan_name,))
def cmd_delcom(cdat):
def cmd_delcom(command):
"""
delcom
Removes the specified alias to a channel. If this is the last alias,
the user is effectively removed from the channel.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
uinput= cdat['uinput']['splitted']
chan_alias = ' '.join(uinput[1:])
if len(chan_alias) == 0:
if len(command.command_argument) == 0:
session.msg("You must specify a channel alias.")
return
if chan_alias not in session.channels_subscribed:
if command.command_argument not in session.channels_subscribed:
session.msg("You are not on that channel.")
return
chan_name = session.channels_subscribed[chan_alias][0]
chan_name = session.channels_subscribed[command.command_argument][0]
session.msg("You have left %s." % (chan_name,))
src.comsys.plr_del_channel(session, chan_alias)
src.comsys.plr_del_channel(session, command.command_argument)
# Announce the user's leaving.
leave_msg = "[%s] %s has left the channel." % \
(chan_name, pobject.get_name(show_dbref=False))
src.comsys.send_cmessage(chan_name, leave_msg)
def cmd_comlist(cdat):
def cmd_comlist(command):
"""
Lists the channels a user is subscribed to.
"""
session = cdat['session']
session = command.session
session.msg("Alias Channel Status")
for chan in session.channels_subscribed:
@ -105,46 +97,48 @@ def cmd_comlist(cdat):
(chan, session.channels_subscribed[chan][0], chan_on))
session.msg("-- End of comlist --")
def cmd_allcom(cdat):
def cmd_allcom(command):
"""
allcom
Allows the user to universally turn off or on all channels they are on,
as well as perform a "who" for all channels they are on.
"""
# TODO: Implement cmd_allcom
pass
def cmd_clearcom(cdat):
def cmd_clearcom(command):
"""
clearcom
Effectively runs delcom on all channels the user is on. It will remove their aliases,
remove them from the channel, and clear any titles they have set.
"""
# TODO: Implement cmd_clearcom
pass
def cmd_clist(cdat):
def cmd_clist(command):
"""
@clist
Lists all available channels on the game.
"""
session = cdat['session']
session = command.session
session.msg("** Channel Owner Description")
for chan in src.comsys.get_all_channels():
session.msg("%s%s %-13.13s %-15.15s %-45.45s" %
('-', '-', chan.get_name(), chan.get_owner().get_name(), 'No Description'))
('-', '-', chan.get_name(), chan.get_owner().get_name(),
'No Description'))
session.msg("-- End of Channel List --")
def cmd_cdestroy(cdat):
def cmd_cdestroy(command):
"""
@cdestroy
Destroys a channel.
"""
session = cdat['session']
uinput= cdat['uinput']['splitted']
cname = ' '.join(uinput[1:])
session = command.session
cname = command.command_argument
if cname == '':
session.msg("You must supply a name!")
@ -158,56 +152,56 @@ def cmd_cdestroy(cdat):
session.msg("Channel %s destroyed." % (name_matches[0],))
name_matches.delete()
def cmd_cset(cdat):
def cmd_cset(command):
"""
@cset
Sets various flags on a channel.
"""
# TODO: Implement cmd_cset
pass
def cmd_ccharge(cdat):
def cmd_ccharge(command):
"""
@ccharge
Sets the cost to transmit over a channel. Default is free.
"""
# TODO: Implement cmd_ccharge
pass
def cmd_cboot(cdat):
def cmd_cboot(command):
"""
@cboot
Kicks a player or object from the channel.
"""
# TODO: Implement cmd_cboot
pass
def cmd_cemit(cdat):
def cmd_cemit(command):
"""
@cemit
@cemit/noheader <message>
@cemit/sendername <message>
@cemit <channel>=<message>
@cemit/noheader <channel>=<message>
@cemit/sendername <channel>=<message>
Allows the user to send a message over a channel as long as
they own or control it. It does not show the user's name unless they
provide the /sendername switch.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
switches = cdat['uinput']['root_chunk'][1:]
server = command.server
if len(args) == 0:
if command.command_argument == 0:
session.msg("Channel emit what?")
return
# Combine the arguments into one string, split it by equal signs into
# channel (entry 0 in the list), and message (entry 1 and above).
eq_args = ' '.join(args).split('=')
eq_args = command.command_argument.split('=', 1)
cname = eq_args[0]
cmessage = ' '.join(eq_args[1:])
cmessage = eq_args[1]
if len(eq_args) != 2:
session.msg("You must provide a channel name and a message to emit.")
return
@ -219,36 +213,37 @@ def cmd_cemit(cdat):
return
name_matches = src.comsys.cname_search(cname, exact=True)
try:
# Safety first, kids!
if name_matches:
cname_parsed = name_matches[0].get_name()
except:
else:
session.msg("Could not find channel %s." % (cname,))
return
if "noheader" in switches:
if "noheader" in command.command_switches:
if not pobject.user_has_perm("objects.emit_commchannel"):
session.msg(defines_global.NOPERMS_MSG)
return
final_cmessage = cmessage
else:
if "sendername" in switches:
if not src.comsys.plr_has_channel(session, cname_parsed, return_muted=False):
if "sendername" in command.command_switches:
if not src.comsys.plr_has_channel(session, cname_parsed,
return_muted=False):
session.msg("You must be on %s to do that." % (cname_parsed,))
return
final_cmessage = "[%s] %s: %s" % (cname_parsed, pobject.get_name(show_dbref=False), cmessage)
final_cmessage = "[%s] %s: %s" % (cname_parsed,
pobject.get_name(show_dbref=False),
cmessage)
else:
if not pobject.user_has_perm("objects.emit_commchannel"):
session.msg(defines_global.NOPERMS_MSG)
return
final_cmessage = "[%s] %s" % (cname_parsed, cmessage)
if not "quiet" in switches:
if not "quiet" in command.command_switches:
session.msg("Sent - %s" % (name_matches[0],))
src.comsys.send_cmessage(cname_parsed, final_cmessage)
def cmd_cwho(cdat):
def cmd_cwho(command):
"""
@cwho
@ -256,22 +251,24 @@ def cmd_cwho(cdat):
Adding /all after the channel name will list disconnected players
as well.
"""
# TODO: Implement cmd_cwho
pass
def cmd_ccreate(cdat):
def cmd_ccreate(command):
"""
@ccreate
Creates a new channel with the invoker being the default owner.
"""
session = cdat['session']
# TODO: Implement cmd_ccreate
session = command.session
pobject = session.get_pobject()
uinput= cdat['uinput']['splitted']
cname = ' '.join(uinput[1:])
if cname == '':
if not command.command_argument:
session.msg("You must supply a name!")
return
cname = command.command_argument
name_matches = src.comsys.cname_search(cname, exact=True)
@ -279,14 +276,14 @@ def cmd_ccreate(cdat):
session.msg("A channel with that name already exists.")
else:
# Create and set the object up.
cdat = {"name": cname, "owner": pobject}
new_chan = src.comsys.create_channel(cdat)
new_chan = src.comsys.create_channel(cname, pobject)
session.msg("Channel %s created." % (new_chan.get_name(),))
def cmd_cchown(cdat):
def cmd_cchown(command):
"""
@cchown
Changes the owner of a channel.
"""
# TODO: Implement cmd_cchown.
pass

View file

@ -14,18 +14,22 @@ from src import session_mgr
from src import ansi
from src.util import functions_general
def cmd_password(cdat):
def cmd_password(command):
"""
Changes your own password.
@newpass <Oldpass>=<Newpass>
@password <Oldpass>=<Newpass>
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
eq_args = ' '.join(args).split('=')
oldpass = ''.join(eq_args[0])
newpass = ''.join(eq_args[1:])
eq_args = command.command_argument.split('=', 1)
if len(eq_args) != 2:
session.msg("Incorrect number of arguments.")
return
oldpass = eq_args[0]
newpass = eq_args[1]
if len(oldpass) == 0:
session.msg("You must provide your old password.")
@ -44,47 +48,52 @@ def cmd_password(cdat):
uaccount.save()
session.msg("Password changed.")
def cmd_emit(cdat):
def cmd_pemit(command):
"""
Emits something to a player.
"""
# TODO: Implement cmd_pemit
def cmd_emit(command):
"""
Emits something to your location.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
uinput= cdat['uinput']['splitted']
message = ' '.join(uinput[1:])
message = command.command_argument
if message == '':
session.msg("Emit what?")
else:
if message:
pobject.get_location().emit_to_contents(message)
else:
session.msg("Emit what?")
def cmd_wall(cdat):
def cmd_wall(command):
"""
Announces a message to all connected players.
"""
session = cdat['session']
wallstring = ' '.join(cdat['uinput']['splitted'][1:])
session = command.session
wallstring = command.command_argument
pobject = session.get_pobject()
if wallstring == '':
if not wallstring:
session.msg("Announce what?")
return
message = "%s shouts \"%s\"" % (session.get_pobject().get_name(show_dbref=False), wallstring)
session_mgr.announce_all(message)
def cmd_idle(cdat):
def cmd_idle(command):
"""
Returns nothing, this lets the player set an idle timer without spamming
his screen.
"""
pass
def cmd_inventory(cdat):
def cmd_inventory(command):
"""
Shows a player's inventory.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
session.msg("You are carrying:")
@ -99,21 +108,23 @@ def cmd_inventory(cdat):
session.msg("You have %d %s." % (money,money_name))
def cmd_look(cdat):
def cmd_look(command):
"""
Handle looking at objects.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
if len(args) == 0:
target_obj = pobject.get_location()
else:
target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
# If an argument is provided with the command, search for the object.
# else look at the current room.
if command.command_argument:
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
else:
target_obj = pobject.get_location()
# SCRIPT: Get the item's appearance from the scriptlink.
session.msg(target_obj.scriptlink.return_appearance({
@ -126,20 +137,21 @@ def cmd_look(cdat):
"target_obj": pobject
})
def cmd_get(cdat):
def cmd_get(command):
"""
Get an object and put it in a player's inventory.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
plr_is_staff = pobject.is_staff()
if len(args) == 0:
if not command.command_argument:
session.msg("Get what?")
return
else:
target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args), search_contents=False)
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument,
search_contents=False)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -158,27 +170,31 @@ def cmd_get(cdat):
target_obj.move_to(pobject, quiet=True)
session.msg("You pick up %s." % (target_obj.get_name(),))
pobject.get_location().emit_to_contents("%s picks up %s." % (pobject.get_name(), target_obj.get_name()), exclude=pobject)
pobject.get_location().emit_to_contents("%s picks up %s." %
(pobject.get_name(),
target_obj.get_name()),
exclude=pobject)
# SCRIPT: Call the object's script's a_get() method.
target_obj.scriptlink.a_get({
"pobject": pobject
})
def cmd_drop(cdat):
def cmd_drop(command):
"""
Drop an object from a player's inventory into their current location.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
plr_is_staff = pobject.is_staff()
if len(args) == 0:
if not command.command_argument:
session.msg("Drop what?")
return
else:
target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args), search_location=False)
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument,
search_location=False)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -189,28 +205,30 @@ def cmd_drop(cdat):
target_obj.move_to(pobject.get_location(), quiet=True)
session.msg("You drop %s." % (target_obj.get_name(),))
pobject.get_location().emit_to_contents("%s drops %s." % (pobject.get_name(), target_obj.get_name()), exclude=pobject)
pobject.get_location().emit_to_contents("%s drops %s." %
(pobject.get_name(),
target_obj.get_name()),
exclude=pobject)
# SCRIPT: Call the object's script's a_drop() method.
target_obj.scriptlink.a_drop({
"pobject": pobject
})
def cmd_examine(cdat):
def cmd_examine(command):
"""
Detailed object examine command
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
attr_search = False
if len(args) == 0:
if not command.command_argument:
# If no arguments are provided, examine the invoker's location.
target_obj = pobject.get_location()
else:
# Look for a slash in the input, indicating an attribute search.
attr_split = args[0].split("/")
attr_split = command.command_argument.split("/", 1)
# If the splitting by the "/" character returns a list with more than 1
# entry, it's an attribute match.
@ -218,41 +236,59 @@ def cmd_examine(cdat):
attr_search = True
# Strip the object search string from the input with the
# object/attribute pair.
searchstr = attr_split[0]
# Just in case there's a slash in an attribute name.
attr_searchstr = '/'.join(attr_split[1:])
obj_searchstr = attr_split[0]
attr_searchstr = attr_split[1].strip()
# Protect against stuff like: ex me/
if attr_searchstr == '':
session.msg('No attribute name provided.')
return
else:
searchstr = ' '.join(args)
# No slash in argument, just examine an object.
obj_searchstr = command.command_argument
target_obj = Object.objects.standard_plr_objsearch(session, searchstr)
# Resolve the target object.
target_obj = Object.objects.standard_plr_objsearch(session,
obj_searchstr)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
if attr_search:
"""
Player did something like: examine me/* or examine me/TE*. Return
each matching attribute with its value.
"""
attr_matches = target_obj.attribute_namesearch(attr_searchstr)
if attr_matches:
for attribute in attr_matches:
session.msg(attribute.get_attrline())
else:
session.msg("No matching attributes found.")
# End attr_search if()
else:
"""
Player is examining an object. Return a full readout of attributes,
along with detailed information about said object.
"""
# Format the examine header area with general flag/type info.
session.msg("%s\r\n%s" % (
target_obj.get_name(fullname=True),
target_obj.get_description(no_parsing=True),
))
session.msg("Type: %s Flags: %s" % (target_obj.get_type(), target_obj.get_flags()))
session.msg("Type: %s Flags: %s" % (target_obj.get_type(),
target_obj.get_flags()))
session.msg("Owner: %s " % (target_obj.get_owner(),))
session.msg("Zone: %s" % (target_obj.get_zone(),))
for attribute in target_obj.get_all_attributes():
session.msg(attribute.get_attrline())
# Contents container lists for sorting by type.
con_players = []
con_things = []
con_exits = []
# Break each object out into their own list.
for obj in target_obj.get_contents():
if obj.is_player():
con_players.append(obj)
@ -261,157 +297,47 @@ def cmd_examine(cdat):
elif obj.is_thing():
con_things.append(obj)
# Render Contents display.
if con_players or con_things:
session.msg("%sContents:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],))
session.msg("%sContents:%s" % (ansi.ansi["hilite"],
ansi.ansi["normal"],))
for player in con_players:
session.msg('%s' % (player.get_name(fullname=True),))
for thing in con_things:
session.msg('%s' % (thing.get_name(fullname=True),))
# Render Exists display.
if con_exits:
session.msg("%sExits:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],))
session.msg("%sExits:%s" % (ansi.ansi["hilite"],
ansi.ansi["normal"],))
for exit in con_exits:
session.msg('%s' %(exit.get_name(fullname=True),))
# Render the object's home or destination (for exits).
if not target_obj.is_room():
if target_obj.is_exit():
# The Home attribute on an exit is really its destination.
session.msg("Destination: %s" % (target_obj.get_home(),))
else:
# For everything else, home is home.
session.msg("Home: %s" % (target_obj.get_home(),))
# This obviously isn't valid for rooms.
session.msg("Location: %s" % (target_obj.get_location(),))
def cmd_page(cdat):
"""
Send a message to target user (if online).
"""
session = cdat['session']
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
parsed_command = cdat['uinput']['parsed_command']
# We use a dict to ensure that the list of targets is unique
targets = dict()
# Get the last paged person
last_paged_dbrefs = pobject.get_attribute_value("LASTPAGED")
# If they have paged someone before, go ahead and grab the object of
# that person.
if last_paged_dbrefs is not False:
last_paged_objects = list()
try:
last_paged_dbref_list = [
x.strip() for x in last_paged_dbrefs.split(',')]
for dbref in last_paged_dbref_list:
if not Object.objects.is_dbref(dbref):
raise ValueError
last_paged_object = Object.objects.dbref_search(dbref)
if last_paged_object is not None:
last_paged_objects.append(last_paged_object)
except ValueError:
# LASTPAGED Attribute is not a list of dbrefs
last_paged_dbrefs = False
# Remove the invalid LASTPAGED attribute
pobject.clear_attribute("LASTPAGED")
# If they don't give a target, or any data to send to the target
# then tell them who they last paged if they paged someone, if not
# tell them they haven't paged anyone.
if parsed_command['targets'] is None and parsed_command['data'] is None:
if last_paged_dbrefs is not False and not last_paged_objects == list():
session.msg("You last paged: %s." % (
', '.join([x.name for x in last_paged_objects])))
return
session.msg("You have not paged anyone.")
return
# Build a list of targets
# If there are no targets, then set the targets to the last person they
# paged.
if parsed_command['targets'] is None:
if not last_paged_objects == list():
targets = dict([(target, 1) for target in last_paged_objects])
else:
# First try to match the entire target string against a single player
full_target_match = Object.objects.player_name_search(
parsed_command['original_targets'])
if full_target_match is not None:
targets[full_target_match] = 1
else:
# For each of the targets listed, grab their objects and append
# it to the targets list
for target in parsed_command['targets']:
# If the target is a dbref, behave appropriately
if Object.objects.is_dbref(target):
session.msg("Is dbref.")
matched_object = Object.objects.dbref_search(target,
limit_types=[defines_global.OTYPE_PLAYER])
if matched_object is not None:
targets[matched_object] = 1
else:
# search returned None
session.msg("Player '%s' does not exist." % (
target))
else:
# Not a dbref, so must be a username, treat it as such
matched_object = Object.objects.player_name_search(
target)
if matched_object is not None:
targets[matched_object] = 1
else:
# search returned None
session.msg("Player '%s' does not exist." % (
target))
data = parsed_command['data']
sender_name = pobject.get_name(show_dbref=False)
# Build our messages
target_message = "%s pages: %s"
sender_message = "You paged %s with '%s'."
# Handle paged emotes
if data.startswith(':'):
data = data[1:]
target_message = "From afar, %s %s"
sender_message = "Long distance to %s: %s %s"
# Handle paged emotes without spaces
if data.startswith(';'):
data = data[1:]
target_message = "From afar, %s%s"
sender_message = "Long distance to %s: %s%s"
# We build a list of target_names for the sender_message later
target_names = []
for target in targets.keys():
# Check to make sure they're connected, or a player
if target.is_connected_plr():
target.emit_to(target_message % (sender_name, data))
target_names.append(target.get_name(show_dbref=False))
else:
session.msg("Player %s does not exist or is not online." % (
target.get_name(show_dbref=False)))
if len(target_names) > 0:
target_names_string = ', '.join(target_names)
try:
session.msg(sender_message % (target_names_string, sender_name, data))
except TypeError:
session.msg(sender_message % (target_names_string, data))
# Now set the LASTPAGED attribute
pobject.set_attribute("LASTPAGED", ','.join(
["#%d" % (x.id) for x in targets.keys()]))
def cmd_quit(cdat):
def cmd_quit(command):
"""
Gracefully disconnect the user as per his own request.
"""
session = cdat['session']
session = command.session
session.msg("Quitting!")
session.handle_close()
def cmd_who(cdat):
def cmd_who(command):
"""
Generic WHO command.
"""
session_list = session_mgr.get_session_list()
session = cdat['session']
session = command.session
pobject = session.get_pobject()
show_session_data = pobject.user_has_perm("genperms.see_session_data")
@ -457,18 +383,19 @@ def cmd_who(cdat):
session.msg(retval)
def cmd_say(cdat):
def cmd_say(command):
"""
Room-based speech command.
"""
session = cdat['session']
session = command.session
if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 1, errortext="Say what?"):
if not command.command_argument:
session.msg("Say what?")
return
session_list = session_mgr.get_session_list()
pobject = session.get_pobject()
speech = ' '.join(cdat['uinput']['splitted'][1:])
speech = command.command_argument
players_present = [player for player in session_list if player.get_pobject().get_location() == session.get_pobject().get_location() and player != session]
@ -478,23 +405,25 @@ def cmd_say(cdat):
session.msg(retval)
def cmd_pose(cdat):
def cmd_pose(command):
"""
Pose/emote command.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
switches = cdat['uinput']['root_chunk'][1:]
if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 1, errortext="Do what?"):
if not command.command_argument:
session.msg("Do what?")
return
session_list = session_mgr.get_session_list()
speech = ' '.join(cdat['uinput']['splitted'][1:])
speech = command.command_argument
if "nospace" in switches:
if "nospace" in command.command_switches:
# Output without a space between the player name and the emote.
sent_msg = "%s%s" % (pobject.get_name(show_dbref=False), speech)
else:
# No switches, default.
sent_msg = "%s %s" % (pobject.get_name(show_dbref=False), speech)
players_present = [player for player in session_list if player.get_pobject().get_location() == session.get_pobject().get_location()]
@ -502,15 +431,15 @@ def cmd_pose(cdat):
for player in players_present:
player.msg(sent_msg)
def cmd_help(cdat):
def cmd_help(command):
"""
Help system commands.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
topicstr = ' '.join(cdat['uinput']['splitted'][1:])
topicstr = command.command_argument
if len(topicstr) == 0:
if not command.command_argument:
topicstr = "Help Index"
elif len(topicstr) < 2 and not topicstr.isdigit():
session.msg("Your search query is too short. It must be at least three letters long.")

View file

@ -16,79 +16,95 @@ import django
from apps.objects.models import Object
from src import scheduler
from src import defines_global
from src import flags
def cmd_version(cdat):
def cmd_version(command):
"""
Version info command.
"""
session = cdat['session']
session = command.session
retval = "-"*50 +"\n\r"
retval += " Evennia %s\n\r" % (defines_global.EVENNIA_VERSION,)
retval += " Django %s\n\r" % (django.get_version())
retval += "-"*50
session.msg(retval)
def cmd_time(cdat):
def cmd_time(command):
"""
Server local time.
"""
session = cdat['session']
session.msg('Current server time : %s' % (time.strftime('%a %b %d %H:%M:%S %Y (%Z)', time.localtime(),)))
session = command.session
session.msg('Current server time : %s' %
(time.strftime('%a %b %d %H:%M:%S %Y (%Z)', time.localtime(),)))
def cmd_uptime(cdat):
def cmd_uptime(command):
"""
Server uptime and stats.
"""
session = cdat['session']
server = cdat['server']
session = command.session
server = command.server
start_delta = time.time() - server.start_time
loadavg = os.getloadavg()
session.msg('Current server time : %s' % (time.strftime('%a %b %d %H:%M %Y (%Z)', time.localtime(),)))
session.msg('Server start time : %s' % (time.strftime('%a %b %d %H:%M %Y', time.localtime(server.start_time),)))
session.msg('Server uptime : %s' % functions_general.time_format(start_delta, style=2))
session.msg('Server load (1 min) : %.2f' % loadavg[0])
session.msg('Current server time : %s' %
(time.strftime('%a %b %d %H:%M %Y (%Z)', time.localtime(),)))
session.msg('Server start time : %s' %
(time.strftime('%a %b %d %H:%M %Y', time.localtime(server.start_time),)))
session.msg('Server uptime : %s' %
functions_general.time_format(start_delta, style=2))
# os.getloadavg() is not available on Windows.
if not functions_general.host_os_is('nt'):
loadavg = os.getloadavg()
session.msg('Server load (1 min) : %.2f' %
loadavg[0])
def cmd_list(cdat):
def cmd_list(command):
"""
Shows some game related information.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
argstr = ''.join(args)
msg_invalid = "Unknown option. Use one of: commands, flags, process"
if len(argstr) == 0:
if not command.command_argument:
session.msg(msg_invalid)
elif argstr == "commands":
elif command.command_argument == "commands":
session.msg('Commands: '+ ' '.join(session.server.command_list()))
elif argstr == "process":
elif command.command_argument == "process":
if not functions_general.host_os_is('nt'):
loadvg = os.getloadavg()
psize = resource.getpagesize()
rusage = resource.getrusage(resource.RUSAGE_SELF)
session.msg("Process ID: %10d %10d bytes per page" % (os.getpid(), psize))
session.msg("Time used: %10d user %10d sys" % (rusage[0],rusage[1]))
session.msg("Integral mem:%10d shared %10d private%10d stack" % (rusage[3], rusage[4], rusage[5]))
session.msg("Max res mem: %10d pages %10d bytes" % (rusage[2],rusage[2] * psize))
session.msg("Page faults: %10d hard %10d soft %10d swapouts" % (rusage[7], rusage[6], rusage[8]))
session.msg("Disk I/O: %10d reads %10d writes" % (rusage[9], rusage[10]))
session.msg("Network I/O: %10d in %10d out" % (rusage[12], rusage[11]))
session.msg("Context swi: %10d vol %10d forced %10d sigs" % (rusage[14], rusage[15], rusage[13]))
session.msg("Process ID: %10d %10d bytes per page" %
(os.getpid(), psize))
session.msg("Time used: %10d user %10d sys" %
(rusage[0],rusage[1]))
session.msg("Integral mem:%10d shared %10d private%10d stack" %
(rusage[3], rusage[4], rusage[5]))
session.msg("Max res mem: %10d pages %10d bytes" %
(rusage[2],rusage[2] * psize))
session.msg("Page faults: %10d hard %10d soft %10d swapouts" %
(rusage[7], rusage[6], rusage[8]))
session.msg("Disk I/O: %10d reads %10d writes" %
(rusage[9], rusage[10]))
session.msg("Network I/O: %10d in %10d out" %
(rusage[12], rusage[11]))
session.msg("Context swi: %10d vol %10d forced %10d sigs" %
(rusage[14], rusage[15], rusage[13]))
else:
session.msg("Feature not available on Windows.")
return
elif argstr == "flags":
session.msg("Flags: "+" ".join(defines_global.SERVER_FLAGS))
elif command.command_argument == "flags":
session.msg("Flags: "+" ".join(flags.SERVER_FLAGS))
else:
session.msg(msg_invalid)
def cmd_ps(cdat):
def cmd_ps(command):
"""
Shows the process/event table.
"""
session = cdat['session']
session = command.session
session.msg("-- Interval Events --")
for event in scheduler.schedule:
session.msg(" [%d/%d] %s" % (scheduler.get_event_nextfire(event),
@ -96,14 +112,15 @@ def cmd_ps(cdat):
scheduler.get_event_description(event)))
session.msg("Totals: %d interval events" % (len(scheduler.schedule),))
def cmd_stats(cdat):
def cmd_stats(command):
"""
Shows stats about the database.
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
"""
session = cdat['session']
session = command.session
stats_dict = Object.objects.object_totals()
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"],
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" %
(stats_dict["objects"],
stats_dict["rooms"],
stats_dict["exits"],
stats_dict["things"],

View file

@ -1,27 +1,31 @@
"""
These commands typically are to do with building or modifying Objects.
"""
from apps.objects.models import Object
from apps.objects.models import Object, Attribute
# We'll import this as the full path to avoid local variable clashes.
import src.flags
from src import ansi
from src import session_mgr
def cmd_teleport(cdat):
def cmd_teleport(command):
"""
Teleports an object somewhere.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
server = command.server
if len(args) == 0:
if not command.command_argument:
session.msg("Teleport where/what?")
return
eq_args = args[0].split('=')
search_str = ''.join(args)
eq_args = command.command_argument.split('=', 1)
# The quiet switch suppresses leaving and arrival messages.
if "quiet" in command.command_switches:
tel_quietly = True
else:
tel_quietly = False
# If we have more than one entry in our '=' delimited argument list,
# then we're doing a @tel <victim>=<location>. If not, we're doing
@ -46,19 +50,11 @@ def cmd_teleport(cdat):
session.msg("You can't teleport an object inside of itself!")
return
session.msg("Teleported.")
victim.move_to(destination)
# This is somewhat kludgy right now, we'll have to find a better way
# to do it sometime else. If we can find a session in the server's
# session list matching the object we're teleporting, force it to
# look. This is going to typically be a player.
victim_session = session_mgr.session_from_object(victim)
if victim_session:
victim_session.execute_cmd("look")
victim.move_to(destination, quiet=tel_quietly)
else:
# Direct teleport (no equal sign)
target_obj = Object.objects.standard_plr_objsearch(session, search_str)
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -67,76 +63,82 @@ def cmd_teleport(cdat):
session.msg("You can't teleport inside yourself!")
return
session.msg("Teleported.")
pobject.move_to(target_obj)
session.execute_cmd("look")
pobject.move_to(target_obj, quiet=tel_quietly)
def cmd_stats(cdat):
def cmd_stats(command):
"""
Shows stats about the database.
4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage)
"""
session = cdat['session']
session = command.session
stats_dict = Object.objects.object_totals()
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" % (stats_dict["objects"],
session.msg("%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)" %
(stats_dict["objects"],
stats_dict["rooms"],
stats_dict["exits"],
stats_dict["things"],
stats_dict["players"],
stats_dict["garbage"]))
def cmd_alias(cdat):
def cmd_alias(command):
"""
Assigns an alias to a player object for ease of paging, etc.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
if len(args) == 0:
if not command.command_argument:
session.msg("Alias whom?")
return
# Resplit the args on = to check for an almost-required =
eq_args = ' '.join(args).split('=')
eq_args = command.command_argument.split('=', 1)
if len(eq_args) < 2:
session.msg("Alias missing.")
return
target = Object.objects.standard_plr_objsearch(session, eq_args[0])
target_string = eq_args[0]
new_alias = eq_args[1]
# An Object instance for the victim.
target = Object.objects.standard_plr_objsearch(session, target_string)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target:
session.msg("Alias whom?")
session.msg("I can't find that player.")
return
duplicates = Object.objects.player_alias_search(pobject, eq_args[1])
if duplicates:
session.msg("Alias '%s' already exists." % (eq_args[1],))
return
else:
old_alias = target.get_attribute_value('ALIAS')
duplicates = Object.objects.player_alias_search(pobject, new_alias)
if not duplicates or old_alias.lower() == new_alias.lower():
# Either no duplicates or just changing the case of existing alias.
if pobject.controls_other(target):
target.set_attribute('ALIAS', eq_args[1])
session.msg("Alias '%s' set for %s." % (eq_args[1], target.get_name()))
target.set_attribute('ALIAS', new_alias)
session.msg("Alias '%s' set for %s." % (new_alias,
target.get_name()))
else:
session.msg("You do not have access to set an alias for %s." % (target.get_name(),))
session.msg("You do not have access to set an alias for %s." %
(target.get_name(),))
else:
# Duplicates were found.
session.msg("Alias '%s' is already in use." % (new_alias,))
return
def cmd_wipe(cdat):
def cmd_wipe(command):
"""
Wipes an object's attributes, or optionally only those matching a search
string.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
attr_search = False
if len(args) == 0:
if not command.command_argument:
session.msg("Wipe what?")
return
# Look for a slash in the input, indicating an attribute wipe.
attr_split = args[0].split("/")
attr_split = command.command_argument.split("/", 1)
# If the splitting by the "/" character returns a list with more than 1
# entry, it's an attribute match.
@ -144,13 +146,11 @@ def cmd_wipe(cdat):
attr_search = True
# Strip the object search string from the input with the
# object/attribute pair.
searchstr = attr_split[0]
# Just in case there's a slash in an attribute name.
attr_searchstr = '/'.join(attr_split[1:])
searchstr = attr_split[1]
else:
searchstr = ' '.join(args)
searchstr = command.command_argument
target_obj = Object.objects.standard_plr_objsearch(session, searchstr)
target_obj = Object.objects.standard_plr_objsearch(session, attr_split[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -158,11 +158,13 @@ def cmd_wipe(cdat):
if attr_search:
# User has passed an attribute wild-card string. Search for name matches
# and wipe.
attr_matches = target_obj.attribute_namesearch(attr_searchstr, exclude_noset=True)
attr_matches = target_obj.attribute_namesearch(searchstr,
exclude_noset=True)
if attr_matches:
for attr in attr_matches:
target_obj.clear_attribute(attr.get_name())
session.msg("%s - %d attributes wiped." % (target_obj.get_name(), len(attr_matches)))
session.msg("%s - %d attributes wiped." % (target_obj.get_name(),
len(attr_matches)))
else:
session.msg("No matching attributes found.")
else:
@ -170,27 +172,25 @@ def cmd_wipe(cdat):
attr_matches = target_obj.attribute_namesearch("*", exclude_noset=True)
for attr in attr_matches:
target_obj.clear_attribute(attr.get_name())
session.msg("%s - %d attributes wiped." % (target_obj.get_name(), len(attr_matches)))
session.msg("%s - %d attributes wiped." % (target_obj.get_name(),
len(attr_matches)))
def cmd_set(cdat):
def cmd_set(command):
"""
Sets flags or attributes on objects.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
server = command.server
if len(args) == 0:
if not command.command_argument:
session.msg("Set what?")
return
# There's probably a better way to do this. Break the arguments (minus
# the root command) up so we have two items in the list, 0 being the victim,
# 1 being the list of flags or the attribute/value pair.
eq_args = ' '.join(args).split('=')
# Break into target and value by the equal sign.
eq_args = command.command_argument.split('=', 1)
if len(eq_args) < 2:
# Equal signs are not optional for @set.
session.msg("Set what?")
return
@ -203,8 +203,7 @@ def cmd_set(cdat):
session.msg(defines_global.NOCONTROL_MSG)
return
attrib_args = eq_args[1].split(':')
attrib_args = eq_args[1].split(':', 1)
if len(attrib_args) > 1:
# We're dealing with an attribute/value pair.
attrib_name = attrib_args[0].upper()
@ -212,7 +211,7 @@ def cmd_set(cdat):
attrib_value = eq_args[1][splicenum:]
# In global_defines.py, see NOSET_ATTRIBS for protected attribute names.
if not src.flags.is_modifiable_attrib(attrib_name) and not pobject.is_superuser():
if not Attribute.objects.is_modifiable_attrib(attrib_name) and not pobject.is_superuser():
session.msg("You can't modify that attribute.")
return
@ -237,30 +236,32 @@ def cmd_set(cdat):
if not src.flags.is_modifiable_flag(flag):
session.msg("You can't set/unset the flag - %s." % (flag,))
else:
session.msg('%s - %s cleared.' % (victim.get_name(), flag.upper(),))
session.msg('%s - %s cleared.' % (victim.get_name(),
flag.upper(),))
victim.set_flag(flag, False)
else:
# We're setting the flag.
if not src.flags.is_modifiable_flag(flag):
session.msg("You can't set/unset the flag - %s." % (flag,))
else:
session.msg('%s - %s set.' % (victim.get_name(), flag.upper(),))
session.msg('%s - %s set.' % (victim.get_name(),
flag.upper(),))
victim.set_flag(flag, True)
def cmd_find(cdat):
def cmd_find(command):
"""
Searches for an object of a particular name.
"""
session = cdat['session']
server = cdat['server']
searchstring = ' '.join(cdat['uinput']['splitted'][1:])
session = command.session
server = command.server
pobject = session.get_pobject()
can_find = pobject.user_has_perm("genperms.builder")
if searchstring == '':
if not command.command_argument:
session.msg("No search pattern given.")
return
searchstring = command.command_argument
results = Object.objects.global_object_name_search(searchstring)
if len(results) > 0:
@ -271,35 +272,37 @@ def cmd_find(cdat):
else:
session.msg("No name matches found for: %s" % (searchstring,))
def cmd_create(cdat):
def cmd_create(command):
"""
Creates a new object of type 'THING'.
"""
session = cdat['session']
session = command.session
server = session.server
pobject = session.get_pobject()
uinput= cdat['uinput']['splitted']
thingname = ' '.join(uinput[1:])
if thingname == '':
if not command.command_argument:
session.msg("You must supply a name!")
else:
# Create and set the object up.
odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject}
# TODO: This dictionary stuff is silly. Feex.
odat = {"name": command.command_argument,
"type": 3,
"location": pobject,
"owner": pobject}
new_object = Object.objects.create_object(odat)
session.msg("You create a new thing: %s" % (new_object,))
def cmd_nextfree(cdat):
def cmd_nextfree(command):
"""
Returns the next free object number.
"""
session = cdat['session']
session = command.session
nextfree = Object.objects.get_nextfree_dbnum()
session.msg("Next free object number: #%s" % (nextfree,))
def cmd_open(cdat):
def cmd_open(command):
"""
Handle the opening of exits.
@ -308,16 +311,15 @@ def cmd_open(cdat):
@open <Name>=<Dbref>
@open <Name>=<Dbref>,<Name>
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
server = command.server
if len(args) == 0:
if not command.command_argument:
session.msg("Open an exit to where?")
return
eq_args = ' '.join(args).split('=')
eq_args = command.command_argument.split('=', 1)
exit_name = eq_args[0]
if len(exit_name) == 0:
@ -329,8 +331,9 @@ def cmd_open(cdat):
# an un-linked exit, @open <Name>.
if len(eq_args) > 1:
# Opening an exit to another location via @open <Name>=<Dbref>[,<Name>].
comma_split = eq_args[1].split(',')
destination = Object.objects.standard_plr_objsearch(session, comma_split[0])
comma_split = eq_args[1].split(',', 1)
destination = Object.objects.standard_plr_objsearch(session,
comma_split[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not destination:
return
@ -339,43 +342,56 @@ def cmd_open(cdat):
session.msg("You can't open an exit to an exit!")
return
odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":destination}
odat = {"name": exit_name,
"type": 4,
"location": pobject.get_location(),
"owner": pobject,
"home":destination}
new_object = Object.objects.create_object(odat)
session.msg("You open the an exit - %s to %s" % (new_object.get_name(),destination.get_name()))
session.msg("You open the an exit - %s to %s" % (new_object.get_name(),
destination.get_name()))
if len(comma_split) > 1:
second_exit_name = ','.join(comma_split[1:])
odat = {"name": second_exit_name, "type": 4, "location": destination, "owner": pobject, "home": pobject.get_location()}
odat = {"name": second_exit_name,
"type": 4,
"location": destination,
"owner": pobject,
"home": pobject.get_location()}
new_object = Object.objects.create_object(odat)
session.msg("You open the an exit - %s to %s" % (new_object.get_name(),pobject.get_location().get_name()))
session.msg("You open the an exit - %s to %s" % (
new_object.get_name(),
pobject.get_location().get_name()))
else:
# Create an un-linked exit.
odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":None}
odat = {"name": exit_name,
"type": 4,
"location": pobject.get_location(),
"owner": pobject,
"home":None}
new_object = Object.objects.create_object(odat)
session.msg("You open an unlinked exit - %s" % (new_object,))
def cmd_link(cdat):
def cmd_link(command):
"""
Sets an object's home or an exit's destination.
Forms:
@link <Object>=<Target>
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
server = command.server
if len(args) == 0:
if not command.command_argument:
session.msg("Link what?")
return
eq_args = args[0].split('=')
eq_args = command.command_argument.split('=', 1)
target_name = eq_args[0]
dest_name = '='.join(eq_args[1:])
dest_name = eq_args[1]
if len(target_name) == 0:
session.msg("What do you want to link?")
@ -410,19 +426,21 @@ def cmd_link(cdat):
session.msg("You must provide a destination to link to.")
return
def cmd_unlink(cdat):
def cmd_unlink(command):
"""
Unlinks an object.
"""
session = cdat['session']
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
if len(args) == 0:
@unlink <Object>
"""
session = command.session
pobject = session.get_pobject()
if not command.command_argument:
session.msg("Unlink what?")
return
else:
target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -434,67 +452,75 @@ def cmd_unlink(cdat):
target_obj.set_home(None)
session.msg("You have unlinked %s." % (target_obj.get_name(),))
def cmd_dig(cdat):
def cmd_dig(command):
"""
Creates a new object of type 'ROOM'.
"""
session = cdat['session']
pobject = session.get_pobject()
uinput= cdat['uinput']['splitted']
roomname = ' '.join(uinput[1:])
if roomname == '':
@dig <Name>
"""
session = command.session
pobject = session.get_pobject()
roomname = command.command_argument
if not roomname:
session.msg("You must supply a name!")
else:
# Create and set the object up.
odat = {"name": roomname, "type": 2, "location": None, "owner": pobject}
odat = {"name": roomname,
"type": 2,
"location": None,
"owner": pobject}
new_object = Object.objects.create_object(odat)
session.msg("You create a new room: %s" % (new_object,))
def cmd_name(cdat):
def cmd_name(command):
"""
Handle naming an object.
"""
session = cdat['session']
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
eq_args = ' '.join(args).split('=')
searchstring = ''.join(eq_args[0])
if len(args) == 0:
@name <Object>=<Value>
"""
session = command.session
pobject = session.get_pobject()
if not command.command_string:
session.msg("What do you want to name?")
elif len(eq_args) < 2:
return
eq_args = command.command_argument.split('=', 1)
# Only strip spaces from right side in case they want to be silly and
# have a left-padded object name.
new_name = eq_args[1].rstrip()
if len(eq_args) < 2 or eq_args[1] == '':
session.msg("What would you like to name that object?")
else:
target_obj = Object.objects.standard_plr_objsearch(session, searchstring)
target_obj = Object.objects.standard_plr_objsearch(session, eq_args[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
if len(eq_args[1]) == 0:
session.msg("What would you like to name that object?")
else:
newname = '='.join(eq_args[1:])
session.msg("You have renamed %s to %s." % (target_obj, ansi.parse_ansi(newname, strip_formatting=True)))
target_obj.set_name(newname)
ansi_name = ansi.parse_ansi(new_name, strip_formatting=True)
session.msg("You have renamed %s to %s." % (target_obj, ansi_name))
target_obj.set_name(new_name)
def cmd_description(cdat):
def cmd_description(command):
"""
Set an object's description.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
eq_args = ' '.join(args).split('=')
searchstring = ''.join(eq_args[0])
if len(args) == 0:
if not command.command_argument:
session.msg("What do you want to describe?")
elif len(eq_args) < 2:
return
eq_args = command.command_argument.split('=', 1)
if len(eq_args) < 2 or eq_args[1] == '':
session.msg("How would you like to describe that object?")
else:
target_obj = Object.objects.standard_plr_objsearch(session, searchstring)
target_obj = Object.objects.standard_plr_objsearch(session, eq_args[0])
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -503,45 +529,45 @@ def cmd_description(cdat):
session.msg(defines_global.NOCONTROL_MSG)
return
new_desc = '='.join(eq_args[1:])
new_desc = eq_args[1]
session.msg("%s - DESCRIPTION set." % (target_obj,))
target_obj.set_description(new_desc)
def cmd_destroy(cdat):
def cmd_destroy(command):
"""
Destroy an object.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
switches = cdat['uinput']['root_chunk'][1:]
switch_override = False
if "override" in switches:
switch_override = True
if len(args) == 0:
if not command.command_argument:
session.msg("Destroy what?")
return
else:
target_obj = Object.objects.standard_plr_objsearch(session, ' '.join(args))
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
# Safety feature. Switch required to delete players and SAFE objects.
if "override" in command.command_switches:
switch_override = True
if target_obj.is_player():
if pobject.id == target_obj.id:
session.msg("You can't destroy yourself.")
return
if not switch_override:
session.msg("You must use @destroy/override on players.")
return
if target_obj.is_superuser():
session.msg("You can't destroy a superuser.")
return
elif target_obj.is_going() or target_obj.is_garbage():
session.msg("That object is already destroyed.")
target_obj = Object.objects.standard_plr_objsearch(session,
command.command_argument)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
if target_obj.is_player():
if pobject.id == target_obj.id:
session.msg("You can't destroy yourself.")
return
if not switch_override:
session.msg("You must use @destroy/override on players.")
return
if target_obj.is_superuser():
session.msg("You can't destroy a superuser.")
return
elif target_obj.is_going() or target_obj.is_garbage():
session.msg("That object is already destroyed.")
return
session.msg("You destroy %s." % (target_obj.get_name(),))
target_obj.destroy()

119
src/commands/paging.py Normal file
View file

@ -0,0 +1,119 @@
"""
Paging command and support functions.
"""
from apps.objects.models import Object
from src import defines_global
def get_last_paged_objects(pobject):
"""
Returns a list of objects of the user's last paged list, or None if invalid
or non-existant.
"""
last_paged_dbrefs = pobject.get_attribute_value("LASTPAGED")
if last_paged_dbrefs is not False:
last_paged_objects = list()
try:
last_paged_dbref_list = [
x.strip() for x in last_paged_dbrefs.split(',')
]
for dbref in last_paged_dbref_list:
if not Object.objects.is_dbref(dbref):
raise ValueError
last_paged_object = Object.objects.dbref_search(dbref)
if last_paged_object is not None:
last_paged_objects.append(last_paged_object)
return last_paged_objects
except ValueError:
# Remove the invalid LASTPAGED attribute
pobject.clear_attribute("LASTPAGED")
return None
def cmd_page(command):
"""
Send a message to target user (if online).
"""
session = command.session
pobject = session.get_pobject()
server = command.server
args = command.command_argument.split()
targets = []
# Get the last paged person(s)
last_paged_objects = get_last_paged_objects(pobject)
# If they don't give a target, or any data to send to the target
# then tell them who they last paged if they paged someone, if not
# tell them they haven't paged anyone.
if not command.command_argument:
if last_paged_objects:
session.msg("You last paged: %s." % (
', '.join([x.name for x in last_paged_objects])))
return
session.msg("You have not paged anyone.")
return
# Build a list of targets
# If there are no targets, then set the targets to the last person they
# paged.
cmd_targets = command.get_arg_targets()
if cmd_targets is None:
targets = last_paged_objects
else:
# For each of the targets listed, grab their objects and append
# it to the targets list
for target in cmd_targets:
matched_object = Object.objects.local_and_global_search(pobject,
target,
limit_types=[defines_global.OTYPE_PLAYER])
if matched_object:
targets.append(matched_object[0])
print "MATCH:", matched_object[0]
else:
# search returned None
session.msg("Player '%s' can not be found." % (
target))
# Depending on the argument provided, either send the entire thing as
# a message or break off the point after the equal sign.
if command.arg_has_target():
message = command.get_arg_target_value()
else:
message = command.command_argument
sender_name = pobject.get_name(show_dbref=False)
# Build our messages
target_message = "%s pages: %s"
sender_message = "You paged %s with '%s'."
# Handle paged emotes
if message.startswith(':'):
message = message[1:]
target_message = "From afar, %s %s"
sender_message = "Long distance to %s: %s %s"
# Handle paged emotes without spaces
if message.startswith(';'):
message = message[1:]
target_message = "From afar, %s%s"
sender_message = "Long distance to %s: %s%s"
# We build a list of target_names for the sender_message later
target_names = []
for target in targets:
# Check to make sure they're connected, or a player
if target.is_connected_plr():
target.emit_to(target_message % (sender_name, message))
target_names.append(target.get_name(show_dbref=False))
else:
session.msg("Player %s does not exist or is not online." % (
target.get_name(show_dbref=False)))
# Now send a confirmation to the person doing the paging.
if len(target_names) > 0:
target_names_string = ', '.join(target_names)
try:
session.msg(sender_message % (target_names_string, sender_name, message))
except TypeError:
session.msg(sender_message % (target_names_string, message))
# Now set the LASTPAGED attribute
pobject.set_attribute("LASTPAGED", ','.join(
["#%d" % (x.id) for x in targets]))

View file

@ -5,56 +5,54 @@ are generally @-prefixed commands, but there are exceptions.
from apps.objects.models import Object
from src import defines_global
from src import ansi
from src import session_mgr
from src.util import functions_general
def cmd_reload(cdat):
def cmd_reload(command):
"""
Reloads all modules.
"""
session = cdat['session']
session = command.session
server = session.server.reload(session)
def cmd_boot(cdat):
def cmd_boot(command):
"""
Boot a player object from the server.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
eq_args = ' '.join(args).split('=')
searchstring = ''.join(eq_args[0])
switches = cdat['uinput']['root_chunk'][1:]
switch_quiet = False
switch_port = False
if not pobject.is_staff():
session.msg("You do not have permission to do that.")
return
if "quiet" in switches:
if "quiet" in command.command_switches:
# Don't tell the player they've been disconnected, silently boot them.
switch_quiet = True
if "port" in switches:
if "port" in command.command_switches:
# Boot by port number instead of name or dbref.
switch_port = True
if len(args) == 0:
if not command.command_argument:
session.msg("Who would you like to boot?")
return
else:
boot_list = []
if switch_port:
# Boot a particular port.
sessions = session_mgr.get_session_list(True)
for sess in sessions:
if sess.getClientAddress()[1] == int(searchstring):
# Find the session with the matching port number.
if sess.getClientAddress()[1] == int(command.command_argument):
boot_list.append(sess)
# We're done here
# Match found, kill the loop and continue with booting.
break
else:
# Grab the objects that match
objs = Objects.object.global_object_name_search(searchstring)
objs = Object.objects.local_and_global_search(pobject,
command.command_argument)
if len(objs) < 1:
session.msg("Who would you like to boot?")
if not objs:
session.msg("No name or dbref match found for booting.")
return
if not objs[0].is_player():
@ -71,7 +69,15 @@ def cmd_boot(cdat):
if objs[0].is_connected_plr():
boot_list.append(session_mgr.session_from_object(objs[0]))
else:
session.msg("That player is not connected.")
return
if not boot_list:
session.msg("No matches found.")
return
# Carry out the booting of the sessions in the boot list.
for boot in boot_list:
if not switch_quiet:
boot.msg("You have been disconnected by %s." % (pobject.name))
@ -79,25 +85,24 @@ def cmd_boot(cdat):
session_mgr.remove_session(boot)
return
def cmd_newpassword(cdat):
def cmd_newpassword(command):
"""
Set a player's password.
"""
session = cdat['session']
session = command.session
pobject = session.get_pobject()
args = cdat['uinput']['splitted'][1:]
eq_args = ' '.join(args).split('=')
searchstring = ''.join(eq_args[0])
newpass = ''.join(eq_args[1:])
eq_args = command.command_argument.split('=', 1)
searchstring = eq_args[0]
newpass = eq_args[1]
if len(args) == 0:
if not command.command_argument or len(searchstring) == 0:
session.msg("What player's password do you want to change")
return
if len(newpass) == 0:
session.msg("You must supply a new password.")
return
target_obj = Objects.object.standard_plr_objsearch(session, searchstring)
target_obj = Object.objects.standard_plr_objsearch(session, searchstring)
# Use standard_plr_objsearch to handle duplicate/nonexistant results.
if not target_obj:
return
@ -114,14 +119,15 @@ def cmd_newpassword(cdat):
uaccount.set_password(newpass)
uaccount.save()
session.msg("%s - PASSWORD set." % (target_obj.get_name(),))
target_obj.emit_to("%s has changed your password." % (pobject.get_name(show_dbref=False),))
target_obj.emit_to("%s has changed your password." %
(pobject.get_name(show_dbref=False),))
def cmd_shutdown(cdat):
def cmd_shutdown(command):
"""
Shut the server down gracefully.
"""
session = cdat['session']
server = cdat['server']
session = command.session
server = command.server
pobject = session.get_pobject()
session.msg('Shutting down...')

View file

@ -7,51 +7,52 @@ from apps.objects.models import Attribute, Object
from src import defines_global
from src.util import functions_general
def cmd_connect(cdat):
def cmd_connect(command):
"""
This is the connect command at the connection screen. Fairly simple,
uses the Django database API and User model to make it extremely simple.
"""
session = cdat['session']
session = command.session
# Argument check.
if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2):
arg_list = command.command_argument.split()
if not functions_general.cmd_check_num_args(session, arg_list, 2):
return
uemail = cdat['uinput']['splitted'][1]
password = cdat['uinput']['splitted'][2]
uemail = arg_list[0]
password = arg_list[1]
# Match an email address to an account.
email_matches = Object.objects.get_user_from_email(uemail)
autherror = "Specified email does not match any accounts!"
# No username match
if email_matches.count() == 0:
session.msg(autherror)
session.msg("Specified email does not match any accounts!")
return
# We have at least one result, so we can check the password.
user = email_matches[0]
if not user.check_password(password):
session.msg(autherror)
session.msg("Incorrect password.")
else:
uname = user.username
session.login(user)
def cmd_create(cdat):
def cmd_create(command):
"""
Handle the creation of new accounts.
"""
session = cdat['session']
session = command.session
# Argument check.
if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2):
arg_list = command.command_argument.split()
if not functions_general.cmd_check_num_args(session, arg_list, 2):
return
server = session.server
quote_split = ' '.join(cdat['uinput']['splitted']).split("\"")
quote_split = command.command_argument.split("\"")
if len(quote_split) < 2:
session.msg("You must enclose your username in quotation marks.")
@ -84,14 +85,14 @@ def cmd_create(cdat):
elif len(password) < 3:
session.msg("Your password must be 3 characters or longer.")
else:
Object.objects.create_user(cdat, uname, email, password)
Object.objects.create_user(command, uname, email, password)
def cmd_quit(cdat):
def cmd_quit(command):
"""
We're going to maintain a different version of the quit command
here for unconnected users for the sake of simplicity. The logged in
version will be a bit more complicated.
"""
session = cdat['session']
session = command.session
session.msg("Disconnecting...")
session.handle_close()

View file

@ -239,17 +239,16 @@ def get_cobj_from_name(cname):
"""
return CommChannel.objects.get(name=cname)
def create_channel(cdat):
def create_channel(name, owner):
"""
Create a new channel. cdat is a dictionary that contains the following keys.
REQUIRED KEYS:
* name: The name of the new channel.
* owner: The creator of the channel.
Create a new channel.
name: (string) Name of the new channel
owner: (Object) Objec that owns the channel
"""
new_chan = CommChannel()
new_chan.name = ansi.parse_ansi(cdat["name"], strip_ansi=True)
new_chan.ansi_name = "[%s]" % (ansi.parse_ansi(cdat["name"]),)
new_chan.set_owner(cdat["owner"])
new_chan.name = ansi.parse_ansi(name, strip_ansi=True)
new_chan.ansi_name = "[%s]" % (ansi.parse_ansi(name),)
new_chan.set_owner(owner)
new_chan.save()
return new_chan

View file

@ -85,7 +85,7 @@ class EvenniaService(service.Service):
"""
Return a string representing the server's command list.
"""
clist = cmdtable.ctable.keys()
clist = cmdtable.GLOBAL_CMD_TABLE.ctable.keys()
clist.sort()
return clist

View file

@ -74,13 +74,20 @@ class SessionProtocol(StatefulTelnetProtocol):
Any line return indicates a command for the purpose of a MUD. So we take
the user input and pass it to our command handler.
"""
# Clean up the input.
line = (''.join(data))
line = line.strip('\r')
uinput = line
# Stuff anything we need to pass in this dictionary.
cdat = {"server": self.factory.server, "uinput": uinput, "session": self}
cmdhandler.handle(cdat)
# The Command object has all of the methods for parsing and preparing
# for searching and execution.
command = cmdhandler.Command(uinput,
server=self.factory.server,
session=self)
# Send the command object to the command handler for parsing
# and eventual execution.
cmdhandler.handle(command)
def execute_cmd(self, cmdstr):
"""

View file

@ -33,7 +33,7 @@ def cmd_check_num_args(session, arg_list, min_args, errortext="Missing arguments
Check a player command's splitted argument list to make sure it contains
the minimum allowable number of arguments.
"""
if len(arg_list) < min_args+1:
if len(arg_list) < min_args:
session.msg(errortext)
return False
return True