Re-organization of the command handler for the sake of efficiency and cleanliness.

This commit is contained in:
Greg Taylor 2006-12-03 00:40:19 +00:00
parent 703fddcb7f
commit 8352c939ff
5 changed files with 256 additions and 265 deletions

View file

@ -1,76 +1,68 @@
from commands_staff import StaffCommands
from commands_general import GenCommands
from commands_unloggedin import UnLoggedInCommands
import commands_staff
import commands_general
import commands_unloggedin
"""
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.
"""
# We'll use this for our getattr() in the Handler class.
gencommands = GenCommands()
staffcommands = StaffCommands()
unloggedincommands = UnLoggedInCommands()
class UnknownCommand(Exception):
"""
Throw this when a user enters an an invalid command.
"""
class Handler:
def handle(self, cdat):
"""
Use the spliced (list) uinput variable to retrieve the correct
command, or return an invalid command error.
def handle(cdat):
"""
Use the spliced (list) uinput variable to retrieve the correct
command, or return an invalid command error.
We're basically grabbing the player's command by tacking
their input on to 'do_' and looking it up in the GenCommands
class.
"""
session = cdat['session']
server = cdat['server']
We're basically grabbing the player's command by tacking
their input on to 'do_' and looking it up in the GenCommands
class.
"""
session = cdat['session']
server = cdat['server']
try:
# TODO: Protect against non-standard characters.
if cdat['uinput'] == '':
raise UnknownCommand
uinput = cdat['uinput'].split()
parsed_input = {}
try:
# TODO: Protect against non-standard characters.
if cdat['uinput'] == '':
raise UnknownCommand
uinput = cdat['uinput'].split()
parsed_input = {}
# First we split the input up by spaces.
parsed_input['splitted'] = uinput
# 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()
# 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'])
# First we split the input up by spaces.
parsed_input['splitted'] = uinput
# 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()
# 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 session.logged_in:
# If it's prefixed by an '@', it's a staff command.
if parsed_input['root_cmd'][0] != '@':
cmdtable = gencommands
else:
parsed_input['root_cmd'] = parsed_input['root_cmd'][1:]
cmdtable = staffcommands
if session.logged_in:
# If it's prefixed by an '@', it's a staff command.
if parsed_input['root_cmd'][0] != '@':
cmd = getattr(commands_general, 'do_%s' % (parsed_input['root_cmd'],), None )
else:
cmdtable = unloggedincommands
# cmdtable now equals the command table we need to use. Do a command
# lookup for a particular function based on the user's input.
cmd = getattr(cmdtable, 'do_%s' % (parsed_input['root_cmd'],), None )
if callable(cmd):
cdat['uinput'] = parsed_input
cmd(cdat)
else:
raise UnknownCommand
except UnknownCommand:
session.msg("Unknown command.")
parsed_input['root_cmd'] = parsed_input['root_cmd'][1:]
cmd = getattr(commands_staff, 'do_%s' % (parsed_input['root_cmd'],), None )
else:
cmd = getattr(commands_unloggedin, 'do_%s' % (parsed_input['root_cmd'],), None )
if callable(cmd):
cdat['uinput'] = parsed_input
cmd(cdat)
else:
raise UnknownCommand
except UnknownCommand:
session.msg("Unknown command.")

View file

