mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 12:37:16 +02:00
Re-organization of the command handler for the sake of efficiency and cleanliness.
This commit is contained in:
parent
703fddcb7f
commit
8352c939ff
5 changed files with 256 additions and 265 deletions
|
|
@ -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.")
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue