Big big update. Lots of reorganization and shuffling.

This commit is contained in:
Greg Taylor 2006-12-03 00:25:10 +00:00
parent 43f2167e74
commit 703fddcb7f
9 changed files with 345 additions and 178 deletions

View file

@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User
class ObjectClass(models.Model):
"""
Each object class can have different behaviors to apply to it.
@ -66,21 +67,63 @@ class Object(models.Model):
# attribute's names.
attrib_list = {}
def __str__(self):
return "%s(%d)" % (self.name, self.id,)
def is_type(self, typename):
"""
Do a string comparison of user's input and the object's type class object's
name.
"""
return self.type.name == typename
def set_type(self, typename):
"""
Sets a object's type.
"""
pass
class Meta:
permissions = (
("can_examine", "Can examine objects"),
)
class Admin:
list_display = ('name',)
"""
BEGIN COMMON METHODS
"""
def move_to(self, target):
"""
Moves the object to a new location.
"""
self.location.contents_list.remove(self)
self.location = target
target.contents_list.append(self)
self.save()
def dbref_match(self, oname):
import functions_db
"""
Check if the input (oname) can be used to identify this particular object
by means of a dbref match.
"""
if not functions_db.is_dbref(oname):
return False
try:
is_match = int(oname[1:]) == self.id
except ValueError:
return false
return is_match
def name_match(self, oname):
import functions_db
"""
See if the input (oname) can be used to identify this particular object.
Check the # sign for dbref (exact) reference, and anything else is a
name comparison.
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] == '#':
return self.dbref_match(oname)
else:
return oname.lower() in self.name.lower()
def filter_contents_from_str(self, oname):
"""
Search an object's contents for name and dbref matches. Don't put any
logic in here, we'll do that from the end of the command or function.
"""
return [prospect for prospect in self.contents_list if prospect.name_match(oname)]
def __str__(self):
return "%s(%d)" % (self.name, self.id,)

View file

@ -1,168 +1,11 @@
from django.contrib.auth.models import User
from apps.objects.models import Object
import settings
import string
from ansi import *
from commands_staff import StaffCommands
from commands_general import GenCommands
from commands_unloggedin import UnLoggedInCommands
"""
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.
"""
class GenCommands:
"""
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)
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)
class StaffCommands:
"""
Restricted staff commands.
"""
def do_dig(self, cdat):
"""
Digs a new room out.
"""
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"
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)
class UnLoggedInCommands:
"""
Commands that are available from the connect screen.
"""
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]
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)
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()
# We'll use this for our getattr() in the Handler class.
gencommands = GenCommands()
staffcommands = StaffCommands()

View file

@ -0,0 +1,72 @@
import settings
from ansi import *
class GenCommands:
"""
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)
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)

View file

@ -0,0 +1,95 @@
from apps.objects.models import Object
import functions_db
class StaffCommands:
"""
Restricted staff commands.
"""
def do_dig(self, cdat):
"""
Digs a new room out.
"""
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"
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.")
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,))

View file

@ -0,0 +1,54 @@
from django.contrib.auth.models import User
class UnLoggedInCommands:
"""
Commands that are available from the connect screen.
"""
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]
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)
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()

View file

@ -1,4 +1,4 @@
from apps.objects.models import Object, Attribute
def object_find_neighbor(searcher, target_string):
pass
def list_search_object_str(searchlist, ostring):
[prospect for prospect in searchlist if prospect.name_match(ostring)]

View file

@ -0,0 +1,47 @@
from apps.objects.models import Object
def list_search_object_namestr(searchlist, ostring, dbref_only=False):
"""
Iterates through a list of objects and returns a list of
name matches.
"""
if dbref_only:
return [prospect for prospect in searchlist if prospect.dbref_match(ostring)]
else:
return [prospect for prospect in searchlist if prospect.name_match(ostring)]
def local_and_global_search(object, ostring):
"""
Searches an object's location then globally for a dbref or name match.
"""
search_query = ''.join(ostring)
local_matches = list_search_object_namestr(object.location.contents_list, search_query)
# If the object the invoker is in matches, add it as well.
if object.location.dbref_match(ostring) or ostring == 'here':
local_matches.append(object.location)
global_matches = []
if is_dbref(ostring):
global_matches = list(Object.objects.filter(id=search_query))
return local_matches + global_matches
def is_dbref(dbstring):
"""
Is the input a well-formed dbref number?
"""
try:
number = int(dbstring[1:])
except ValueError:
return False
if dbstring[0] != '#':
return False
elif number < 1:
return False
else:
return True

View file

@ -51,6 +51,7 @@ class Server(dispatcher):
# Load stuff up into memory for easy/quick access.
self.load_configvalues()
self.load_objects()
self.load_objects_contents()
self.load_attributes()
self.load_cmd_aliases()
@ -87,7 +88,19 @@ class Server(dispatcher):
dbnum = object.id
self.object_list[dbnum] = object
print ' Objects Loaded: %d' % (len(self.object_list),)
def load_objects_contents(self):
"""
Populate the 'contents_list' list for each object.
TODO: Make this a lot more efficient or merge into
load_objects.
"""
for key, object in self.object_list.iteritems():
if object.location:
object.location.contents_list.append(object)
print ' * Object Inventories Populated'
def load_attributes(self):
"""
Load all of our attributes into memory.

View file

@ -81,7 +81,7 @@ class PlayerSession(async_chat):
"""
After the user has authenticated, handle logging him in.
"""
self.pobject = user
self.pobject = Object.objects.filter(id=user.id)[0]
self.name = user.username
self.logged_in = True
self.conn_time = time.time()