@ -1,72 +1,72 @@
import settings
from ansi import *
class GenCommands:
"""
Generic command module. Pretty much every command should go here for
now.
"""
def do_look(cdat):
"""
Generic command class. Pretty much every command should go here for
now.
"""
def do_look(self, cdat):
"""
Handle looking at objects.
"""
session = cdat['session']
server = cdat['server']
player_loc = session.player_loc
player_loc_obj = server.object_list[player_loc]
retval = "%s%s%s%s\n\r%s" % (
ansi["normal"],
ansi["hilite"],
player_loc_obj.name,
ansi["normal"],
player_loc_obj.description,
)
session.msg(retval)
def do_quit(self, cdat):
"""
Gracefully disconnect the user as per his own request.
"""
session = cdat['session']
session.msg("Quitting!")
session.handle_close()
def do_who(self, cdat):
"""
Generic WHO command.
"""
session_list = cdat['server'].session_list
session = cdat['session']
retval = "Player Name\n\r"
for player in session_list:
retval += '%s\n\r' % (player,)
retval += '%d Players logged in.' % (len(session_list),)
session.msg(retval)
Handle looking at objects.
"""
session = cdat['session']
server = cdat['server']
player_loc = session.player_loc
player_loc_obj = server.object_list[player_loc]
def do_say(self, cdat):
"""
Room-based speech command.
"""
session_list = cdat['server'].session_list
session = cdat['session']
speech = cdat['uinput']['splitted'][1:]
players_present = [player for player in session_list if player.player_loc == session.player_loc and player != session]
retval = "You say, '%s'" % (''.join(speech),)
for player in players_present:
player.msg("%s says, '%s'" % (session.name, speech,))
session.msg(retval)
def do_version(self, cdat):
"""
Version info command.
"""
session = cdat['session']
retval = "-"*50 +"\n\r"
retval += "Evennia %s\n\r" % (settings.EVENNIA_VERSION,)
retval += "-"*50
session.msg(retval)
retval = "%s%s%s%s\n\r%s" % (
ansi["normal"],
ansi["hilite"],
player_loc_obj.name,
ansi["normal"],
player_loc_obj.description,
)
session.msg(retval)
def do_quit(cdat):
"""
Gracefully disconnect the user as per his own request.
"""
session = cdat['session']
session.msg("Quitting!")
session.handle_close()
def do_who(cdat):
"""
Generic WHO command.
"""
session_list = cdat['server'].session_list
session = cdat['session']
retval = "Player Name\n\r"
for player in session_list:
retval += '%s\n\r' % (player,)
retval += '%d Players logged in.' % (len(session_list),)
session.msg(retval)
def do_say(cdat):
"""
Room-based speech command.
"""
session_list = cdat['server'].session_list
session = cdat['session']
speech = cdat['uinput']['splitted'][1:]
players_present = [player for player in session_list if player.player_loc == session.player_loc and player != session]
retval = "You say, '%s'" % (''.join(speech),)
for player in players_present:
player.msg("%s says, '%s'" % (session.name, speech,))
session.msg(retval)
def do_version(cdat):
"""
Version info command.
"""
session = cdat['session']
retval = "-"*50 +"\n\r"
retval += "Evennia %s\n\r" % (settings.EVENNIA_VERSION,)
retval += "-"*50
session.msg(retval)

View file

@ -1,95 +1,96 @@
from apps.objects.models import Object
import functions_db
import commands_general
class StaffCommands:
"""
Restricted staff commands.
"""
def do_dig(cdat):
"""
Restricted staff commands.
Digs a new room out.
"""
def do_dig(self, cdat):
"""
Digs a new room out.
"""
session = cdat['session']
uinput= cdat['uinput']
roomname = ''.join(uinput[1:])
session = cdat['session']
uinput= cdat['uinput']
roomname = ''.join(uinput[1:])
if roomname == '':
session.msg("You must supply a room name!")
else:
newroom = Object()
newroom.name = roomname
newroom.type = "Room"
if roomname == '':
session.msg("You must supply a room name!")
def do_nextfree(cdat):
"""
Returns the next free object number.
"""
session = cdat['session']
server = cdat['server']
nextfree = server.get_nextfree_dbnum()
retval = "Next free object number: %s" % (nextfree,)
session.msg(retval)
def do_teleport(cdat):
"""
Teleports an object somewhere.
"""
session = cdat['session']
pobject = session.pobject
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
if len(args) == 0:
session.msg("Teleport where/what?")
return
eq_args = args[0].split('=')
# 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
# a direct teleport, @tel <destination>.
if len(eq_args) > 1:
session.msg("Equal sign present.")
else:
session.msg("No equal sign, direct tport.")
results = functions_db.local_and_global_search(pobject, ''.join(args))
if len(results) > 1:
session.msg("More than one match found (please narrow target):")
for result in results:
session.msg(" %s(#%s)" % (result.name, result.id,))
elif len(results) == 0:
session.msg("I don't see that here.")
else:
newroom = Object()
newroom.name = roomname
newroom.type = "Room"
session.msg("Teleported.")
pobject.move_to(results[0])
commands_general.do_look(cdat)
def do_nextfree(self, cdat):
"""
Returns the next free object number.
"""
session = cdat['session']
server = cdat['server']
nextfree = server.get_nextfree_dbnum()
retval = "Next free object number: %s" % (nextfree,)
session.msg(retval)
def do_teleport(self, cdat):
"""
Teleports an object somewhere.
"""
session = cdat['session']
pobject = session.pobject
server = cdat['server']
args = cdat['uinput']['splitted'][1:]
if len(args) == 0:
session.msg("Teleport where/what?")
return
eq_args = args[0].split('=')
# 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
# a direct teleport, @tel <destination>.
if len(eq_args) > 1:
session.msg("Equal sign present.")
#session.msg("Args: %s\n\rEqargs: %s" % (args, eq_args,))
def do_find(cdat):
"""
Searches for an object of a particular name.
"""
session = cdat['session']
server = cdat['server']
searchstring = ''.join(cdat['uinput']['splitted'][1:])
if searchstring == '':
session.msg("No search pattern given.")
return
memory_based = True
if memory_based:
results = functions_db.list_search_object_namestr(server.object_list.values(), searchstring)
if len(results) > 0:
session.msg("Name matches for: %s" % (searchstring,))
for result in results:
session.msg(" %s(#%s)" % (result.name, result.id,))
session.msg("%d matches returned." % (len(results),))
else:
session.msg("No equal sign, direct tport.")
results = functions_db.local_and_global_search(pobject, ''.join(args))
if len(results) > 1:
session.msg("More than one match found (please narrow target):")
for result in results:
session.msg(" %s(#%s)" % (result.name, result.id,))
elif len(results) == 0:
session.msg("I don't see that here.")
else:
session.msg("Teleported.")
pobject.move_to(results[0])
#GenCommands.do_look(cdat)
#session.msg("Args: %s\n\rEqargs: %s" % (args, eq_args,))
def do_find(self, cdat):
"""
Searches for an object of a particular name.
"""
session = cdat['session']
server = cdat['server']
searchstring = ''.join(cdat['uinput']['splitted'][1:])
if searchstring == '':
session.msg("No search pattern given.")
return
memory_based = True
if memory_based:
results = functions_db.list_search_object_namestr(server.object_list.values(), searchstring)
if len(results) > 0:
session.msg("Name matches for: %s" % (searchstring,))
for result in results:
session.msg(" %s(#%s)" % (result.name, result.id,))
session.msg("%d matches returned." % (len(results),))
else:
session.msg("No name matches found for: %s" % (searchstring,))
session.msg("No name matches found for: %s" % (searchstring,))

View file

@ -1,54 +1,54 @@
from django.contrib.auth.models import User
class UnLoggedInCommands:
"""
Commands that are available from the connect screen.
"""
def do_connect(cdat):
"""
Commands that are available from the connect screen.
This is the connect command at the connection screen. Fairly simple,
uses the Django database API and User model to make it extremely simple.
"""
def do_connect(self, cdat):
"""
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']
uname = cdat['uinput']['splitted'][1]
password = cdat['uinput']['splitted'][2]
session = cdat['session']
uname = cdat['uinput']['splitted'][1]
password = cdat['uinput']['splitted'][2]
account = User.objects.filter(username=uname)
user = account[0]
autherror = "Invalid username or password!"
if account.count() == 0:
session.msg(autherror)
if not user.check_password(password):
session.msg(autherror)
else:
uname = user.username
session.login(user)
account = User.objects.filter(username=uname)
user = account[0]
def do_create(cdat):
"""
Handle the creation of new accounts.
"""
session = cdat['session']
server = cdat['server']
uname = cdat['uinput']['splitted'][1]
email = cdat['uinput']['splitted'][2]
password = cdat['uinput']['splitted'][3]
account = User.objects.filter(username=uname)
if not account.count() == 0:
session.msg("There is already a player with that name!")
elif len(password) < 3:
session.msg("Your password must be 3 characters or longer.")
else:
server.create_user(session, uname, email, password)
autherror = "Invalid username or password!"
if account.count() == 0:
session.msg(autherror)
if not user.check_password(password):
session.msg(autherror)
else:
uname = user.username
session.login(user)
def do_create(self, cdat):
"""
Handle the creation of new accounts.
"""
session = cdat['session']
server = cdat['server']
uname = cdat['uinput']['splitted'][1]
email = cdat['uinput']['splitted'][2]
password = cdat['uinput']['splitted'][3]
account = User.objects.filter(username=uname)
if not account.count() == 0:
session.msg("There is already a player with that name!")
elif len(password) < 3:
session.msg("Your password must be 3 characters or longer.")
else:
server.create_user(session, uname, email, password)
def do_quit(self, cdat):
"""
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.msg("Disconnecting...")
session.handle_close()
def do_quit(cdat):
"""
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.msg("Disconnecting...")
session.handle_close()

View file

@ -1,12 +1,10 @@
from asyncore import dispatcher
from asynchat import async_chat
import socket, asyncore, time, sys
from cmdhandler import *
import cmdhandler
from apps.objects.models import Object
from django.contrib.auth.models import User
chandler = Handler()
class PlayerSession(async_chat):
"""
This class represents a player's sesssion. From here we branch down into
@ -53,7 +51,7 @@ class PlayerSession(async_chat):
self.cmd_last = time.time()
# Stuff anything we need to pass in this dictionary.
cdat = {"server": self.server, "uinput": uinput, "session": self}
chandler.handle(cdat)
cmdhandler.handle(cdat)
def handle_close(self):
"""