diff --git a/evennia/trunk/apps/objects/models.py b/evennia/trunk/apps/objects/models.py index aeda491f4e..6ca004b48a 100755 --- a/evennia/trunk/apps/objects/models.py +++ b/evennia/trunk/apps/objects/models.py @@ -84,14 +84,36 @@ class Object(models.Model): """ BEGIN COMMON METHODS """ - def move_to(self, target): + def load_to_location(self): """ - Moves the object to a new location. + Adds an object to its location. + """ + print 'Adding %s to %s.' % (self.id, self.location.id,) + self.location.contents_list.append(self) + + def get_contents(self): """ - self.location.contents_list.remove(self) - self.location = target - target.contents_list.append(self) - self.save() + Returns the contents of an object. + + TODO: Make this use the object's contents_list field. There's + something horribly long with the load routine right now. + """ + return list(Object.objects.filter(location__id=self.id)) + + def move_to(self, server, target): + """ + Moves the object to a new location. We're going to modify the server's + cached version of the object rather than the one we're given due + to the way references are passed. We can firm this up by other means + but this is more or less fool-proof for now. + """ + #if self in self.location.contents_list: + # self.location.contents_list.remove(self) + #target.contents_list.append(self) + + cached_object = server.get_object_from_dbref(self.id) + cached_object.location = target + cached_object.save() def dbref_match(self, oname): import functions_db @@ -130,6 +152,35 @@ class Object(models.Model): 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)] - + + # Type comparison methods. + def is_player(self): + return self.type is 1 + def is_room(self): + return self.type is 2 + def is_thing(self): + return self.type is 3 + def is_exit(self): + return self.type is 4 + def is_garbage(self): + return self.type is 5 + + def is_type(self, otype): + """ + See if an object is a certain type. + """ + otype = otype[0] + + if otype is 'p': + return self.is_player() + elif otype is 'r': + return self.is_room() + elif otype is 't': + return self.is_thing() + elif otype is 'e': + return self.is_exit() + elif otype is 'g': + return self.is_garbage() + def __str__(self): return "%s(%d)" % (self.name, self.id,) diff --git a/evennia/trunk/commands_general.py b/evennia/trunk/commands_general.py index cd81013457..2cf2cec8b5 100644 --- a/evennia/trunk/commands_general.py +++ b/evennia/trunk/commands_general.py @@ -1,6 +1,7 @@ import settings import time import functions_general +import functions_db from ansi import * """ @@ -13,17 +14,59 @@ def do_look(cdat): Handle looking at objects. """ session = cdat['session'] - player_loc_obj = session.pobject.location + pobject = session.pobject + args = cdat['uinput']['splitted'][1:] - retval = "%s%s%s%s\n\r%s" % ( + if len(args) == 0: + target_obj = session.pobject.location + else: + 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: + target_obj = results[0] + + retval = "%s%s%s(#%i)%s\r\n%s" % ( ansi["normal"], ansi["hilite"], - player_loc_obj.name, + target_obj.name, + target_obj.id, ansi["normal"], - player_loc_obj.description, + target_obj.description, ) session.msg(retval) + con_players = [] + con_things = [] + con_exits = [] + + for obj in target_obj.get_contents(): + if obj.is_player: + if obj != session.pobject: + con_players.append(obj) + elif obj.is_exit: + con_exits.append(obj) + else: + con_things.append(obj) + + if con_players: + session.msg("%sPlayers:%s" % (ansi["hilite"], ansi["normal"],)) + for player in con_players: + session.msg('%s(#%s)' %(player.name, player.id,)) + if con_things: + session.msg("%sThings:%s" % (ansi["hilite"], ansi["normal"],)) + for thing in con_things: + session.msg('%s(#%s)' %(thing.name, thing.id,)) + if con_exits: + session.msg("%sExits:%s" % (ansi["hilite"], ansi["normal"],)) + for exit in con_exits: + session.msg('%s(#%s)' %(exit.name, exit.id,)) + def do_quit(cdat): """ Gracefully disconnect the user as per his own request. @@ -69,7 +112,7 @@ def do_say(cdat): session_list = cdat['server'].session_list session = cdat['session'] speech = ''.join(cdat['uinput']['splitted'][1:]) - players_present = [player for player in session_list if player.player_loc == session.player_loc and player != session] + players_present = [player for player in session_list if player.pobject.location == session.pobject.location and player != session] retval = "You say, '%s'" % (speech,) for player in players_present: diff --git a/evennia/trunk/commands_staff.py b/evennia/trunk/commands_staff.py index 9c689513b7..bcab08f66c 100644 --- a/evennia/trunk/commands_staff.py +++ b/evennia/trunk/commands_staff.py @@ -1,6 +1,7 @@ from apps.objects.models import Object import functions_db import commands_general +import cmdhandler """ Restricted staff commands. @@ -47,15 +48,48 @@ def do_teleport(cdat): return eq_args = args[0].split('=') + search_str = ''.join(args) # If we have more than one entry in our '=' delimited argument list, # then we're doing a @tel =. If not, we're doing # a direct teleport, @tel . if len(eq_args) > 1: - session.msg("Equal sign present.") + # Equal sign teleport. + victim = functions_db.local_and_global_search(pobject, eq_args[0]) + destination = functions_db.local_and_global_search(pobject, eq_args[1]) + + if len(victim) == 0: + session.msg("I can't find the victim to teleport.") + return + elif len(destination) == 0: + session.msg("I can't find the destination for the victim.") + return + elif len(victim) > 1: + session.msg("Multiple results returned for victim!") + return + elif len(destination) > 1: + session.msg("Multiple results returned for destination!") + else: + if victim == destination: + session.msg("You can't teleport an object inside of itself!") + return + session.msg("Teleported.") + victim[0].move_to(server, destination[0]) + + # 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 = functions_db.session_from_object(server.session_list, victim[0]) + if victim_session: + # We need to form up a new cdat dictionary to pass with the command. + # Kinda yucky I guess. + cdat2 = {"server": server, "uinput": 'look', "session": victim_session} + cmdhandler.handle(cdat2) + else: - session.msg("No equal sign, direct tport.") - results = functions_db.local_and_global_search(pobject, ''.join(args)) + # Direct teleport (no equal sign) + results = functions_db.local_and_global_search(pobject, search_str) if len(results) > 1: session.msg("More than one match found (please narrow target):") @@ -63,9 +97,13 @@ def do_teleport(cdat): session.msg(" %s(#%s)" % (result.name, result.id,)) elif len(results) == 0: session.msg("I don't see that here.") + return else: + if results[0] == pobject: + session.msg("You can't teleport inside yourself!") + return session.msg("Teleported.") - pobject.move_to(results[0]) + pobject.move_to(server, results[0]) commands_general.do_look(cdat) #session.msg("Args: %s\n\rEqargs: %s" % (args, eq_args,)) diff --git a/evennia/trunk/functions_db.py b/evennia/trunk/functions_db.py index 143bf8c6e3..cbc1cc63a3 100644 --- a/evennia/trunk/functions_db.py +++ b/evennia/trunk/functions_db.py @@ -24,7 +24,7 @@ def local_and_global_search(object, ostring, local_only=False): if len(dbref_match) > 0: return dbref_match - local_matches = list_search_object_namestr(object.location.contents_list, search_query) + local_matches = list_search_object_namestr(object.location.get_contents(), search_query) # If the object the invoker is in matches, add it as well. if object.location.dbref_match(ostring) or ostring == 'here': @@ -48,4 +48,23 @@ def is_dbref(dbstring): else: return True - +def session_from_object(session_list, targobject): + """ + Return the session object given a object (if there is one open). + """ + results = [prospect for prospect in session_list if prospect.pobject == targobject] + if results: + return results[0] + else: + return False + +def session_from_dbref(session_list, dbstring): + """ + Return the session object given a dbref (if there is one open). + """ + if is_dbref(dbstring): + results = [prospect for prospect in session_list if prospect.pobject.dbref_match(dbstring)] + if results: + return results[0] + else: + return False diff --git a/evennia/trunk/server.py b/evennia/trunk/server.py index 974702b902..c777abd280 100755 --- a/evennia/trunk/server.py +++ b/evennia/trunk/server.py @@ -93,13 +93,19 @@ class Server(dispatcher): """ Populate the 'contents_list' list for each object. - TODO: Make this a lot more efficient or merge into - load_objects. + TODO: This thing is just completely shot. No idea what's going on but + it's bad mojo. """ - for key, object in self.object_list.iteritems(): - if object.location: - object.location.contents_list.append(object) + """ + object_list = Object.objects.all() + for object in object_list: + if object.location and not object.is_room(): + object.load_to_location() + #print 'Adding %s to %s' % (object.id, object.location.id,) + for object in object_list: + print 'OBJ: %s CON: %s' % (object.id, object.location,) print ' * Object Inventories Populated' + """ def load_attributes(self): """ @@ -133,12 +139,18 @@ class Server(dispatcher): """ BEGIN GENERAL METHODS """ + def get_object_from_dbref(self, dbref): + """ + Returns an object when given a dbref. + """ + return self.object_list.get(dbref, False) + def create_user(self, session, uname, email, password): """ Handles the creation of new users. """ start_room = int(self.get_configvalue('player_dbnum_start')) - start_room_obj = self.object_list[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 diff --git a/evennia/trunk/sessions.py b/evennia/trunk/sessions.py index a5b6e7495e..7d17a26c18 100755 --- a/evennia/trunk/sessions.py +++ b/evennia/trunk/sessions.py @@ -4,6 +4,7 @@ import socket, asyncore, time, sys import cmdhandler from apps.objects.models import Object from django.contrib.auth.models import User +import commands_general class PlayerSession(async_chat): """ @@ -26,8 +27,6 @@ class PlayerSession(async_chat): self.cmd_total = 0 # The time when the user connected. self.conn_time = time.time() - # Player's room location. Move this to a player sub-class. - self.player_loc = 1 def collect_incoming_data(self, data): """ @@ -79,11 +78,14 @@ class PlayerSession(async_chat): """ After the user has authenticated, handle logging him in. """ - self.pobject = Object.objects.filter(id=user.id)[0] + self.pobject = self.server.get_object_from_dbref(user.id) self.name = user.username self.logged_in = True self.conn_time = time.time() - self.msg("Logging in as %s." % (self.name,)) + + self.msg("You are now logged in as %s." % (self.name,)) + cdat = {"session": self, "uinput":'look', "server": self.server} + cmdhandler.handle(cdat) print "Login: %s" % (self,) def msg(self, message):