From ad009e20ab9c1890639f786b628e976e93e3cbd2 Mon Sep 17 00:00:00 2001 From: loki77 Date: Fri, 13 Jun 2008 18:15:54 +0000 Subject: [PATCH] basicobject.py --------------- - Checks for NULL description on objects- if Null, it doesn't print the extra line any more. - Made the checks for contents a little less ambiguous cmdhandler.py -------------- - Added new method 'parse_command' which takes a command string and tries to break it up based on common command parsing rules. Mostly complete, but could use some work on the edge cases. Check out the docstring on the function- I tried to make it fairly well documented. - Changed the check for 'non-standard characters' to just return, rather than throw an Exception. Not sure if this causes any issues, but I noticed that when you hit enter without entering a command it would trigger this code. Now it just fails silently. - The handle function now calls the parse_command function now and stores the results in parsed_input['parsed_command']. This then gets put into cdat['uinput'] at the end of handle() like before. The old data in parsed_input is still there, this is just a new field. - Added cdat['raw_input'] to pass the full, untouched command string on. This is also stored in parsed_input['parsed_command']['raw_command'] so not sure fi this is necessary any longer, probably not. cmdtable.py ------------ - Just cleaned it up a bit and straightened out the columns after changing 3-4 space indentation. apps/objects/models.py ----------------------- - set_description now sets the description attribute to 'None' (or Null in the db) when given a blank description. This is used for the change mentioned above in basicobject.py - get_description now returns None if self.description is None - used defines_global in the comparison methods like is_player functions_db.py ---------------- - Changed import defines_global as defines_global to just 'import defines_global'- wasn't sure why this was this way, if I broke something (I didn't seem to) let me know. - renamed player_search to player_name_search. Removed the use of local_and_global_search inside of it. local_and_global_search now calls it when it receives a search_string that starts with *. - alias_search now only looks at attributes with attr_name == ALIAS. It used to just look at attr_value, which could match anything, it seemed. - added 'dbref_search' - local_and_global_search changes: - Now uses dbref_search & player_search if the string starts with "#" or "*" respectively - Changed when it uses dbref_search to whenever the search_string is a dbref. It used to check that it was a dbref, and that search_contents & search_location were set, but I *believe* in most MU*'s when you supply a dbref it never fails to find the object. commands/unloggedin.py ----------------------- - removed hardcoded object type #'s and started using defines_global instead - when creating a new account, made sure that no object with an alias matching the player name requested exists. This is behavior from TinyMUSH, and I think most MUSHs follow this, but if not this is easy enough to change back. commands/general.py -------------------- - Rewrote cmd_page: - New Features - Page by dbref - Page multiple people - pose (:) and no space pose (;) pages - When someone hits page without a target or data, it now will tell the player who they last paged, or say they haven't paged anyone if they don't have a LASTPAGED - uses parse_command, made it a lot easier to work through the extra functionality added above - When there are multiple words in a page target, it first tries to find a player that matches the entire string. If that fails, then it goes through each word, assuming each is a separate target, and works out paging them. commands/objmanip.py --------------------- - I started to muck with cmd_name & cmd_page, but decided to hold off for now. Largely, if everyone is cool with the idea that names & aliases should be totally unique, then we need to go ahead and re-write these. I'll do that if everyone is cool with it. --- apps/objects/models.py | 1699 ++++++++++++++++++++-------------------- cmdhandler.py | 377 +++++---- cmdtable.py | 122 +-- commands/general.py | 951 +++++++++++----------- commands/objmanip.py | 926 +++++++++++----------- commands/unloggedin.py | 153 ++-- functions_db.py | 601 +++++++------- scripts/basicobject.py | 246 +++--- 8 files changed, 2634 insertions(+), 2441 deletions(-) diff --git a/apps/objects/models.py b/apps/objects/models.py index efbb6fe6e9..a8d04d62cd 100755 --- a/apps/objects/models.py +++ b/apps/objects/models.py @@ -9,869 +9,876 @@ import gameconf import ansi class Attribute(models.Model): - """ - Attributes are things that are specific to different types of objects. For - example, a drink container needs to store its fill level, whereas an exit - needs to store its open/closed/locked/unlocked state. These are done via - attributes, rather than making different classes for each object type and - storing them directly. The added benefit is that we can add/remove - attributes on the fly as we like. - """ - attr_name = models.CharField(max_length=255) - attr_value = models.CharField(max_length=255) - attr_hidden = models.BooleanField(default=0) - attr_object = models.ForeignKey("Object") - - def __str__(self): - return "%s(%s)" % (self.attr_name, self.id) - - class Admin: - list_display = ('attr_object', 'attr_name', 'attr_value',) - search_fields = ['attr_name'] - - """ - BEGIN COMMON METHODS - """ - def get_name(self): - """ - Returns an attribute's name. - """ - return self.attr_name - - def get_value(self): - """ - Returns an attribute's value. - """ - return self.attr_value - - def get_object(self): - """ - Returns the object that the attribute resides on. - """ - return self.attr_object - - def is_hidden(self): - """ - Returns True if the attribute is hidden. - """ - if self.attr_hidden or self.get_name().upper() in defines_global.HIDDEN_ATTRIBS: - return True - else: - return False + """ + Attributes are things that are specific to different types of objects. For + example, a drink container needs to store its fill level, whereas an exit + needs to store its open/closed/locked/unlocked state. These are done via + attributes, rather than making different classes for each object type and + storing them directly. The added benefit is that we can add/remove + attributes on the fly as we like. + """ + attr_name = models.CharField(max_length=255) + attr_value = models.CharField(max_length=255) + attr_hidden = models.BooleanField(default=0) + attr_object = models.ForeignKey("Object") + + def __str__(self): + return "%s(%s)" % (self.attr_name, self.id) + + class Admin: + list_display = ('attr_object', 'attr_name', 'attr_value',) + search_fields = ['attr_name'] + + """ + BEGIN COMMON METHODS + """ + def get_name(self): + """ + Returns an attribute's name. + """ + return self.attr_name + + def get_value(self): + """ + Returns an attribute's value. + """ + return self.attr_value + + def get_object(self): + """ + Returns the object that the attribute resides on. + """ + return self.attr_object + + def is_hidden(self): + """ + Returns True if the attribute is hidden. + """ + if self.attr_hidden or self.get_name().upper() in defines_global.HIDDEN_ATTRIBS: + return True + else: + return False - def is_noset(self): - """ - Returns True if the attribute is unsettable. - """ - if self.get_name().upper() in defines_global.NOSET_ATTRIBS: - return True - else: - return False - - def get_attrline(self): - """ - Best described as a __str__ method for in-game. Renders the attribute's - name and value as per MUX. - """ - return "%s%s%s: %s" % (ansi.ansi["hilite"], - self.get_name(), - ansi.ansi["normal"], - self.get_value()) + def is_noset(self): + """ + Returns True if the attribute is unsettable. + """ + if self.get_name().upper() in defines_global.NOSET_ATTRIBS: + return True + else: + return False + + def get_attrline(self): + """ + Best described as a __str__ method for in-game. Renders the attribute's + name and value as per MUX. + """ + return "%s%s%s: %s" % (ansi.ansi["hilite"], + self.get_name(), + ansi.ansi["normal"], + self.get_value()) class Object(models.Model): - """ - The Object class is very generic representation of a THING, PLAYER, EXIT, - ROOM, or other entities within the database. Pretty much anything in the - game is an object. Objects may be one of several different types, and - may be parented to allow for differing behaviors. - - We eventually want to find some way to implement object parents via loadable - modules or sub-classing. - """ - name = models.CharField(max_length=255) - ansi_name = models.CharField(max_length=255) - owner = models.ForeignKey('self', related_name="obj_owner", blank=True, null=True) - zone = models.ForeignKey('self', related_name="obj_zone", blank=True, null=True) - home = models.ForeignKey('self', related_name="obj_home", blank=True, null=True) - type = models.SmallIntegerField(choices=defines_global.OBJECT_TYPES) - # TODO: Move description to an attribute.s - description = models.TextField(blank=True, null=True) - location = models.ForeignKey('self', related_name="obj_location", blank=True, null=True) - flags = models.TextField(blank=True, null=True) - nosave_flags = models.TextField(blank=True, null=True) - date_created = models.DateField(editable=False, auto_now_add=True) - scriptlink = None - - def __cmp__(self, other): - """ - Used to figure out if one object is the same as another. - """ - return self.id == other.id - - def __str__(self): - return "%s" % (self.get_name(no_ansi=True),) - - class Meta: - ordering = ['-date_created', 'id'] - - class Admin: - list_display = ('id', 'name', 'type', 'date_created') - list_filter = ('type',) - search_fields = ['name'] - save_on_top = True - - """ - BEGIN COMMON METHODS - """ - def emit_to(self, message): - """ - Emits something to any sessions attached to the object. - - message: (str) The message to send - """ - # We won't allow emitting to objects... yet. - if not self.is_player(): - return False - - session = session_mgr.session_from_object(self) - if session: - session.msg(ansi.parse_ansi(message)) - else: - return False - - def emit_to_contents(self, message, exclude=None): - """ - Emits something to all objects inside an object. - """ - contents = self.get_contents() - - if exclude: - contents.remove(exclude) - - for obj in contents: - obj.emit_to(message) - - def is_staff(self): - """ - Returns TRUE if the object is a staff player. - """ - if not self.is_player(): - return False - - profile = User.objects.filter(id=self.id) - - if len(profile) == 0: - return False - else: - return profile[0].is_staff - - def is_superuser(self): - """ - Returns TRUE if the object is a super user player. - """ - if not self.is_player(): - return False - - profile = User.objects.filter(id=self.id) - - if len(profile) == 0: - return False - else: - return profile[0].is_superuser - - def user_has_perm(self, perm): - """ - Checks to see whether a user has the specified permission or is a super - user. - - perm: (string) A string representing the desired permission. - """ - if not self.is_player(): - return False - - if self.is_superuser(): - return True - - if self.get_user_account().has_perm(perm): - return True - else: - return False - - def user_has_perm_list(self, perm_list): - """ - Checks to see whether a user has the specified permission or is a super - user. This form accepts an iterable of strings representing permissions, - if the user has any of them return true. - - perm: (iterable) An iterable of strings of permissions. - """ - if not self.is_player(): - return False - - if self.is_superuser(): - return True - - for perm in perm_list: - # Stop searching perms on the first match. - if self.get_user_account().has_perm(perm): - return True - - # Fall through to failure - return False - - def owns_other(self, other_obj): - """ - See if the envoked object owns another object. - other_obj: (Object) Reference for object to check ownership of. - """ - return self.id == other_obj.get_owner().id - - def controls_other(self, other_obj): - """ - See if the envoked object controls another object. - other_obj: (Object) Reference for object to check dominance of. - """ - if self == other_obj: - return True - - if self.is_superuser(): - # Don't allow superusers to dominate other superusers. - if not other_obj.is_superuser(): - return True - else: - return False - - if self.owns_other(other_obj): - # If said object owns the target, then give it the green. - return True - - # They've failed to meet any of the above conditions. - return False - - def set_home(self, new_home): - """ - Sets an object's home. - """ - self.home = new_home - self.save() - - def set_name(self, new_name): - """ - Rename an object. - """ - self.name = ansi.parse_ansi(new_name, strip_ansi=True) - self.ansi_name = ansi.parse_ansi(new_name, strip_formatting=True) - self.save() - - # If it's a player, we need to update their user object as well. - if self.is_player(): - pobject = self.get_user_account() - pobject.username = new_name - pobject.save() - - def get_user_account(self): - """ - Returns the player object's account object (User object). - """ - if not self.is_player(): - return False - return User.objects.get(id=self.id) - - def get_name(self, fullname=False, show_dbref=True, no_ansi=False): - """ - Returns an object's name. - """ - if not no_ansi and self.ansi_name: - name_string = self.ansi_name - else: - name_string = self.name - - if show_dbref: - dbref_string = "(#%s%s)" % (self.id, self.flag_string()) - else: - dbref_string = "" - - if fullname: - return "%s%s" % (ansi.parse_ansi(name_string, strip_ansi=no_ansi), dbref_string) - else: - return "%s%s" % (ansi.parse_ansi(name_string.split(';')[0], strip_ansi=no_ansi), dbref_string) - - def set_description(self, new_desc): - """ - Rename an object. - """ - self.description = new_desc - self.save() - - def get_description(self, no_parsing=False, wrap_text=False): - """ - Returns an object's ANSI'd description. - """ - try: - # Evaluate ANSI and stuff? - if no_parsing: - retval = self.description - else: - retval = ansi.parse_ansi(self.description) - - # Default to a 78 character wrap. - if wrap_text: - return functions_general.word_wrap(retval) - else: - return retval - except: - # No description attribute present, return empty string. - return "" - - def get_flags(self): - """ - Returns an object's flag list. - """ - flags = self.flags - nosave_flags = self.nosave_flags - if not flags: - flags = "" - if not nosave_flags: - nosave_flags = "" - - return '%s %s' % (flags, nosave_flags) - - def clear_attribute(self, attribute): - """ - Removes an attribute entirely. - - attribute: (str) The attribute's name. - """ - if self.has_attribute(attribute): - attrib_obj = self.get_attribute_obj(attribute) - attrib_obj.delete() - return True - else: - return False - - def get_all_attributes(self): - """ - Returns a QuerySet of an object's attributes. - """ - return [attr for attr in self.attribute_set.all() if not attr.is_hidden()] - - def clear_all_attributes(self): - """ - Clears all of an object's attributes. - """ - attribs = self.get_all_attributes() - for attrib in attribs: - attrib.delete() - - def destroy(self): - """ - Destroys an object, sets it to GOING. Can still be recovered - if the user decides to. - """ - - # See if we need to kick the player off. - session = session_mgr.session_from_object(self) - if session: - session.msg("You have been destroyed, goodbye.") - session.handle_close() - - # If the object is a player, set the player account object to inactive. - # It can still be recovered at this point. - if self.is_player(): - try: - uobj = User.objects.get(id=self.id) - uobj.is_active = False - uobj.save() - except: - functions_general.log_errmsg('Destroying object %s but no matching player.' % (self,)) - - # Set the object type to GOING - self.type = 5 - # Destroy any exits to and from this room, do this first - self.clear_exits() - # Clear out any objects located within the object - self.clear_objects() - self.save() - - def delete(self): - """ - Deletes an object permanently. Marks it for re-use by a new object. - """ - # Delete the associated player object permanently. - uobj = User.objects.filter(id=self.id) - if len(uobj) > 0: - uobj[0].delete() - - # Set the object to type GARBAGE. - self.type = 6 - self.save() - - # Clear all attributes - self.clear_all_attributes() - - def clear_exits(self): - """ - Destroys all of the exits and any exits pointing to this - object as a destination. - """ - exits = self.get_contents(filter_type=4) - exits += self.obj_home.all().filter(type__exact=4) - - for exit in exits: - exit.destroy() - - def clear_objects(self): - """ - Moves all objects (players/things) currently in a GOING -> GARBAGE location - to their home or default home (if it can be found). - """ - # Gather up everything, other than exits and going/garbage, that is under - # the belief this is its location. - objs = self.obj_location.filter(type__in=[1,2,3]) - default_home_id = gameconf.get_configvalue('default_home') - try: - default_home = Object.objects.get(id=default_home_id) - except: - functions_general.log_errmsg("Could not find default home '(#%d)'." % (default_home_id)) - - for obj in objs: - home = obj.get_home() - text = "object" - - if obj.is_player(): - text = "player" - - # Obviously, we can't send it back to here. - if home.id == self.id: - obj.home = default_home - obj.save() - home = default_home - - # If for some reason it's still None... - if not home: - functions_general.log_errmsg("Missing default home, %s '%s(#%d)' now has a null location." % (text, obj.name, obj.id)) - - if obj.is_player(): - if obj.is_connected_plr(): - if home: - obj.emit_to("Your current location has ceased to exist, moving you to your home %s(#%d)." % (home.name, home.id)) - else: - # Famous last words: The player should never see this. - 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.save() - - def set_attribute(self, attribute, new_value): - """ - Sets an attribute on an object. Creates the attribute if need - be. - - attribute: (str) The attribute's name. - new_value: (str) The value to set the attribute to. - """ - if self.has_attribute(attribute): - # Attribute already exists, update it. - attrib_obj = Attribute.objects.filter(attr_object=self).filter(attr_name__iexact=attribute)[0] - attrib_obj.attr_value = new_value - attrib_obj.save() - else: - # Attribute object doesn't exist, create it. - new_attrib = Attribute() - new_attrib.attr_name = attribute - new_attrib.attr_value = new_value - new_attrib.attr_object = self - new_attrib.attr_hidden = False - new_attrib.save() - - def has_attribute(self, attribute): - """ - See if we have an attribute set on the object. - - attribute: (str) The attribute's name. - """ - attr = Attribute.objects.filter(attr_object=self).filter(attr_name__iexact=attribute) - if attr.count() == 0: - return False - else: - return True - - def attribute_namesearch(self, searchstr, exclude_noset=False): - """ - Searches the object's attributes for name matches against searchstr - via regular expressions. Returns a list. - - searchstr: (str) A string (maybe with wildcards) to search for. - """ - # Retrieve the list of attributes for this object. - 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) - # 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()] - else: - return [attr for attr in attrs if match_exp.search(attr.get_name()) and not attr.is_hidden()] - - def has_flag(self, flag): - """ - Does our object have a certain flag? - - flag: (str) Flag name - """ - # For whatever reason, we have to do this so things work - # in SQLite. - flags = str(self.flags).split() - nosave_flags = str(self.nosave_flags).split() - return flag in flags or flag in nosave_flags - - def set_flag(self, flag, value): - """ - Add a flag to our object's flag list. - - flag: (str) Flag name - value: (bool) Set (True) or un-set (False) - """ - flag = flag.upper() - has_flag = self.has_flag(flag) - - if value == False and has_flag: - # Clear the flag. - if functions_db.is_unsavable_flag(flag): - # Not a savable flag (CONNECTED, etc) - flags = self.nosave_flags.split() - flags.remove(flag) - self.nosave_flags = ' '.join(flags) - else: - # Is a savable flag. - flags = self.flags.split() - flags.remove(flag) - self.flags = ' '.join(flags) - self.save() - - elif value == False and not has_flag: - # Object doesn't have the flag to begin with. - pass - elif value == True and has_flag: - # We've already go it. - pass - else: - # Setting a flag. - if functions_db.is_unsavable_flag(flag): - # Not a savable flag (CONNECTED, etc) - flags = str(self.nosave_flags).split() - flags.append(flag) - self.nosave_flags = ' '.join(flags) - else: - # Is a savable flag. - flags = str(self.flags).split() - flags.append(flag) - self.flags = ' '.join(flags) - self.save() - - def is_connected_plr(self): - """ - Is this object a connected player? - """ - if self.is_player(): - if session_mgr.session_from_object(self): - return True - else: - return False - else: - return False - - def get_owner(self): - """ - Returns an object's owner. - """ - # Players always own themselves. - if self.is_player(): - return self - else: - return self.owner - - def get_home(self): - """ - Returns an object's home. - """ - try: - return self.home - except: - return None - - def get_location(self): - """ - Returns an object's location. - """ - try: - return self.location - except: - functions_general.log_errmsg("Object '%s(#%d)' has invalid location: #%s" % (self.name,self.id,self.location_id)) - return False - - def get_scriptlink(self): - """ - Returns an object's script parent. - """ - if not self.scriptlink: - self.scriptlink = scripthandler.scriptlink(self, self.get_attribute_value('__parent', 'basicobject')) - - if self.scriptlink: - # If the scriptlink variable can't be populated, this will fail - # silently and let the exception hit in the scripthandler. - return self.scriptlink - return None - - def get_attribute_value(self, attrib, default=False): - """ - Returns the value of an attribute on an object. You may need to - type cast the returned value from this function! - - attrib: (str) The attribute's name. - """ - if self.has_attribute(attrib): - attrib = Attribute.objects.filter(attr_object=self).filter(attr_name=attrib) - return attrib[0].attr_value - else: - if default: - return default - else: - return False - - def get_attribute_obj(self, attrib): - """ - Returns the attribute object matching the specified name. - - attrib: (str) The attribute's name. - """ - if self.has_attribute(attrib): - return Attribute.objects.filter(attr_object=self).filter(attr_name=attrib) - else: - return False - - def get_contents(self, filter_type=None): - """ - Returns the contents of an object. - - filter_type: (int) An object type number to filter by. - """ - if filter_type: - return list(Object.objects.filter(location__id=self.id).filter(type=filter_type)) - else: - return list(Object.objects.filter(location__id=self.id).exclude(type__gt=4)) - - def get_zone(self): - """ - Returns the object that is marked as this object's zone. - """ - try: - return self.zone - except: - return None - - def move_to(self, target, quiet=False): - """ - 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. - """ - if not quiet: - if self.get_location(): - self.get_location().emit_to_contents("%s has left." % (self.get_name(),), exclude=self) - - self.location = target - self.save() - - if not quiet: - self.get_location().emit_to_contents("%s has arrived." % (self.get_name(),), exclude=self) - - def dbref_match(self, oname): - """ - Check if the input (oname) can be used to identify this particular object - by means of a dbref match. - - oname: (str) Name to match against. - """ - 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, match_type="fuzzy"): - """ - 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] == '#': - # First character is a pound sign, looks to be a dbref. - return self.dbref_match(oname) - elif match_type == "exact": - # Exact matching - name_chunks = self.name.lower().split(';') - for chunk in name_chunks: - if oname.lower() == chunk: - return True - return False - else: - # Fuzzy matching. - 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. - - oname: (str) The string to filter from. - """ - contents = self.get_contents() - return [prospect for prospect in contents if prospect.name_match(oname)] - - # Type comparison methods. - def is_player(self): - return self.type == 1 - def is_room(self): - return self.type == 2 - def is_thing(self): - return self.type == 3 - def is_exit(self): - return self.type == 4 - def is_going(self): - return self.type == 5 - def is_garbage(self): - return self.type == 6 - - def get_type(self, return_number=False): - """ - Returns the numerical or string representation of an object's type. - - return_number: (bool) True returns numeric type, False returns string. - """ - if return_number: - return self.type - else: - return defines_global.OBJECT_TYPES[self.type][1] + """ + The Object class is very generic representation of a THING, PLAYER, EXIT, + ROOM, or other entities within the database. Pretty much anything in the + game is an object. Objects may be one of several different types, and + may be parented to allow for differing behaviors. - def is_type(self, otype): - """ - See if an object is a certain type. - - otype: (str) A string representation of the object's type (ROOM, THING) - """ - otype = otype[0] - - if otype == 'p': - return self.is_player() - elif otype == 'r': - return self.is_room() - elif otype == 't': - return self.is_thing() - elif otype == 'e': - return self.is_exit() - elif otype == 'g': - return self.is_garbage() + We eventually want to find some way to implement object parents via loadable + modules or sub-classing. + """ + name = models.CharField(max_length=255) + ansi_name = models.CharField(max_length=255) + owner = models.ForeignKey('self', related_name="obj_owner", blank=True, null=True) + zone = models.ForeignKey('self', related_name="obj_zone", blank=True, null=True) + home = models.ForeignKey('self', related_name="obj_home", blank=True, null=True) + type = models.SmallIntegerField(choices=defines_global.OBJECT_TYPES) + # TODO: Move description to an attribute.s + description = models.TextField(blank=True, null=True) + location = models.ForeignKey('self', related_name="obj_location", blank=True, null=True) + flags = models.TextField(blank=True, null=True) + nosave_flags = models.TextField(blank=True, null=True) + date_created = models.DateField(editable=False, auto_now_add=True) + scriptlink = None - def flag_string(self): - """ - Returns the flag string for an object. This abbreviates all of the flags - set on the object into a list of single-character flag characters. - """ - # We have to cast this because the admin interface is really picky - # about tuple index types. Bleh. - otype = int(self.type) - return defines_global.OBJECT_TYPES[otype][1][0] + def __cmp__(self, other): + """ + Used to figure out if one object is the same as another. + """ + return self.id == other.id + + def __str__(self): + return "%s" % (self.get_name(no_ansi=True),) + + class Meta: + ordering = ['-date_created', 'id'] + + class Admin: + list_display = ('id', 'name', 'type', 'date_created') + list_filter = ('type',) + search_fields = ['name'] + save_on_top = True + + """ + BEGIN COMMON METHODS + """ + def emit_to(self, message): + """ + Emits something to any sessions attached to the object. + + message: (str) The message to send + """ + # We won't allow emitting to objects... yet. + if not self.is_player(): + return False + + session = session_mgr.session_from_object(self) + if session: + session.msg(ansi.parse_ansi(message)) + else: + return False + + def emit_to_contents(self, message, exclude=None): + """ + Emits something to all objects inside an object. + """ + contents = self.get_contents() + + if exclude: + contents.remove(exclude) + + for obj in contents: + obj.emit_to(message) + + def is_staff(self): + """ + Returns TRUE if the object is a staff player. + """ + if not self.is_player(): + return False + + profile = User.objects.filter(id=self.id) + + if len(profile) == 0: + return False + else: + return profile[0].is_staff + + def is_superuser(self): + """ + Returns TRUE if the object is a super user player. + """ + if not self.is_player(): + return False + + profile = User.objects.filter(id=self.id) + + if len(profile) == 0: + return False + else: + return profile[0].is_superuser + + def user_has_perm(self, perm): + """ + Checks to see whether a user has the specified permission or is a super + user. + + perm: (string) A string representing the desired permission. + """ + if not self.is_player(): + return False + + if self.is_superuser(): + return True + + if self.get_user_account().has_perm(perm): + return True + else: + return False + + def user_has_perm_list(self, perm_list): + """ + Checks to see whether a user has the specified permission or is a super + user. This form accepts an iterable of strings representing permissions, + if the user has any of them return true. + + perm: (iterable) An iterable of strings of permissions. + """ + if not self.is_player(): + return False + + if self.is_superuser(): + return True + + for perm in perm_list: + # Stop searching perms on the first match. + if self.get_user_account().has_perm(perm): + return True + + # Fall through to failure + return False + + def owns_other(self, other_obj): + """ + See if the envoked object owns another object. + other_obj: (Object) Reference for object to check ownership of. + """ + return self.id == other_obj.get_owner().id + + def controls_other(self, other_obj): + """ + See if the envoked object controls another object. + other_obj: (Object) Reference for object to check dominance of. + """ + if self == other_obj: + return True + + if self.is_superuser(): + # Don't allow superusers to dominate other superusers. + if not other_obj.is_superuser(): + return True + else: + return False + + if self.owns_other(other_obj): + # If said object owns the target, then give it the green. + return True + + # They've failed to meet any of the above conditions. + return False + + def set_home(self, new_home): + """ + Sets an object's home. + """ + self.home = new_home + self.save() + + def set_name(self, new_name): + """ + Rename an object. + """ + self.name = ansi.parse_ansi(new_name, strip_ansi=True) + self.ansi_name = ansi.parse_ansi(new_name, strip_formatting=True) + self.save() + + # If it's a player, we need to update their user object as well. + if self.is_player(): + pobject = self.get_user_account() + pobject.username = new_name + pobject.save() + + def get_user_account(self): + """ + Returns the player object's account object (User object). + """ + if not self.is_player(): + return False + return User.objects.get(id=self.id) + + def get_name(self, fullname=False, show_dbref=True, no_ansi=False): + """ + Returns an object's name. + """ + if not no_ansi and self.ansi_name: + name_string = self.ansi_name + else: + name_string = self.name + + if show_dbref: + dbref_string = "(#%s%s)" % (self.id, self.flag_string()) + else: + dbref_string = "" + + if fullname: + return "%s%s" % (ansi.parse_ansi(name_string, strip_ansi=no_ansi), dbref_string) + else: + return "%s%s" % (ansi.parse_ansi(name_string.split(';')[0], strip_ansi=no_ansi), dbref_string) + + def set_description(self, new_desc): + """ + Set an objects description + """ + if new_desc == '': + self.description = None + else: + self.description = new_desc + self.save() + + def get_description(self, no_parsing=False, wrap_text=False): + """ + Returns an object's ANSI'd description or None if description is not + set. + """ + try: + # If no description is set, return None + if self.description is None: + return None + # Evaluate ANSI and stuff? + if no_parsing: + retval = self.description + else: + retval = ansi.parse_ansi(self.description) + + # Default to a 78 character wrap. + if wrap_text: + return functions_general.word_wrap(retval) + else: + return retval + except: + # No description attribute present, return empty string. + return None + + def get_flags(self): + """ + Returns an object's flag list. + """ + flags = self.flags + nosave_flags = self.nosave_flags + if not flags: + flags = "" + if not nosave_flags: + nosave_flags = "" + + return '%s %s' % (flags, nosave_flags) + + def clear_attribute(self, attribute): + """ + Removes an attribute entirely. + + attribute: (str) The attribute's name. + """ + if self.has_attribute(attribute): + attrib_obj = self.get_attribute_obj(attribute) + attrib_obj.delete() + return True + else: + return False + + def get_all_attributes(self): + """ + Returns a QuerySet of an object's attributes. + """ + return [attr for attr in self.attribute_set.all() if not attr.is_hidden()] + + def clear_all_attributes(self): + """ + Clears all of an object's attributes. + """ + attribs = self.get_all_attributes() + for attrib in attribs: + attrib.delete() + + def destroy(self): + """ + Destroys an object, sets it to GOING. Can still be recovered + if the user decides to. + """ + + # See if we need to kick the player off. + session = session_mgr.session_from_object(self) + if session: + session.msg("You have been destroyed, goodbye.") + session.handle_close() + + # If the object is a player, set the player account object to inactive. + # It can still be recovered at this point. + if self.is_player(): + try: + uobj = User.objects.get(id=self.id) + uobj.is_active = False + uobj.save() + except: + functions_general.log_errmsg('Destroying object %s but no matching player.' % (self,)) + + # Set the object type to GOING + self.type = 5 + # Destroy any exits to and from this room, do this first + self.clear_exits() + # Clear out any objects located within the object + self.clear_objects() + self.save() + + def delete(self): + """ + Deletes an object permanently. Marks it for re-use by a new object. + """ + # Delete the associated player object permanently. + uobj = User.objects.filter(id=self.id) + if len(uobj) > 0: + uobj[0].delete() + + # Set the object to type GARBAGE. + self.type = 6 + self.save() + + # Clear all attributes + self.clear_all_attributes() + + def clear_exits(self): + """ + Destroys all of the exits and any exits pointing to this + object as a destination. + """ + exits = self.get_contents(filter_type=4) + exits += self.obj_home.all().filter(type__exact=4) + + for exit in exits: + exit.destroy() + + def clear_objects(self): + """ + Moves all objects (players/things) currently in a GOING -> GARBAGE location + to their home or default home (if it can be found). + """ + # Gather up everything, other than exits and going/garbage, that is under + # the belief this is its location. + objs = self.obj_location.filter(type__in=[1,2,3]) + default_home_id = gameconf.get_configvalue('default_home') + try: + default_home = Object.objects.get(id=default_home_id) + except: + functions_general.log_errmsg("Could not find default home '(#%d)'." % (default_home_id)) + + for obj in objs: + home = obj.get_home() + text = "object" + + if obj.is_player(): + text = "player" + + # Obviously, we can't send it back to here. + if home.id == self.id: + obj.home = default_home + obj.save() + home = default_home + + # If for some reason it's still None... + if not home: + functions_general.log_errmsg("Missing default home, %s '%s(#%d)' now has a null location." % (text, obj.name, obj.id)) + + if obj.is_player(): + if obj.is_connected_plr(): + if home: + obj.emit_to("Your current location has ceased to exist, moving you to your home %s(#%d)." % (home.name, home.id)) + else: + # Famous last words: The player should never see this. + 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.save() + + def set_attribute(self, attribute, new_value): + """ + Sets an attribute on an object. Creates the attribute if need + be. + + attribute: (str) The attribute's name. + new_value: (str) The value to set the attribute to. + """ + if self.has_attribute(attribute): + # Attribute already exists, update it. + attrib_obj = Attribute.objects.filter(attr_object=self).filter(attr_name__iexact=attribute)[0] + attrib_obj.attr_value = new_value + attrib_obj.save() + else: + # Attribute object doesn't exist, create it. + new_attrib = Attribute() + new_attrib.attr_name = attribute + new_attrib.attr_value = new_value + new_attrib.attr_object = self + new_attrib.attr_hidden = False + new_attrib.save() + + def has_attribute(self, attribute): + """ + See if we have an attribute set on the object. + + attribute: (str) The attribute's name. + """ + attr = Attribute.objects.filter(attr_object=self).filter(attr_name__iexact=attribute) + if attr.count() == 0: + return False + else: + return True + + def attribute_namesearch(self, searchstr, exclude_noset=False): + """ + Searches the object's attributes for name matches against searchstr + via regular expressions. Returns a list. + + searchstr: (str) A string (maybe with wildcards) to search for. + """ + # Retrieve the list of attributes for this object. + 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) + # 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()] + else: + return [attr for attr in attrs if match_exp.search(attr.get_name()) and not attr.is_hidden()] + + def has_flag(self, flag): + """ + Does our object have a certain flag? + + flag: (str) Flag name + """ + # For whatever reason, we have to do this so things work + # in SQLite. + flags = str(self.flags).split() + nosave_flags = str(self.nosave_flags).split() + return flag in flags or flag in nosave_flags + + def set_flag(self, flag, value): + """ + Add a flag to our object's flag list. + + flag: (str) Flag name + value: (bool) Set (True) or un-set (False) + """ + flag = flag.upper() + has_flag = self.has_flag(flag) + + if value == False and has_flag: + # Clear the flag. + if functions_db.is_unsavable_flag(flag): + # Not a savable flag (CONNECTED, etc) + flags = self.nosave_flags.split() + flags.remove(flag) + self.nosave_flags = ' '.join(flags) + else: + # Is a savable flag. + flags = self.flags.split() + flags.remove(flag) + self.flags = ' '.join(flags) + self.save() + + elif value == False and not has_flag: + # Object doesn't have the flag to begin with. + pass + elif value == True and has_flag: + # We've already go it. + pass + else: + # Setting a flag. + if functions_db.is_unsavable_flag(flag): + # Not a savable flag (CONNECTED, etc) + flags = str(self.nosave_flags).split() + flags.append(flag) + self.nosave_flags = ' '.join(flags) + else: + # Is a savable flag. + flags = str(self.flags).split() + flags.append(flag) + self.flags = ' '.join(flags) + self.save() + + def is_connected_plr(self): + """ + Is this object a connected player? + """ + if self.is_player(): + if session_mgr.session_from_object(self): + return True + else: + return False + else: + return False + + def get_owner(self): + """ + Returns an object's owner. + """ + # Players always own themselves. + if self.is_player(): + return self + else: + return self.owner + + def get_home(self): + """ + Returns an object's home. + """ + try: + return self.home + except: + return None + + def get_location(self): + """ + Returns an object's location. + """ + try: + return self.location + except: + functions_general.log_errmsg("Object '%s(#%d)' has invalid location: #%s" % (self.name,self.id,self.location_id)) + return False + + def get_scriptlink(self): + """ + Returns an object's script parent. + """ + if not self.scriptlink: + self.scriptlink = scripthandler.scriptlink(self, self.get_attribute_value('__parent', 'basicobject')) + + if self.scriptlink: + # If the scriptlink variable can't be populated, this will fail + # silently and let the exception hit in the scripthandler. + return self.scriptlink + return None + + def get_attribute_value(self, attrib, default=False): + """ + Returns the value of an attribute on an object. You may need to + type cast the returned value from this function! + + attrib: (str) The attribute's name. + """ + if self.has_attribute(attrib): + attrib = Attribute.objects.filter(attr_object=self).filter(attr_name=attrib) + return attrib[0].attr_value + else: + if default: + return default + else: + return False + + def get_attribute_obj(self, attrib): + """ + Returns the attribute object matching the specified name. + + attrib: (str) The attribute's name. + """ + if self.has_attribute(attrib): + return Attribute.objects.filter(attr_object=self).filter(attr_name=attrib) + else: + return False + + def get_contents(self, filter_type=None): + """ + Returns the contents of an object. + + filter_type: (int) An object type number to filter by. + """ + if filter_type: + return list(Object.objects.filter(location__id=self.id).filter(type=filter_type)) + else: + return list(Object.objects.filter(location__id=self.id).exclude(type__gt=4)) + + def get_zone(self): + """ + Returns the object that is marked as this object's zone. + """ + try: + return self.zone + except: + return None + + def move_to(self, target, quiet=False): + """ + 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. + """ + if not quiet: + if self.get_location(): + self.get_location().emit_to_contents("%s has left." % (self.get_name(),), exclude=self) + + self.location = target + self.save() + + if not quiet: + self.get_location().emit_to_contents("%s has arrived." % (self.get_name(),), exclude=self) + + def dbref_match(self, oname): + """ + Check if the input (oname) can be used to identify this particular object + by means of a dbref match. + + oname: (str) Name to match against. + """ + 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, match_type="fuzzy"): + """ + 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] == '#': + # First character is a pound sign, looks to be a dbref. + return self.dbref_match(oname) + elif match_type == "exact": + # Exact matching + name_chunks = self.name.lower().split(';') + for chunk in name_chunks: + if oname.lower() == chunk: + return True + return False + else: + # Fuzzy matching. + 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. + + oname: (str) The string to filter from. + """ + contents = self.get_contents() + return [prospect for prospect in contents if prospect.name_match(oname)] + + # Type comparison methods. + def is_player(self): + return self.type == defines_global.OTYPE_PLAYER + def is_room(self): + return self.type == defines_global.OTYPE_ROOM + def is_thing(self): + return self.type == defines_global.OTYPE_THING + def is_exit(self): + return self.type == defines_global.OTYPE_EXIT + def is_going(self): + return self.type == defines_global.OTYPE_GOING + def is_garbage(self): + return self.type == defines_global.OTYPE_GARBAGE + + def get_type(self, return_number=False): + """ + Returns the numerical or string representation of an object's type. + + return_number: (bool) True returns numeric type, False returns string. + """ + if return_number: + return self.type + else: + return defines_global.OBJECT_TYPES[self.type][1] + + def is_type(self, otype): + """ + See if an object is a certain type. + + otype: (str) A string representation of the object's type (ROOM, THING) + """ + otype = otype[0] + + if otype == 'p': + return self.is_player() + elif otype == 'r': + return self.is_room() + elif otype == 't': + return self.is_thing() + elif otype == 'e': + return self.is_exit() + elif otype == 'g': + return self.is_garbage() + + def flag_string(self): + """ + Returns the flag string for an object. This abbreviates all of the flags + set on the object into a list of single-character flag characters. + """ + # We have to cast this because the admin interface is really picky + # about tuple index types. Bleh. + otype = int(self.type) + return defines_global.OBJECT_TYPES[otype][1][0] class CommChannel(models.Model): - """ - The CommChannel class represents a comsys channel in the vein of MUX/MUSH. - """ - name = models.CharField(max_length=255) - ansi_name = models.CharField(max_length=255) - owner = models.ForeignKey(Object, related_name="chan_owner") - description = models.CharField(max_length=80) - req_grp = models.ManyToManyField(Group, blank=True, null=True) + """ + The CommChannel class represents a comsys channel in the vein of MUX/MUSH. + """ + name = models.CharField(max_length=255) + ansi_name = models.CharField(max_length=255) + owner = models.ForeignKey(Object, related_name="chan_owner") + description = models.CharField(max_length=80) + req_grp = models.ManyToManyField(Group, blank=True, null=True) - def __str__(self): - return "%s" % (self.name,) - - class Meta: - ordering = ['-name'] - permissions = ( - ("emit_commchannel", "May @cemit over channels."), - ) - - class Admin: - list_display = ('name', 'owner') + def __str__(self): + return "%s" % (self.name,) + + class Meta: + ordering = ['-name'] + permissions = ( + ("emit_commchannel", "May @cemit over channels."), + ) + + class Admin: + list_display = ('name', 'owner') - def get_name(self): - """ - Returns a channel's name. - """ - return self.name + def get_name(self): + """ + Returns a channel's name. + """ + return self.name - def get_header(self): - """ - Returns the channel's header text, or what is shown before each channel - message. - """ - return ansi.parse_ansi(self.ansi_name) + def get_header(self): + """ + Returns the channel's header text, or what is shown before each channel + message. + """ + return ansi.parse_ansi(self.ansi_name) - def get_owner(self): - """ - Returns a channels' owner. - """ - return self.owner + def get_owner(self): + """ + Returns a channels' owner. + """ + return self.owner - def set_name(self, new_name): - """ - Rename a channel - """ - self.name = ansi.parse_ansi(new_name, strip_ansi=True) - self.header = "[%s]" % (ansi.parse_ansi(new_name),) - self.save() + def set_name(self, new_name): + """ + Rename a channel + """ + self.name = ansi.parse_ansi(new_name, strip_ansi=True) + self.header = "[%s]" % (ansi.parse_ansi(new_name),) + self.save() - def set_header(self, new_header): - """ - Sets a channel's header text. - """ - self.header = ansi.parse_ansi(new_header) - self.save() + def set_header(self, new_header): + """ + Sets a channel's header text. + """ + self.header = ansi.parse_ansi(new_header) + self.save() - def set_owner(self, new_owner): - """ - Sets a channel's owner. - """ - self.owner = new_owner - self.save() + def set_owner(self, new_owner): + """ + Sets a channel's owner. + """ + self.owner = new_owner + self.save() class CommChannelMessage(models.Model): - """ - A single logged channel message. - """ - channel = models.ForeignKey(CommChannel, related_name="msg_channel") - message = models.CharField(max_length=255) - date_sent = models.DateTimeField(editable=False, auto_now_add=True) + """ + A single logged channel message. + """ + channel = models.ForeignKey(CommChannel, related_name="msg_channel") + message = models.CharField(max_length=255) + date_sent = models.DateTimeField(editable=False, auto_now_add=True) - def __str__(self): - return "%s: %s" % (self.sender.name, self.message) - - class Meta: - ordering = ['-date_sent'] - - class Admin: - list_display = ('channel', 'message') + def __str__(self): + return "%s: %s" % (self.sender.name, self.message) + + class Meta: + ordering = ['-date_sent'] + + class Admin: + list_display = ('channel', 'message') import functions_db import functions_general diff --git a/cmdhandler.py b/cmdhandler.py index 56939f0915..e23a9cef20 100755 --- a/cmdhandler.py +++ b/cmdhandler.py @@ -14,170 +14,245 @@ something. """ class UnknownCommand(Exception): - """ - Throw this when a user enters an an invalid command. - """ + """ + Throw this when a user enters an an invalid command. + """ 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 functions_db.list_search_object_namestr(exits, searchstr, match_type="exact") + """ + See if we can find an input match to exits. + """ + exits = pobject.get_location().get_contents(filter_type=4) + return functions_db.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] [/option]= + - Simple: + look + look + + 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 /= + - Ends up considering both targets as one with a space between them, and the switch as a switch. + @pemit / = + - 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 = + # 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): - """ - Use the spliced (list) uinput variable to retrieve the correct - command, or return an invalid command error. + """ + 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 'cmd_' 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 = {} - - # 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']) - - # This will hold the reference to the command's function. - cmd = None - - if session.logged_in: - # Store the timestamp of the user's last command. - session.cmd_last = time.time() - - # Lets the users get around badly configured NAT timeouts. - if parsed_input['root_cmd'] == 'idle': + We're basically grabbing the player's command by tacking + their input on to 'cmd_' and looking it up in the GenCommands + class. + """ + session = cdat['session'] + server = cdat['server'] + + try: + # TODO: Protect against non-standard characters. + if cdat['uinput'] == '': return - # Increment our user's command counter. - session.cmd_total += 1 - # Player-visible idle time, not used in idle timeout calcs. - session.cmd_last_visible = time.time() + parsed_input = {} + parsed_input['parsed_command'] = parse_command(cdat['uinput']) - # Just in case. Prevents some really funky-case crashes. - if len(parsed_input['root_cmd']) == 0: - raise UnknownCommand + # 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'] - # 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 functions_comsys.plr_has_channel(session, - parsed_input['root_cmd'], - alias_search=True, - return_muted=True): - - calias = parsed_input['root_cmd'] - cname = functions_comsys.plr_cname_from_alias(session, calias) - cmessage = ' '.join(parsed_input['splitted'][1:]) - - if cmessage == "who": - functions_comsys.msg_cwho(session, cname) - return - elif cmessage == "on": - functions_comsys.plr_chan_on(session, calias) - return - elif cmessage == "off": - functions_comsys.plr_chan_off(session, calias) - return - elif cmessage == "last": - functions_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' + # 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']) - # Get the command's function reference (Or False) - cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd']) - if cmdtuple: - # If there is a permissions element to the entry, check perms. - if cmdtuple[1]: - if not session.get_pobject().user_has_perm_list(cmdtuple[1]): - session.msg(defines_global.NOPERMS_MSG) - return - # If flow reaches this point, user has perms and command is ready. - cmd = cmdtuple[0] - - else: - # Not logged in, look through the unlogged-in command table. - cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd'], unlogged_cmd=True) - if cmdtuple: - cmd = cmdtuple[0] + # This will hold the reference to the command's function. + cmd = None - # Debugging stuff. - #session.msg("ROOT : %s" % (parsed_input['root_cmd'],)) - #session.msg("SPLIT: %s" % (parsed_input['splitted'],)) - - if callable(cmd): - cdat['uinput'] = parsed_input - try: - cmd(cdat) - except: - session.msg("Untrapped error, please file a bug report:\n%s" % (format_exc(),)) - functions_general.log_errmsg("Untrapped error, evoker %s: %s" % - (session, format_exc())) - return + if session.logged_in: + # Store the timestamp of the user's last command. + session.cmd_last = time.time() - 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'])) - if exit_matches: - targ_exit = exit_matches[0] - if targ_exit.get_home(): - cdat['uinput'] = parsed_input - - # SCRIPT: See if the player can traverse the exit - if not targ_exit.get_scriptlink().default_lock({ - "pobject": pobject - }): - session.msg("You can't traverse that exit.") - else: - pobject.move_to(targ_exit.get_home()) - session.execute_cmd("look") - else: - session.msg("That exit leads to nowhere.") + # Lets the users get around badly configured NAT timeouts. + if parsed_input['root_cmd'] == 'idle': + return + + # Increment our user's command counter. + session.cmd_total += 1 + # Player-visible idle time, not used in idle timeout calcs. + session.cmd_last_visible = time.time() + + # Just in case. Prevents some really funky-case crashes. + if len(parsed_input['root_cmd']) == 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 functions_comsys.plr_has_channel(session, + parsed_input['root_cmd'], + alias_search=True, + return_muted=True): + + calias = parsed_input['root_cmd'] + cname = functions_comsys.plr_cname_from_alias(session, calias) + cmessage = ' '.join(parsed_input['splitted'][1:]) + + if cmessage == "who": + functions_comsys.msg_cwho(session, cname) + return + elif cmessage == "on": + functions_comsys.plr_chan_on(session, calias) + return + elif cmessage == "off": + functions_comsys.plr_chan_off(session, calias) + return + elif cmessage == "last": + functions_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' + + # Get the command's function reference (Or False) + cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd']) + if cmdtuple: + # If there is a permissions element to the entry, check perms. + if cmdtuple[1]: + if not session.get_pobject().user_has_perm_list(cmdtuple[1]): + session.msg(defines_global.NOPERMS_MSG) + return + # If flow reaches this point, user has perms and command is ready. + cmd = cmdtuple[0] + + else: + # Not logged in, look through the unlogged-in command table. + cmdtuple = cmdtable.return_cmdtuple(parsed_input['root_cmd'], unlogged_cmd=True) + if cmdtuple: + cmd = cmdtuple[0] + + # Debugging stuff. + #session.msg("ROOT : %s" % (parsed_input['root_cmd'],)) + #session.msg("SPLIT: %s" % (parsed_input['splitted'],)) + + if callable(cmd): + cdat['uinput'] = parsed_input + try: + cmd(cdat) + except: + session.msg("Untrapped error, please file a bug report:\n%s" % (format_exc(),)) + functions_general.log_errmsg("Untrapped error, evoker %s: %s" % + (session, format_exc())) return - # If we reach this point, we haven't matched anything. - raise UnknownCommand + 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'])) + if exit_matches: + targ_exit = exit_matches[0] + if targ_exit.get_home(): + cdat['uinput'] = parsed_input + + # SCRIPT: See if the player can traverse the exit + if not targ_exit.get_scriptlink().default_lock({ + "pobject": pobject + }): + session.msg("You can't traverse that exit.") + else: + pobject.move_to(targ_exit.get_home()) + session.execute_cmd("look") + else: + session.msg("That exit leads to nowhere.") + return - except UnknownCommand: - session.msg("Huh? (Type \"help\" for help.)") + # If we reach this point, we haven't matched anything. + raise UnknownCommand + + except UnknownCommand: + session.msg("Huh? (Type \"help\" for help.)") diff --git a/cmdtable.py b/cmdtable.py index c4c827c892..d93a4481aa 100644 --- a/cmdtable.py +++ b/cmdtable.py @@ -18,73 +18,73 @@ permissions tuple. """ # -- Unlogged-in Command Table -- -# Command Name Command Function Privilege Tuple +# Command Name Command Function Privilege Tuple uncon_ctable = { - "connect": (commands.unloggedin.cmd_connect, None), - "create": (commands.unloggedin.cmd_create, None), - "quit": (commands.unloggedin.cmd_quit, None), + "connect": (commands.unloggedin.cmd_connect, None), + "create": (commands.unloggedin.cmd_create, None), + "quit": (commands.unloggedin.cmd_quit, None), } # -- Command Table -- -# Command Name Command Function Privilege Tuple +# Command Name Command Function Privilege Tuple ctable = { - "addcom": (commands.comsys.cmd_addcom, None), - "comlist": (commands.comsys.cmd_comlist, None), - "delcom": (commands.comsys.cmd_delcom, None), - "drop": (commands.general.cmd_drop, None), - "examine": (commands.general.cmd_examine, None), - "get": (commands.general.cmd_get, None), - "help": (commands.general.cmd_help, None), - "idle": (commands.general.cmd_idle, None), - "inventory": (commands.general.cmd_inventory, None), - "look": (commands.general.cmd_look, None), - "page": (commands.general.cmd_page, None), - "pose": (commands.general.cmd_pose, None), - "quit": (commands.general.cmd_quit, None), - "say": (commands.general.cmd_say, None), - "time": (commands.general.cmd_time, None), - "uptime": (commands.general.cmd_uptime, None), - "version": (commands.general.cmd_version, None), - "who": (commands.general.cmd_who, None), - "@alias": (commands.objmanip.cmd_alias, None), - "@boot": (commands.privileged.cmd_boot, ("genperms.manage_players")), - "@ccreate": (commands.comsys.cmd_ccreate, ("objects.add_commchannel")), - "@cdestroy": (commands.comsys.cmd_cdestroy, ("objects.delete_commchannel")), - "@cemit": (commands.comsys.cmd_cemit, None), - "@clist": (commands.comsys.cmd_clist, None), - "@create": (commands.objmanip.cmd_create, ("genperms.builder")), - "@describe": (commands.objmanip.cmd_description, None), - "@destroy": (commands.objmanip.cmd_destroy, ("genperms.builder")), - "@dig": (commands.objmanip.cmd_dig, ("genperms.builder")), - "@emit": (commands.general.cmd_emit, ("genperms.announce")), - "@find": (commands.objmanip.cmd_find, ("genperms.builder")), - "@link": (commands.objmanip.cmd_link, ("genperms.builder")), - "@list": (commands.info.cmd_list, ("genperms.process_control")), - "@name": (commands.objmanip.cmd_name, None), - "@nextfree": (commands.objmanip.cmd_nextfree, ("genperms.builder")), - "@newpassword": (commands.privileged.cmd_newpassword, ("genperms.manage_players")), - "@open": (commands.objmanip.cmd_open, ("genperms.builder")), - "@password": (commands.general.cmd_password, None), - "@ps": (commands.info.cmd_ps, ("genperms.process_control")), - "@reload": (commands.privileged.cmd_reload, ("genperms.process_control")), - "@set": (commands.objmanip.cmd_set, None), - "@shutdown": (commands.privileged.cmd_shutdown, ("genperms.process_control")), - "@stats": (commands.info.cmd_stats, None), - "@teleport": (commands.objmanip.cmd_teleport, ("genperms.builder")), - "@unlink": (commands.objmanip.cmd_unlink, ("genperms.builder")), - "@wall": (commands.general.cmd_wall, ("genperms.announce")), - "@wipe": (commands.objmanip.cmd_wipe, None), + "addcom": (commands.comsys.cmd_addcom, None), + "comlist": (commands.comsys.cmd_comlist, None), + "delcom": (commands.comsys.cmd_delcom, None), + "drop": (commands.general.cmd_drop, None), + "examine": (commands.general.cmd_examine, None), + "get": (commands.general.cmd_get, None), + "help": (commands.general.cmd_help, None), + "idle": (commands.general.cmd_idle, None), + "inventory": (commands.general.cmd_inventory, None), + "look": (commands.general.cmd_look, None), + "page": (commands.general.cmd_page, None), + "pose": (commands.general.cmd_pose, None), + "quit": (commands.general.cmd_quit, None), + "say": (commands.general.cmd_say, None), + "time": (commands.general.cmd_time, None), + "uptime": (commands.general.cmd_uptime, None), + "version": (commands.general.cmd_version, None), + "who": (commands.general.cmd_who, None), + "@alias": (commands.objmanip.cmd_alias, None), + "@boot": (commands.privileged.cmd_boot, ("genperms.manage_players")), + "@ccreate": (commands.comsys.cmd_ccreate, ("objects.add_commchannel")), + "@cdestroy": (commands.comsys.cmd_cdestroy, ("objects.delete_commchannel")), + "@cemit": (commands.comsys.cmd_cemit, None), + "@clist": (commands.comsys.cmd_clist, None), + "@create": (commands.objmanip.cmd_create, ("genperms.builder")), + "@describe": (commands.objmanip.cmd_description, None), + "@destroy": (commands.objmanip.cmd_destroy, ("genperms.builder")), + "@dig": (commands.objmanip.cmd_dig, ("genperms.builder")), + "@emit": (commands.general.cmd_emit, ("genperms.announce")), +# "@pemit": (commands.general.cmd_pemit, None), + "@find": (commands.objmanip.cmd_find, ("genperms.builder")), + "@link": (commands.objmanip.cmd_link, ("genperms.builder")), + "@list": (commands.info.cmd_list, ("genperms.process_control")), + "@name": (commands.objmanip.cmd_name, None), + "@nextfree": (commands.objmanip.cmd_nextfree, ("genperms.builder")), + "@newpassword": (commands.privileged.cmd_newpassword, ("genperms.manage_players")), + "@open": (commands.objmanip.cmd_open, ("genperms.builder")), + "@password": (commands.general.cmd_password, None), + "@ps": (commands.info.cmd_ps, ("genperms.process_control")), + "@reload": (commands.privileged.cmd_reload, ("genperms.process_control")), + "@set": (commands.objmanip.cmd_set, None), + "@shutdown": (commands.privileged.cmd_shutdown, ("genperms.process_control")), + "@stats": (commands.info.cmd_stats, None), + "@teleport": (commands.objmanip.cmd_teleport, ("genperms.builder")), + "@unlink": (commands.objmanip.cmd_unlink, ("genperms.builder")), + "@wall": (commands.general.cmd_wall, ("genperms.announce")), + "@wipe": (commands.objmanip.cmd_wipe, None), } def return_cmdtuple(func_name, unlogged_cmd=False): - """ - Returns a reference to the command's tuple. If there are no matches, - returns false. - """ - if not unlogged_cmd: - cfunc = ctable.get(func_name, False) - else: - cfunc = uncon_ctable.get(func_name, False) - - return cfunc + """ + Returns a reference to the command's tuple. If there are no matches, + returns false. + """ + if not unlogged_cmd: + cfunc = ctable.get(func_name, False) + else: + cfunc = uncon_ctable.get(func_name, False) + return cfunc diff --git a/commands/general.py b/commands/general.py index 9bde8b025b..d3fb7258cd 100644 --- a/commands/general.py +++ b/commands/general.py @@ -12,486 +12,553 @@ Generic command module. Pretty much every command should go here for now. """ def cmd_password(cdat): - """ - Changes your own password. - - @newpass = - """ - session = cdat['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:]) - - if len(oldpass) == 0: - session.msg("You must provide your old password.") - elif len(newpass) == 0: - session.msg("You must provide your new password.") - else: - uaccount = pobject.get_user_account() - - if not uaccount.check_password(oldpass): - session.msg("The specified old password isn't correct.") - elif len(newpass) < 3: - session.msg("Passwords must be at least three characters long.") - return - else: - uaccount.set_password(newpass) - uaccount.save() - session.msg("Password changed.") + """ + Changes your own password. + + @newpass = + """ + session = cdat['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:]) + + if len(oldpass) == 0: + session.msg("You must provide your old password.") + elif len(newpass) == 0: + session.msg("You must provide your new password.") + else: + uaccount = pobject.get_user_account() + + if not uaccount.check_password(oldpass): + session.msg("The specified old password isn't correct.") + elif len(newpass) < 3: + session.msg("Passwords must be at least three characters long.") + return + else: + uaccount.set_password(newpass) + uaccount.save() + session.msg("Password changed.") -def cmd_emit(cdat): - """ - Emits something to your location. - """ - session = cdat['session'] - pobject = session.get_pobject() - uinput= cdat['uinput']['splitted'] - message = ' '.join(uinput[1:]) - - if message == '': - session.msg("Emit what?") - else: - pobject.get_location().emit_to_contents(message) +def cmd_emit(cdat): + """ + Emits something to your location. + """ + session = cdat['session'] + pobject = session.get_pobject() + uinput= cdat['uinput']['splitted'] + message = ' '.join(uinput[1:]) + + if message == '': + session.msg("Emit what?") + else: + pobject.get_location().emit_to_contents(message) def cmd_wall(cdat): - """ - Announces a message to all connected players. - """ - session = cdat['session'] - wallstring = ' '.join(cdat['uinput']['splitted'][1:]) - pobject = session.get_pobject() - - if wallstring == '': - session.msg("Announce what?") - return - - message = "%s shouts \"%s\"" % (session.get_pobject().get_name(show_dbref=False), wallstring) - functions_general.announce_all(message) + """ + Announces a message to all connected players. + """ + session = cdat['session'] + wallstring = ' '.join(cdat['uinput']['splitted'][1:]) + pobject = session.get_pobject() + + if wallstring == '': + session.msg("Announce what?") + return + + message = "%s shouts \"%s\"" % (session.get_pobject().get_name(show_dbref=False), wallstring) + functions_general.announce_all(message) def cmd_idle(cdat): - """ - Returns nothing, this lets the player set an idle timer without spamming - his screen. - """ - pass - + """ + Returns nothing, this lets the player set an idle timer without spamming + his screen. + """ + pass + def cmd_inventory(cdat): - """ - Shows a player's inventory. - """ - session = cdat['session'] - pobject = session.get_pobject() - session.msg("You are carrying:") - - for item in pobject.get_contents(): - session.msg(" %s" % (item.get_name(),)) - - money = int(pobject.get_attribute_value("MONEY", default=0)) - if money == 1: - money_name = gameconf.get_configvalue("MONEY_NAME_SINGULAR") - else: - money_name = gameconf.get_configvalue("MONEY_NAME_PLURAL") + """ + Shows a player's inventory. + """ + session = cdat['session'] + pobject = session.get_pobject() + session.msg("You are carrying:") + + for item in pobject.get_contents(): + session.msg(" %s" % (item.get_name(),)) + + money = int(pobject.get_attribute_value("MONEY", default=0)) + if money == 1: + money_name = gameconf.get_configvalue("MONEY_NAME_SINGULAR") + else: + money_name = gameconf.get_configvalue("MONEY_NAME_PLURAL") - session.msg("You have %d %s." % (money,money_name)) + session.msg("You have %d %s." % (money,money_name)) def cmd_look(cdat): - """ - Handle looking at objects. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] + """ + Handle looking at objects. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] - if len(args) == 0: - target_obj = pobject.get_location() - else: - target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return - - # SCRIPT: Get the item's appearance from the scriptlink. - session.msg(target_obj.get_scriptlink().return_appearance({ - "target_obj": target_obj, - "pobject": pobject - })) - - # SCRIPT: Call the object's script's a_desc() method. - target_obj.get_scriptlink().a_desc({ - "target_obj": pobject - }) - + if len(args) == 0: + target_obj = pobject.get_location() + else: + target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return + + # SCRIPT: Get the item's appearance from the scriptlink. + session.msg(target_obj.get_scriptlink().return_appearance({ + "target_obj": target_obj, + "pobject": pobject + })) + + # SCRIPT: Call the object's script's a_desc() method. + target_obj.get_scriptlink().a_desc({ + "target_obj": pobject + }) + def cmd_get(cdat): - """ - Get an object and put it in a player's inventory. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] - plr_is_staff = pobject.is_staff() + """ + Get an object and put it in a player's inventory. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + plr_is_staff = pobject.is_staff() - if len(args) == 0: - session.msg("Get what?") - return - else: - target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_contents=False) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + if len(args) == 0: + session.msg("Get what?") + return + else: + target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_contents=False) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if pobject == target_obj: - session.msg("You can't get yourself.") - return - - if not plr_is_staff and (target_obj.is_player() or target_obj.is_exit()): - session.msg("You can't get that.") - return - - if target_obj.is_room() or target_obj.is_garbage() or target_obj.is_going(): - session.msg("You can't get that.") - return - - 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) - - # SCRIPT: Call the object's script's a_get() method. - target_obj.get_scriptlink().a_get({ - "pobject": pobject - }) - + if pobject == target_obj: + session.msg("You can't get yourself.") + return + + if not plr_is_staff and (target_obj.is_player() or target_obj.is_exit()): + session.msg("You can't get that.") + return + + if target_obj.is_room() or target_obj.is_garbage() or target_obj.is_going(): + session.msg("You can't get that.") + return + + 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) + + # SCRIPT: Call the object's script's a_get() method. + target_obj.get_scriptlink().a_get({ + "pobject": pobject + }) + def cmd_drop(cdat): - """ - Drop an object from a player's inventory into their current location. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] - plr_is_staff = pobject.is_staff() + """ + Drop an object from a player's inventory into their current location. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + plr_is_staff = pobject.is_staff() - if len(args) == 0: - session.msg("Drop what?") - return - else: - target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_location=False) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + if len(args) == 0: + session.msg("Drop what?") + return + else: + target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args), search_location=False) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if not pobject == target_obj.get_location(): - session.msg("You don't appear to be carrying that.") - return - - 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) + if not pobject == target_obj.get_location(): + session.msg("You don't appear to be carrying that.") + return + + 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) - # SCRIPT: Call the object's script's a_drop() method. - target_obj.get_scriptlink().a_drop({ - "pobject": pobject - }) - + # SCRIPT: Call the object's script's a_drop() method. + target_obj.get_scriptlink().a_drop({ + "pobject": pobject + }) + def cmd_examine(cdat): - """ - Detailed object examine command - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] - attr_search = False - - if len(args) == 0: - # 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("/") - - # If the splitting by the "/" character returns a list with more than 1 - # entry, it's an attribute match. - if len(attr_split) > 1: - 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:]) - else: - searchstr = ' '.join(args) + """ + Detailed object examine command + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + attr_search = False + + if len(args) == 0: + # 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("/") + + # If the splitting by the "/" character returns a list with more than 1 + # entry, it's an attribute match. + if len(attr_split) > 1: + 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:]) + else: + searchstr = ' '.join(args) - target_obj = functions_db.standard_plr_objsearch(session, searchstr) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return - - if attr_search: - attr_matches = target_obj.attribute_namesearch(attr_searchstr) - if attr_matches: - for attribute in attr_matches: + target_obj = functions_db.standard_plr_objsearch(session, searchstr) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return + + if attr_search: + 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: + 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("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()) - else: - session.msg("No matching attributes found.") - # End attr_search if() - else: - 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("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()) - - con_players = [] - con_things = [] - con_exits = [] - - for obj in target_obj.get_contents(): - if obj.is_player(): - con_players.append(obj) - elif obj.is_exit(): - con_exits.append(obj) - elif obj.is_thing(): - con_things.append(obj) - - if con_players or con_things: - 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),)) - - if con_exits: - session.msg("%sExits:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],)) - for exit in con_exits: - session.msg('%s' %(exit.get_name(fullname=True),)) - - if not target_obj.is_room(): - if target_obj.is_exit(): - session.msg("Destination: %s" % (target_obj.get_home(),)) - else: - session.msg("Home: %s" % (target_obj.get_home(),)) - - session.msg("Location: %s" % (target_obj.get_location(),)) - + + con_players = [] + con_things = [] + con_exits = [] + + for obj in target_obj.get_contents(): + if obj.is_player(): + con_players.append(obj) + elif obj.is_exit(): + con_exits.append(obj) + elif obj.is_thing(): + con_things.append(obj) + + if con_players or con_things: + 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),)) + + if con_exits: + session.msg("%sExits:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],)) + for exit in con_exits: + session.msg('%s' %(exit.get_name(fullname=True),)) + + if not target_obj.is_room(): + if target_obj.is_exit(): + session.msg("Destination: %s" % (target_obj.get_home(),)) + else: + session.msg("Home: %s" % (target_obj.get_home(),)) + + 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:] + """ + 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 functions_db.is_dbref(dbref): + raise ValueError + last_paged_object = functions_db.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 len(args) == 0: - session.msg("Page who/what?") - return + # 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 - # Combine the arguments into one string, split it by equal signs into - # victim (entry 0 in the list), and message (entry 1 and above). - eq_args = ' '.join(args).split('=') + # 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 = functions_db.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 functions_db.is_dbref(target): + session.msg("Is dbref.") + matched_object = functions_db.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 = functions_db.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" - # If no equal sign is in the passed arguments, see if the player has - # a LASTPAGED attribute. If they do, default the page to them, if not, - # don't touch anything and error out. - if len(eq_args) == 1 and pobject.has_attribute("LASTPAGED"): - eq_args.insert(0, "#%s" % (pobject.get_attribute_value("LASTPAGED"),)) - - if len(eq_args) > 1: - target = functions_db.player_search(pobject, eq_args[0]) - message = ' '.join(eq_args[1:]) + # 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) == 0: - session.msg("I don't recognize \"%s\"." % (eq_args[0].capitalize(),)) - return - elif len(message) == 0: - session.msg("I need a message to deliver.") - return - elif len(target) > 1: - session.msg("Try a more unique spelling of their name.") - return - else: - if target[0].is_connected_plr(): - target[0].emit_to("%s pages: %s" % - (pobject.get_name(show_dbref=False), message)) - session.msg("You paged %s with '%s'." % - (target[0].get_name(show_dbref=False), message)) - pobject.set_attribute("LASTPAGED", target[0].id) - else: - session.msg("Player %s does not exist or is not online." % - (target[0].get_name(show_dbref=False),)) - else: - session.msg("Page who?") - return + 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): - """ - Gracefully disconnect the user as per his own request. - """ - session = cdat['session'] - session.msg("Quitting!") - session.handle_close() - + """ + Gracefully disconnect the user as per his own request. + """ + session = cdat['session'] + session.msg("Quitting!") + session.handle_close() + def cmd_who(cdat): - """ - Generic WHO command. - """ - session_list = session_mgr.get_session_list() - session = cdat['session'] - pobject = session.get_pobject() - show_session_data = pobject.user_has_perm("genperms.see_session_data") + """ + Generic WHO command. + """ + session_list = session_mgr.get_session_list() + session = cdat['session'] + pobject = session.get_pobject() + show_session_data = pobject.user_has_perm("genperms.see_session_data") - # Only those with the see_session_data or superuser status can see - # session details. - if show_session_data: - retval = "Player Name On For Idle Room Cmds Host\n\r" - else: - retval = "Player Name On For Idle\n\r" - - for player in session_list: - if not player.logged_in: - continue - delta_cmd = time.time() - player.cmd_last_visible - delta_conn = time.time() - player.conn_time - plr_pobject = player.get_pobject() + # Only those with the see_session_data or superuser status can see + # session details. + if show_session_data: + retval = "Player Name On For Idle Room Cmds Host\n\r" + else: + retval = "Player Name On For Idle\n\r" + + for player in session_list: + if not player.logged_in: + continue + delta_cmd = time.time() - player.cmd_last_visible + delta_conn = time.time() - player.conn_time + plr_pobject = player.get_pobject() - if show_session_data: - retval += '%-16s%9s %4s%-3s#%-6d%5d%3s%-25s\r\n' % \ - (plr_pobject.get_name(show_dbref=False)[:25].ljust(27), \ - # On-time - functions_general.time_format(delta_conn,0), \ - # Idle time - functions_general.time_format(delta_cmd,1), \ - # Flags - '', \ - # Location - plr_pobject.get_location().id, \ - player.cmd_total, \ - # More flags? - '', \ - player.address[0]) - else: - retval += '%-16s%9s %4s%-3s\r\n' % \ - (plr_pobject.get_name(show_dbref=False)[:25].ljust(27), \ - # On-time - functions_general.time_format(delta_conn,0), \ - # Idle time - functions_general.time_format(delta_cmd,1), \ - # Flags - '') - retval += '%d Players logged in.' % (len(session_list),) - - session.msg(retval) + if show_session_data: + retval += '%-16s%9s %4s%-3s#%-6d%5d%3s%-25s\r\n' % \ + (plr_pobject.get_name(show_dbref=False)[:25].ljust(27), \ + # On-time + functions_general.time_format(delta_conn,0), \ + # Idle time + functions_general.time_format(delta_cmd,1), \ + # Flags + '', \ + # Location + plr_pobject.get_location().id, \ + player.cmd_total, \ + # More flags? + '', \ + player.address[0]) + else: + retval += '%-16s%9s %4s%-3s\r\n' % \ + (plr_pobject.get_name(show_dbref=False)[:25].ljust(27), \ + # On-time + functions_general.time_format(delta_conn,0), \ + # Idle time + functions_general.time_format(delta_cmd,1), \ + # Flags + '') + retval += '%d Players logged in.' % (len(session_list),) + + session.msg(retval) def cmd_say(cdat): - """ - Room-based speech command. - """ - session = cdat['session'] + """ + Room-based speech command. + """ + session = cdat['session'] - if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 1, errortext="Say what?"): - return - - session_list = session_mgr.get_session_list() - pobject = session.get_pobject() - speech = ' '.join(cdat['uinput']['splitted'][1:]) - - players_present = [player for player in session_list if player.get_pobject().get_location() == session.get_pobject().get_location() and player != session] - - retval = "You say, '%s'" % (speech,) - for player in players_present: - player.msg("%s says, '%s'" % (pobject.get_name(show_dbref=False), speech,)) - - session.msg(retval) + if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 1, errortext="Say what?"): + return + + session_list = session_mgr.get_session_list() + pobject = session.get_pobject() + speech = ' '.join(cdat['uinput']['splitted'][1:]) + + players_present = [player for player in session_list if player.get_pobject().get_location() == session.get_pobject().get_location() and player != session] + + retval = "You say, '%s'" % (speech,) + for player in players_present: + player.msg("%s says, '%s'" % (pobject.get_name(show_dbref=False), speech,)) + + session.msg(retval) def cmd_pose(cdat): - """ - Pose/emote command. - """ - session = cdat['session'] - pobject = session.get_pobject() - switches = cdat['uinput']['root_chunk'][1:] + """ + Pose/emote command. + """ + session = cdat['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?"): - return - - session_list = session_mgr.get_session_list() - speech = ' '.join(cdat['uinput']['splitted'][1:]) - - if "nospace" in switches: - sent_msg = "%s%s" % (pobject.get_name(show_dbref=False), speech) - else: - 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()] - - for player in players_present: - player.msg(sent_msg) - + if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 1, errortext="Do what?"): + return + + session_list = session_mgr.get_session_list() + speech = ' '.join(cdat['uinput']['splitted'][1:]) + + if "nospace" in switches: + sent_msg = "%s%s" % (pobject.get_name(show_dbref=False), speech) + else: + 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()] + + for player in players_present: + player.msg(sent_msg) + def cmd_help(cdat): - """ - Help system commands. - """ - session = cdat['session'] - pobject = session.get_pobject() - topicstr = ' '.join(cdat['uinput']['splitted'][1:]) - - if len(topicstr) == 0: - 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.") - return - - topics = functions_help.find_topicmatch(pobject, topicstr) - - if len(topics) == 0: - session.msg("No matching topics found, please refine your search.") - suggestions = functions_help.find_topicsuggestions(pobject, topicstr) - if len(suggestions) > 0: - session.msg("Matching similarly named topics:") - for result in suggestions: - session.msg(" %s" % (result,)) - session.msg("You may type 'help <#>' to see any of these topics.") - elif len(topics) > 1: - session.msg("More than one match found:") - for result in topics: - session.msg("%3d. %s" % (result.id, result.get_topicname())) - session.msg("You may type 'help <#>' to see any of these topics.") - else: - topic = topics[0] - session.msg("\r\n%s%s%s" % (ansi.ansi["hilite"], topic.get_topicname(), ansi.ansi["normal"])) - session.msg(topic.get_entrytext_ingame()) - + """ + Help system commands. + """ + session = cdat['session'] + pobject = session.get_pobject() + topicstr = ' '.join(cdat['uinput']['splitted'][1:]) + + if len(topicstr) == 0: + 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.") + return + + topics = functions_help.find_topicmatch(pobject, topicstr) + + if len(topics) == 0: + session.msg("No matching topics found, please refine your search.") + suggestions = functions_help.find_topicsuggestions(pobject, topicstr) + if len(suggestions) > 0: + session.msg("Matching similarly named topics:") + for result in suggestions: + session.msg(" %s" % (result,)) + session.msg("You may type 'help <#>' to see any of these topics.") + elif len(topics) > 1: + session.msg("More than one match found:") + for result in topics: + session.msg("%3d. %s" % (result.id, result.get_topicname())) + session.msg("You may type 'help <#>' to see any of these topics.") + else: + topic = topics[0] + session.msg("\r\n%s%s%s" % (ansi.ansi["hilite"], topic.get_topicname(), ansi.ansi["normal"])) + session.msg(topic.get_entrytext_ingame()) + def cmd_version(cdat): - """ - Version info command. - """ - session = cdat['session'] - retval = "-"*50 +"\n\r" - retval += "Evennia %s\n\r" % (defines_global.EVENNIA_VERSION,) - retval += "-"*50 - session.msg(retval) + """ + Version info command. + """ + session = cdat['session'] + retval = "-"*50 +"\n\r" + retval += "Evennia %s\n\r" % (defines_global.EVENNIA_VERSION,) + retval += "-"*50 + session.msg(retval) def cmd_time(cdat): - """ - Server local time. - """ - session = cdat['session'] - session.msg('Current server time : %s' % (time.strftime('%a %b %d %H:%M %Y (%Z)', time.localtime(),))) - + """ + Server local time. + """ + session = cdat['session'] + session.msg('Current server time : %s' % (time.strftime('%a %b %d %H:%M %Y (%Z)', time.localtime(),))) + def cmd_uptime(cdat): - """ - Server uptime and stats. - """ - session = cdat['session'] - server = cdat['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]) + """ + Server uptime and stats. + """ + session = cdat['session'] + server = cdat['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]) diff --git a/commands/objmanip.py b/commands/objmanip.py index 779647132d..c5e8ec8fe6 100644 --- a/commands/objmanip.py +++ b/commands/objmanip.py @@ -3,540 +3,540 @@ import session_mgr import functions_db def cmd_teleport(cdat): - """ - Teleports an object somewhere. - """ - session = cdat['session'] - pobject = session.get_pobject() - server = cdat['server'] - args = cdat['uinput']['splitted'][1:] + """ + Teleports an object somewhere. + """ + session = cdat['session'] + pobject = session.get_pobject() + server = cdat['server'] + args = cdat['uinput']['splitted'][1:] - if len(args) == 0: - session.msg("Teleport where/what?") - return + if len(args) == 0: + session.msg("Teleport where/what?") + return - eq_args = args[0].split('=') - search_str = ''.join(args) + 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: - # Equal sign teleport. - victim = functions_db.standard_plr_objsearch(session, eq_args[0]) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not victim: - return + # 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: + # Equal sign teleport. + victim = functions_db.standard_plr_objsearch(session, eq_args[0]) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not victim: + return - destination = functions_db.standard_plr_objsearch(session, eq_args[1]) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not destination: - return + destination = functions_db.standard_plr_objsearch(session, eq_args[1]) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not destination: + return - if victim.is_room(): - session.msg("You can't teleport a room.") - return + if victim.is_room(): + session.msg("You can't teleport a room.") + return - if victim == destination: - session.msg("You can't teleport an object inside of itself!") - return - session.msg("Teleported.") - victim.move_to(destination) + if victim == destination: + 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") + # 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") - else: - # Direct teleport (no equal sign) - target_obj = functions_db.standard_plr_objsearch(session, search_str) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + else: + # Direct teleport (no equal sign) + target_obj = functions_db.standard_plr_objsearch(session, search_str) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if target_obj == pobject: - session.msg("You can't teleport inside yourself!") - return - session.msg("Teleported.") - pobject.move_to(target_obj) - session.execute_cmd("look") + if target_obj == pobject: + session.msg("You can't teleport inside yourself!") + return + session.msg("Teleported.") + pobject.move_to(target_obj) + session.execute_cmd("look") def cmd_stats(cdat): - """ - Shows stats about the database. - 4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage) - """ - session = cdat['session'] - stats_dict = functions_db.object_totals() - 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"])) + """ + Shows stats about the database. + 4012 objects = 144 rooms, 212 exits, 613 things, 1878 players. (1165 garbage) + """ + session = cdat['session'] + stats_dict = functions_db.object_totals() + 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): - """ - Assigns an alias to a player object for ease of paging, etc. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] + """ + Assigns an alias to a player object for ease of paging, etc. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] - if len(args) == 0: - session.msg("Alias whom?") - return - - # Resplit the args on = to check for an almost-required = - eq_args = ' '.join(args).split('=') - - if len(eq_args) < 2: - session.msg("Alias missing.") - return - - target = functions_db.standard_plr_objsearch(session, eq_args[0]) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target: - session.msg("Alias whom?") - return + if len(args) == 0: + session.msg("Alias whom?") + return + + # Resplit the args on = to check for an almost-required = + eq_args = ' '.join(args).split('=') + + if len(eq_args) < 2: + session.msg("Alias missing.") + return + + target = functions_db.standard_plr_objsearch(session, eq_args[0]) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target: + session.msg("Alias whom?") + return - duplicates = functions_db.alias_search(pobject, eq_args[1]) - - if duplicates: - session.msg("Alias '%s' already exists." % (eq_args[1],)) - return - else: - 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())) - else: - session.msg("You do not have access to set an alias for %s." % (target.get_name(),)) + duplicates = functions_db.alias_search(pobject, eq_args[1]) + + if duplicates: + session.msg("Alias '%s' already exists." % (eq_args[1],)) + return + else: + 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())) + else: + session.msg("You do not have access to set an alias for %s." % (target.get_name(),)) def cmd_wipe(cdat): - """ - Wipes an object's attributes, or optionally only those matching a search - string. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] - attr_search = False + """ + Wipes an object's attributes, or optionally only those matching a search + string. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + attr_search = False - if len(args) == 0: - session.msg("Wipe what?") - return + if len(args) == 0: + session.msg("Wipe what?") + return - # Look for a slash in the input, indicating an attribute wipe. - attr_split = args[0].split("/") + # Look for a slash in the input, indicating an attribute wipe. + attr_split = args[0].split("/") - # If the splitting by the "/" character returns a list with more than 1 - # entry, it's an attribute match. - if len(attr_split) > 1: - 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:]) - else: - searchstr = ' '.join(args) + # If the splitting by the "/" character returns a list with more than 1 + # entry, it's an attribute match. + if len(attr_split) > 1: + 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:]) + else: + searchstr = ' '.join(args) - target_obj = functions_db.standard_plr_objsearch(session, searchstr) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + target_obj = functions_db.standard_plr_objsearch(session, searchstr) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - 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) - if attr_matches: - for attr in attr_matches: + 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) + 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))) + else: + session.msg("No matching attributes found.") + else: + # User didn't specify a wild-card string, wipe entire object. + 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))) - else: - session.msg("No matching attributes found.") - else: - # User didn't specify a wild-card string, wipe entire object. - 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): - """ - Sets flags or attributes on objects. - """ - session = cdat['session'] - pobject = session.get_pobject() - server = cdat['server'] - args = cdat['uinput']['splitted'][1:] + """ + Sets flags or attributes on objects. + """ + session = cdat['session'] + pobject = session.get_pobject() + server = cdat['server'] + args = cdat['uinput']['splitted'][1:] - if len(args) == 0: - session.msg("Set what?") - return + if len(args) == 0: + 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('=') + # 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('=') - if len(eq_args) < 2: - session.msg("Set what?") - return - - victim = functions_db.standard_plr_objsearch(session, eq_args[0]) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not victim: - return + if len(eq_args) < 2: + session.msg("Set what?") + return + + victim = functions_db.standard_plr_objsearch(session, eq_args[0]) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not victim: + return - if not pobject.controls_other(victim): - session.msg(defines_global.NOCONTROL_MSG) - return + if not pobject.controls_other(victim): + session.msg(defines_global.NOCONTROL_MSG) + return - attrib_args = eq_args[1].split(':') + attrib_args = eq_args[1].split(':') - if len(attrib_args) > 1: - # We're dealing with an attribute/value pair. - attrib_name = attrib_args[0].upper() - splicenum = eq_args[1].find(':') + 1 - attrib_value = eq_args[1][splicenum:] - - # In global_defines.py, see NOSET_ATTRIBS for protected attribute names. - if not functions_db.is_modifiable_attrib(attrib_name) and not pobject.is_superuser(): - session.msg("You can't modify that attribute.") - return - - if attrib_value: - # An attribute value was specified, create or set the attribute. - verb = 'set' - victim.set_attribute(attrib_name, attrib_value) - else: - # No value was given, this means we delete the attribute. - verb = 'cleared' - victim.clear_attribute(attrib_name) - session.msg("%s - %s %s." % (victim.get_name(), attrib_name, verb)) - else: - # Flag manipulation form. - flag_list = eq_args[1].split() - - for flag in flag_list: - flag = flag.upper() - if flag[0] == '!': - # We're un-setting the flag. - flag = flag[1:] - if not functions_db.is_modifiable_flag(flag): - session.msg("You can't set/unset the flag - %s." % (flag,)) + if len(attrib_args) > 1: + # We're dealing with an attribute/value pair. + attrib_name = attrib_args[0].upper() + splicenum = eq_args[1].find(':') + 1 + attrib_value = eq_args[1][splicenum:] + + # In global_defines.py, see NOSET_ATTRIBS for protected attribute names. + if not functions_db.is_modifiable_attrib(attrib_name) and not pobject.is_superuser(): + session.msg("You can't modify that attribute.") + return + + if attrib_value: + # An attribute value was specified, create or set the attribute. + verb = 'set' + victim.set_attribute(attrib_name, attrib_value) + else: + # No value was given, this means we delete the attribute. + verb = 'cleared' + victim.clear_attribute(attrib_name) + session.msg("%s - %s %s." % (victim.get_name(), attrib_name, verb)) + else: + # Flag manipulation form. + flag_list = eq_args[1].split() + + for flag in flag_list: + flag = flag.upper() + if flag[0] == '!': + # We're un-setting the flag. + flag = flag[1:] + if not functions_db.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(),)) + victim.set_flag(flag, False) else: - session.msg('%s - %s cleared.' % (victim.get_name(), flag.upper(),)) - victim.set_flag(flag, False) - else: - # We're setting the flag. - if not functions_db.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(),)) - victim.set_flag(flag, True) + # We're setting the flag. + if not functions_db.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(),)) + victim.set_flag(flag, True) def cmd_find(cdat): - """ - Searches for an object of a particular name. - """ - session = cdat['session'] - server = cdat['server'] - searchstring = ' '.join(cdat['uinput']['splitted'][1:]) - pobject = session.get_pobject() - can_find = pobject.user_has_perm("genperms.builder") + """ + Searches for an object of a particular name. + """ + session = cdat['session'] + server = cdat['server'] + searchstring = ' '.join(cdat['uinput']['splitted'][1:]) + pobject = session.get_pobject() + can_find = pobject.user_has_perm("genperms.builder") - if searchstring == '': - session.msg("No search pattern given.") - return - - results = functions_db.global_object_name_search(searchstring) + if searchstring == '': + session.msg("No search pattern given.") + return + + results = functions_db.global_object_name_search(searchstring) - if len(results) > 0: - session.msg("Name matches for: %s" % (searchstring,)) - for result in results: - session.msg(" %s" % (result.get_name(fullname=True),)) - session.msg("%d matches returned." % (len(results),)) - else: - session.msg("No name matches found for: %s" % (searchstring,)) + if len(results) > 0: + session.msg("Name matches for: %s" % (searchstring,)) + for result in results: + session.msg(" %s" % (result.get_name(fullname=True),)) + session.msg("%d matches returned." % (len(results),)) + else: + session.msg("No name matches found for: %s" % (searchstring,)) def cmd_create(cdat): - """ - Creates a new object of type 'THING'. - """ - session = cdat['session'] - server = session.server - pobject = session.get_pobject() - uinput= cdat['uinput']['splitted'] - thingname = ' '.join(uinput[1:]) - - if thingname == '': - session.msg("You must supply a name!") - else: - # Create and set the object up. - odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} - new_object = functions_db.create_object(odat) - - session.msg("You create a new thing: %s" % (new_object,)) - + """ + Creates a new object of type 'THING'. + """ + session = cdat['session'] + server = session.server + pobject = session.get_pobject() + uinput= cdat['uinput']['splitted'] + thingname = ' '.join(uinput[1:]) + + if thingname == '': + session.msg("You must supply a name!") + else: + # Create and set the object up. + odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} + new_object = functions_db.create_object(odat) + + session.msg("You create a new thing: %s" % (new_object,)) + def cmd_nextfree(cdat): - """ - Returns the next free object number. - """ - session = cdat['session'] - - nextfree = functions_db.get_nextfree_dbnum() - session.msg("Next free object number: #%s" % (nextfree,)) - + """ + Returns the next free object number. + """ + session = cdat['session'] + + nextfree = functions_db.get_nextfree_dbnum() + session.msg("Next free object number: #%s" % (nextfree,)) + def cmd_open(cdat): - """ - Handle the opening of exits. - - Forms: - @open - @open = - @open =, - """ - session = cdat['session'] - pobject = session.get_pobject() - server = cdat['server'] - args = cdat['uinput']['splitted'][1:] - - if len(args) == 0: - session.msg("Open an exit to where?") - return - - eq_args = ' '.join(args).split('=') - exit_name = eq_args[0] - - if len(exit_name) == 0: - session.msg("You must supply an exit name.") - return - - # If we have more than one entry in our '=' delimited argument list, - # then we're doing a @open =[,]. If not, we're doing - # an un-linked exit, @open . - if len(eq_args) > 1: - # Opening an exit to another location via @open =[,]. - comma_split = eq_args[1].split(',') - destination = functions_db.standard_plr_objsearch(session, comma_split[0]) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not destination: - return + """ + Handle the opening of exits. + + Forms: + @open + @open = + @open =, + """ + session = cdat['session'] + pobject = session.get_pobject() + server = cdat['server'] + args = cdat['uinput']['splitted'][1:] + + if len(args) == 0: + session.msg("Open an exit to where?") + return + + eq_args = ' '.join(args).split('=') + exit_name = eq_args[0] + + if len(exit_name) == 0: + session.msg("You must supply an exit name.") + return + + # If we have more than one entry in our '=' delimited argument list, + # then we're doing a @open =[,]. If not, we're doing + # an un-linked exit, @open . + if len(eq_args) > 1: + # Opening an exit to another location via @open =[,]. + comma_split = eq_args[1].split(',') + destination = functions_db.standard_plr_objsearch(session, comma_split[0]) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not destination: + return - if destination.is_exit(): - session.msg("You can't open an exit to an exit!") - return + if destination.is_exit(): + 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} - new_object = functions_db.create_object(odat) + odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":destination} + new_object = functions_db.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()} - new_object = functions_db.create_object(odat) - session.msg("You open the an exit - %s to %s" % (new_object.get_name(),pobject.get_location().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()} + new_object = functions_db.create_object(odat) + 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} - new_object = functions_db.create_object(odat) + else: + # Create an un-linked exit. + odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":None} + new_object = functions_db.create_object(odat) - session.msg("You open an unlinked exit - %s" % (new_object,)) + session.msg("You open an unlinked exit - %s" % (new_object,)) def cmd_link(cdat): - """ - Sets an object's home or an exit's destination. + """ + Sets an object's home or an exit's destination. - Forms: - @link = - """ - session = cdat['session'] - pobject = session.get_pobject() - server = cdat['server'] - args = cdat['uinput']['splitted'][1:] + Forms: + @link = + """ + session = cdat['session'] + pobject = session.get_pobject() + server = cdat['server'] + args = cdat['uinput']['splitted'][1:] - if len(args) == 0: - session.msg("Link what?") - return + if len(args) == 0: + session.msg("Link what?") + return - eq_args = args[0].split('=') - target_name = eq_args[0] - dest_name = '='.join(eq_args[1:]) + eq_args = args[0].split('=') + target_name = eq_args[0] + dest_name = '='.join(eq_args[1:]) - if len(target_name) == 0: - session.msg("What do you want to link?") - return + if len(target_name) == 0: + session.msg("What do you want to link?") + return - if len(eq_args) > 1: - target_obj = functions_db.standard_plr_objsearch(session, target_name) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + if len(eq_args) > 1: + target_obj = functions_db.standard_plr_objsearch(session, target_name) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if not pobject.controls_other(target_obj): - session.msg(defines_global.NOCONTROL_MSG) - return + if not pobject.controls_other(target_obj): + session.msg(defines_global.NOCONTROL_MSG) + return - # If we do something like "@link blah=", we unlink the object. - if len(dest_name) == 0: - target_obj.set_home(None) - session.msg("You have unlinked %s." % (target_obj,)) - return + # If we do something like "@link blah=", we unlink the object. + if len(dest_name) == 0: + target_obj.set_home(None) + session.msg("You have unlinked %s." % (target_obj,)) + return - destination = functions_db.standard_plr_objsearch(session, dest_name) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not destination: - return + destination = functions_db.standard_plr_objsearch(session, dest_name) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not destination: + return - target_obj.set_home(destination) - session.msg("You link %s to %s." % (target_obj,destination)) + target_obj.set_home(destination) + session.msg("You link %s to %s." % (target_obj,destination)) - else: - # We haven't provided a target. - session.msg("You must provide a destination to link to.") - return + else: + # We haven't provided a target. + session.msg("You must provide a destination to link to.") + return def cmd_unlink(cdat): - """ - Unlinks an object. - """ - session = cdat['session'] - pobject = session.get_pobject() - args = cdat['uinput']['splitted'][1:] - - if len(args) == 0: - session.msg("Unlink what?") - return - else: - target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + """ + Unlinks an object. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + + if len(args) == 0: + session.msg("Unlink what?") + return + else: + target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if not pobject.controls_other(target_obj): - session.msg(defines_global.NOCONTROL_MSG) - return + if not pobject.controls_other(target_obj): + session.msg(defines_global.NOCONTROL_MSG) + return - target_obj.set_home(None) - session.msg("You have unlinked %s." % (target_obj.get_name(),)) + target_obj.set_home(None) + session.msg("You have unlinked %s." % (target_obj.get_name(),)) def cmd_dig(cdat): - """ - Creates a new object of type 'ROOM'. - """ - session = cdat['session'] - pobject = session.get_pobject() - uinput= cdat['uinput']['splitted'] - roomname = ' '.join(uinput[1:]) - - if roomname == '': - session.msg("You must supply a name!") - else: - # Create and set the object up. - odat = {"name": roomname, "type": 2, "location": None, "owner": pobject} - new_object = functions_db.create_object(odat) - - session.msg("You create a new room: %s" % (new_object,)) + """ + Creates a new object of type 'ROOM'. + """ + session = cdat['session'] + pobject = session.get_pobject() + uinput= cdat['uinput']['splitted'] + roomname = ' '.join(uinput[1:]) + + if roomname == '': + session.msg("You must supply a name!") + else: + # Create and set the object up. + odat = {"name": roomname, "type": 2, "location": None, "owner": pobject} + new_object = functions_db.create_object(odat) + + session.msg("You create a new room: %s" % (new_object,)) def cmd_name(cdat): - """ - 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: - session.msg("What do you want to name?") - elif len(eq_args) < 2: - session.msg("What would you like to name that object?") - else: - target_obj = functions_db.standard_plr_objsearch(session, searchstring) - # 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) + """ + 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: + session.msg("What do you want to name?") + elif len(eq_args) < 2: + session.msg("What would you like to name that object?") + else: + target_obj = functions_db.standard_plr_objsearch(session, searchstring) + # 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) def cmd_description(cdat): - """ - Set an object's description. - """ - 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: - session.msg("What do you want to describe?") - elif len(eq_args) < 2: - session.msg("How would you like to describe that object?") - else: - target_obj = functions_db.standard_plr_objsearch(session, searchstring) - # Use standard_plr_objsearch to handle duplicate/nonexistant results. - if not target_obj: - return + """ + Set an object's description. + """ + 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: + session.msg("What do you want to describe?") + elif len(eq_args) < 2: + session.msg("How would you like to describe that object?") + else: + target_obj = functions_db.standard_plr_objsearch(session, searchstring) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: + return - if not pobject.controls_other(target_obj): - session.msg(defines_global.NOCONTROL_MSG) - return + if not pobject.controls_other(target_obj): + session.msg(defines_global.NOCONTROL_MSG) + return - new_desc = '='.join(eq_args[1:]) - session.msg("%s - DESCRIPTION set." % (target_obj,)) - target_obj.set_description(new_desc) + new_desc = '='.join(eq_args[1:]) + session.msg("%s - DESCRIPTION set." % (target_obj,)) + target_obj.set_description(new_desc) def cmd_destroy(cdat): - """ - Destroy an object. - """ - session = cdat['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: - session.msg("Destroy what?") - return - else: - target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) - # 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.") + """ + Destroy an object. + """ + session = cdat['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: + session.msg("Destroy what?") + return + else: + target_obj = functions_db.standard_plr_objsearch(session, ' '.join(args)) + # Use standard_plr_objsearch to handle duplicate/nonexistant results. + if not target_obj: return - if not switch_override: - session.msg("You must use @destroy/override on players.") + + 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 - 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() + + session.msg("You destroy %s." % (target_obj.get_name(),)) + target_obj.destroy() diff --git a/commands/unloggedin.py b/commands/unloggedin.py index 333ead7e5f..45194fd93a 100644 --- a/commands/unloggedin.py +++ b/commands/unloggedin.py @@ -1,91 +1,98 @@ from django.contrib.auth.models import User +from apps.objects.models import Attribute, Object import functions_db import functions_general +import defines_global """ Commands that are available from the connect screen. """ def cmd_connect(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. - """ + """ + 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 = cdat['session'] - # Argument check. - if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2): - return - - uemail = cdat['uinput']['splitted'][1] - password = cdat['uinput']['splitted'][2] + # Argument check. + if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2): + return + + uemail = cdat['uinput']['splitted'][1] + password = cdat['uinput']['splitted'][2] - # Match an email address to an account. - email_matches = functions_db.get_user_from_email(uemail) - - autherror = "Specified email does not match any accounts!" - # No username match - if email_matches.count() == 0: - session.msg(autherror) - 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) - else: - uname = user.username - session.login(user) - + # Match an email address to an account. + email_matches = functions_db.get_user_from_email(uemail) + + autherror = "Specified email does not match any accounts!" + # No username match + if email_matches.count() == 0: + session.msg(autherror) + 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) + else: + uname = user.username + session.login(user) + def cmd_create(cdat): - """ - Handle the creation of new accounts. - """ - session = cdat['session'] + """ + Handle the creation of new accounts. + """ + session = cdat['session'] - # Argument check. - if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2): - return - - server = session.server - quote_split = ' '.join(cdat['uinput']['splitted']).split("\"") - - if len(quote_split) < 2: - session.msg("You must enclose your username in quotation marks.") - return - - uname = quote_split[1] - lastarg_split = quote_split[2].split() + # Argument check. + if not functions_general.cmd_check_num_args(session, cdat['uinput']['splitted'], 2): + return + + server = session.server + quote_split = ' '.join(cdat['uinput']['splitted']).split("\"") + + if len(quote_split) < 2: + session.msg("You must enclose your username in quotation marks.") + return + + uname = quote_split[1] + lastarg_split = quote_split[2].split() - if len(lastarg_split) != 2: - session.msg("You must specify an email address, followed by a password!") - return - - email = lastarg_split[0] - password = lastarg_split[1] + if len(lastarg_split) != 2: + session.msg("You must specify an email address, followed by a password!") + return + + email = lastarg_split[0] + password = lastarg_split[1] - # Search for a user object with the specified username. - account = User.objects.filter(username=uname) - # Match an email address to an account. - email_matches = functions_db.get_user_from_email(email) - - if not account.count() == 0: - session.msg("There is already a player with that name!") - elif not email_matches.count() == 0: - session.msg("There is already a player with that email address!") - elif len(password) < 3: - session.msg("Your password must be 3 characters or longer.") - else: - functions_db.create_user(cdat, uname, email, password) + # Search for a user object with the specified username. + account = User.objects.filter(username=uname) + # Match an email address to an account. + email_matches = functions_db.get_user_from_email(email) + # Look for any objects with an 'Alias' attribute that matches + # the requested username + alias_matches = Object.objects.filter(attribute__attr_name__exact="ALIAS", + attribute__attr_value__iexact=uname).filter( + type=defines_global.OTYPE_PLAYER) + + if not account.count() == 0 or not alias_matches.count() == 0: + session.msg("There is already a player with that name!") + elif not email_matches.count() == 0: + session.msg("There is already a player with that email address!") + elif len(password) < 3: + session.msg("Your password must be 3 characters or longer.") + else: + functions_db.create_user(cdat, uname, email, password) def cmd_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() + """ + 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() diff --git a/functions_db.py b/functions_db.py index 6e06e9c86e..edc8fa3942 100644 --- a/functions_db.py +++ b/functions_db.py @@ -4,341 +4,372 @@ from datetime import datetime, timedelta from django.db import connection from django.contrib.auth.models import User from apps.objects.models import Object, Attribute -import defines_global as defines_global +import defines_global import gameconf +from django.db.models import Q """ Common database functions. """ def num_total_players(): - """ - Returns the total number of registered players. - """ - return User.objects.count() + """ + Returns the total number of registered players. + """ + return User.objects.count() def get_connected_players(): - """ - Returns the a QuerySet containing the currently connected players. - """ - return Object.objects.filter(nosave_flags__contains="CONNECTED") + """ + Returns the a QuerySet containing the currently connected players. + """ + return Object.objects.filter(nosave_flags__contains="CONNECTED") def get_recently_created_players(days=7): - """ - Returns a QuerySet containing the player User accounts that have been - connected within the last days. - """ - end_date = datetime.now() - tdelta = timedelta(days) - start_date = end_date - tdelta - return User.objects.filter(date_joined__range=(start_date, end_date)) + """ + Returns a QuerySet containing the player User accounts that have been + connected within the last days. + """ + end_date = datetime.now() + tdelta = timedelta(days) + start_date = end_date - tdelta + return User.objects.filter(date_joined__range=(start_date, end_date)) def get_recently_connected_players(days=7): - """ - Returns a QuerySet containing the player User accounts that have been - connected within the last days. - """ - end_date = datetime.now() - tdelta = timedelta(days) - start_date = end_date - tdelta - return User.objects.filter(last_login__range=(start_date, end_date)).order_by('-last_login') + """ + Returns a QuerySet containing the player User accounts that have been + connected within the last days. + """ + end_date = datetime.now() + tdelta = timedelta(days) + start_date = end_date - tdelta + return User.objects.filter(last_login__range=(start_date, end_date)).order_by('-last_login') def is_unsavable_flag(flagname): - """ - Returns TRUE if the flag is an unsavable flag. - """ - return flagname.upper() in defines_global.NOSAVE_FLAGS + """ + Returns TRUE if the flag is an unsavable flag. + """ + return flagname.upper() in defines_global.NOSAVE_FLAGS def is_modifiable_flag(flagname): - """ - Check to see if a particular flag is modifiable. - """ - if flagname.upper() not in defines_global.NOSET_FLAGS: - return True - else: - return False - + """ + Check to see if a particular flag is modifiable. + """ + if flagname.upper() not in defines_global.NOSET_FLAGS: + return True + else: + return False + def is_modifiable_attrib(attribname): - """ - Check to see if a particular attribute is modifiable. + """ + Check to see if a particular attribute is modifiable. - attribname: (string) An attribute name to check. - """ - if attribname.upper() not in defines_global.NOSET_ATTRIBS: - return True - else: - return False - + attribname: (string) An attribute name to check. + """ + if attribname.upper() not in defines_global.NOSET_ATTRIBS: + return True + else: + return False + def get_nextfree_dbnum(): - """ - Figure out what our next free database reference number is. - - If we need to recycle a GARBAGE object, return the object to recycle - Otherwise, return the first free dbref. - """ - # First we'll see if there's an object of type 6 (GARBAGE) that we - # can recycle. - nextfree = Object.objects.filter(type__exact=defines_global.OTYPE_GARBAGE) - if nextfree: - # We've got at least one garbage object to recycle. - return nextfree.id - else: - # No garbage to recycle, find the highest dbnum and increment it - # for our next free. - return int(Object.objects.order_by('-id')[0].id + 1) + """ + Figure out what our next free database reference number is. + + If we need to recycle a GARBAGE object, return the object to recycle + Otherwise, return the first free dbref. + """ + # First we'll see if there's an object of type 6 (GARBAGE) that we + # can recycle. + nextfree = Object.objects.filter(type__exact=defines_global.OTYPE_GARBAGE) + if nextfree: + # We've got at least one garbage object to recycle. + return nextfree.id + else: + # No garbage to recycle, find the highest dbnum and increment it + # for our next free. + return int(Object.objects.order_by('-id')[0].id + 1) def global_object_name_search(ostring, exact_match=False): - """ - Searches through all objects for a name match. - """ - if exact_match: - return Object.objects.filter(name__iexact=ostring).exclude(type=defines_global.OTYPE_GARBAGE) - else: - return Object.objects.filter(name__icontains=ostring).exclude(type=defines_global.OTYPE_GARBAGE) - + """ + Searches through all objects for a name match. + """ + if exact_match: + return Object.objects.filter(name__iexact=ostring).exclude(type=defines_global.OTYPE_GARBAGE) + else: + return Object.objects.filter(name__icontains=ostring).exclude(type=defines_global.OTYPE_GARBAGE) + def list_search_object_namestr(searchlist, ostring, dbref_only=False, limit_types=False, match_type="fuzzy"): - """ - Iterates through a list of objects and returns a list of - name matches. - searchlist: (List of Objects) The objects to perform name comparisons on. - ostring: (string) The string to match against. - dbref_only: (bool) Only compare dbrefs. - limit_types: (list of int) A list of Object type numbers to filter by. - """ - if dbref_only: - if limit_types: - return [prospect for prospect in searchlist if prospect.dbref_match(ostring) and prospect.type in limit_types] - else: - return [prospect for prospect in searchlist if prospect.dbref_match(ostring)] - else: - if limit_types: - return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type) and prospect.type in limit_types] - else: - return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)] + """ + Iterates through a list of objects and returns a list of + name matches. + searchlist: (List of Objects) The objects to perform name comparisons on. + ostring: (string) The string to match against. + dbref_only: (bool) Only compare dbrefs. + limit_types: (list of int) A list of Object type numbers to filter by. + """ + if dbref_only: + if limit_types: + return [prospect for prospect in searchlist if prospect.dbref_match(ostring) and prospect.type in limit_types] + else: + return [prospect for prospect in searchlist if prospect.dbref_match(ostring)] + else: + if limit_types: + return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type) and prospect.type in limit_types] + else: + return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)] -def player_search(searcher, ostring): - """ - Combines an alias and local/global search for a player's name. If there are - no alias matches, do a global search limiting by type PLAYER. - - searcher: (Object) The object doing the searching. - ostring: (string) The alias string to search for. - """ - alias_results = alias_search(searcher, ostring) - if len(alias_results) > 0: - return alias_results - else: - return local_and_global_search(searcher, ostring, limit_types=[defines_global.OTYPE_PLAYER]) def standard_plr_objsearch(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. + """ + Perform a standard object search via a player session, handling multiple + results and lack thereof gracefully. - session: (SessionProtocol) Reference to the player's session. - ostring: (str) The string to match object names against. - """ - pobject = session.get_pobject() - results = local_and_global_search(pobject, ostring, search_contents=search_contents, search_location=search_location, dbref_only=dbref_only, limit_types=limit_types) + session: (SessionProtocol) Reference to the player's session. + ostring: (str) The string to match object names against. + """ + pobject = session.get_pobject() + results = 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):") - for result in results: - session.msg(" %s" % (result.get_name(),)) - return False - elif len(results) == 0: - session.msg("I don't see that here.") - return False - else: - return results[0] + if len(results) > 1: + session.msg("More than one match found (please narrow target):") + for result in results: + session.msg(" %s" % (result.get_name(),)) + return False + elif len(results) == 0: + session.msg("I don't see that here.") + return False + else: + return results[0] def object_totals(): - """ - Returns a dictionary with database object totals. - """ - dbtotals = {} - dbtotals["objects"] = Object.objects.count() - dbtotals["things"] = Object.objects.filter(type=defines_global.OTYPE_THING).count() - dbtotals["exits"] = Object.objects.filter(type=defines_global.OTYPE_EXIT).count() - dbtotals["rooms"] = Object.objects.filter(type=defines_global.OTYPE_ROOM).count() - dbtotals["garbage"] = Object.objects.filter(type=defines_global.OTYPE_GARBAGE).count() - dbtotals["players"] = Object.objects.filter(type=defines_global.OTYPE_PLAYER).count() - return dbtotals + """ + Returns a dictionary with database object totals. + """ + dbtotals = {} + dbtotals["objects"] = Object.objects.count() + dbtotals["things"] = Object.objects.filter(type=defines_global.OTYPE_THING).count() + dbtotals["exits"] = Object.objects.filter(type=defines_global.OTYPE_EXIT).count() + dbtotals["rooms"] = Object.objects.filter(type=defines_global.OTYPE_ROOM).count() + dbtotals["garbage"] = Object.objects.filter(type=defines_global.OTYPE_GARBAGE).count() + dbtotals["players"] = Object.objects.filter(type=defines_global.OTYPE_PLAYER).count() + return dbtotals def alias_search(searcher, 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) - results = Attribute.objects.select_related().filter(attr_value__iexact=ostring) - return [prospect.get_object() for prospect in results if prospect.get_object().is_player()] - + """ + 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) + 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()] + +def player_name_search(search_string): + """ + Combines an alias and global search for a player's name. If there are + no alias matches, do a global search limiting by type PLAYER. + + search_string: (string) The name string to search for. + """ + # Handle the case where someone might have started the search_string + # with a * + if search_string.startswith('*') is True: + search_string = search_string[1:] + # Use Q objects to build complex OR query to look at either + # the player name or ALIAS attribute + player_filter = Q(name__iexact=search_string) + alias_filter = Q(attribute__attr_name__exact="ALIAS") & \ + Q(attribute__attr_value__iexact=search_string) + player_matches = Object.objects.filter( + player_filter | alias_filter).filter( + type=defines_global.OTYPE_PLAYER).distinct() + try: + return player_matches[0] + except IndexError: + return None + +def dbref_search(dbref_string, limit_types=False): + """ + Searches for a given dbref. + + dbref_number: (string) The dbref to search for + limit_types: (list of int) A list of Object type numbers to filter by. + """ + if not is_dbref(dbref_string): + return None + dbref_string = dbref_string[1:] + dbref_matches = Object.objects.filter(id=dbref_string).exclude( + type=defines_global.OTYPE_GARBAGE) + # Check for limiters + if limit_types is not False: + for limiter in limit_types: + dbref_matches.filter(type=limiter) + try: + return dbref_matches[0] + except IndexError: + return None + def local_and_global_search(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. - - searcher: (Object) The object performing the search. - ostring: (string) The string to compare names against. - search_contents: (bool) While true, check the contents of the searcher. - search_location: (bool) While true, check the searcher's surroundings. - dbref_only: (bool) Only compare dbrefs. - limit_types: (list of int) A list of Object type numbers to filter by. - """ - search_query = ''.join(ostring) + """ + Searches an object's location then globally for a dbref or name match. + + searcher: (Object) The object performing the search. + ostring: (string) The string to compare names against. + search_contents: (bool) While true, check the contents of the searcher. + search_location: (bool) While true, check the searcher's surroundings. + dbref_only: (bool) Only compare dbrefs. + limit_types: (list of int) A list of Object type numbers to filter by. + """ + search_query = ''.join(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 is_dbref(ostring) and search_contents and search_location: - search_num = search_query[1:] - dbref_results = Object.objects.filter(id=search_num).exclude(type=6) + # 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 is_dbref(ostring): + search_num = search_query[1:] + dbref_match = dbref_search(search_num, limit_types) + if dbref_match is not None: + return [dbref_match] - # If there is a type limiter in, filter by it. - if limit_types: - for limiter in limit_types: - dbref_results.filter(type=limiter) - - dbref_match = list(dbref_results) - if len(dbref_match) > 0: - return dbref_match + # If the search string is one of the following, return immediately with + # the appropriate result. + if searcher.get_location().dbref_match(ostring) or ostring == 'here': + return [searcher.get_location()] + elif ostring == 'me' and searcher: + return [searcher] - # If the search string is one of the following, return immediately with - # the appropriate result. - if searcher.get_location().dbref_match(ostring) or ostring == 'here': - return [searcher.get_location()] - elif ostring == 'me' and searcher: - return [searcher] + if search_query[0] == "*": + # Player search- gotta search by name or alias + search_target = search_query[1:] + player_match = player_name_search(search_target) + if player_match is not None: + return [player_match] - local_matches = [] - # 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) - if search_location: - local_matches += list_search_object_namestr(searcher.get_location().get_contents(), search_query, limit_types=limit_types) - - return local_matches + local_matches = [] + # 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) + if search_location: + local_matches += list_search_object_namestr(searcher.get_location().get_contents(), search_query, limit_types=limit_types) + return local_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 - + """ + Is the input a well-formed dbref number? + """ + try: + number = int(dbstring[1:]) + except ValueError: + return False + if not dbstring.startswith("#"): + return False + elif number < 1: + return False + else: + return True + def get_user_from_email(uemail): - """ - Returns a player's User object when given an email address. - """ - return User.objects.filter(email__iexact=uemail) + """ + Returns a player's User object when given an email address. + """ + return User.objects.filter(email__iexact=uemail) def get_object_from_dbref(dbref): - """ - Returns an object when given a dbref. - """ - return Object.objects.get(id=dbref) - + """ + Returns an object when given a dbref. + """ + return Object.objects.get(id=dbref) + def create_object(odat): - """ - Create a new object. odat is a dictionary that contains the following keys. - REQUIRED KEYS: - * type: Integer representing the object's type. - * name: The name of the new object. - * location: Reference to another object for the new object to reside in. - * owner: The creator of the object. - OPTIONAL KEYS: - * home: Reference to another object to home to. If not specified, use - location key for home. - """ - next_dbref = get_nextfree_dbnum() - new_object = Object() + """ + Create a new object. odat is a dictionary that contains the following keys. + REQUIRED KEYS: + * type: Integer representing the object's type. + * name: The name of the new object. + * location: Reference to another object for the new object to reside in. + * owner: The creator of the object. + OPTIONAL KEYS: + * home: Reference to another object to home to. If not specified, use + location key for home. + """ + next_dbref = get_nextfree_dbnum() + new_object = Object() - new_object.id = next_dbref - new_object.type = odat["type"] - new_object.set_name(odat["name"]) + new_object.id = next_dbref + new_object.type = odat["type"] + new_object.set_name(odat["name"]) - # If this is a player, we don't want him owned by anyone. - # The get_owner() function will return that the player owns - # himself. - if odat["type"] == 1: - new_object.owner = None - new_object.zone = None - else: - new_object.owner = odat["owner"] - - if new_object.get_owner().get_zone(): - new_object.zone = new_object.get_owner().get_zone() + # If this is a player, we don't want him owned by anyone. + # The get_owner() function will return that the player owns + # himself. + if odat["type"] == 1: + new_object.owner = None + new_object.zone = None + else: + new_object.owner = odat["owner"] + + if new_object.get_owner().get_zone(): + new_object.zone = new_object.get_owner().get_zone() - # If we have a 'home' key, use that for our home value. Otherwise use - # the location key. - if odat.has_key("home"): - new_object.home = odat["home"] - else: - if new_object.is_exit(): - new_object.home = None - else: - new_object.home = odat["location"] - - new_object.save() + # If we have a 'home' key, use that for our home value. Otherwise use + # the location key. + if odat.has_key("home"): + new_object.home = odat["home"] + else: + if new_object.is_exit(): + new_object.home = None + else: + new_object.home = odat["location"] + + new_object.save() - # Rooms have a NULL location. - if not new_object.is_room(): - new_object.move_to(odat['location']) - - return new_object + # Rooms have a NULL location. + if not new_object.is_room(): + new_object.move_to(odat['location']) + + return new_object def create_user(cdat, uname, email, password): - """ - Handles the creation of new users. - """ - session = cdat['session'] - server = cdat['server'] - start_room = int(gameconf.get_configvalue('player_dbnum_start')) - start_room_obj = get_object_from_dbref(start_room) + """ + Handles the creation of new users. + """ + session = cdat['session'] + server = cdat['server'] + start_room = int(gameconf.get_configvalue('player_dbnum_start')) + start_room_obj = 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 + # 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 - # 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 + # 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. - user.save() - - # We can't use the user model to change the id because of the way keys - # are handled, so we actually need to fall back to raw SQL. Boo hiss. - cursor = connection.cursor() - cursor.execute("UPDATE auth_user SET id=%d WHERE id=%d" % (uid, user.id)) - - # Grab the user object again since we've changed it and the old reference - # is no longer valid. - user = User.objects.get(id=uid) + user = User.objects.create_user(uname, email, password) + # It stinks to have to do this but it's the only trivial way now. + user.save() + + # We can't use the user model to change the id because of the way keys + # are handled, so we actually need to fall back to raw SQL. Boo hiss. + cursor = connection.cursor() + cursor.execute("UPDATE auth_user SET id=%d WHERE id=%d" % (uid, user.id)) + + # Grab the user object again since we've changed it and the old reference + # is no longer valid. + 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) + # 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) - # Activate the player's session and set them loose. - session.login(user) - print 'Registration: %s' % (session,) - session.msg("Welcome to %s, %s.\n\r" % (gameconf.get_configvalue('site_name'), session.get_pobject().get_name(show_dbref=False),)) + # Activate the player's session and set them loose. + session.login(user) + print 'Registration: %s' % (session,) + session.msg("Welcome to %s, %s.\n\r" % (gameconf.get_configvalue('site_name'), session.get_pobject().get_name(show_dbref=False),)) diff --git a/scripts/basicobject.py b/scripts/basicobject.py index 8903d02167..7cfcaa70ea 100644 --- a/scripts/basicobject.py +++ b/scripts/basicobject.py @@ -6,132 +6,138 @@ default. It will have the necessary outline for developers to sub-class and over import ansi class BasicObject: - def __init__(self, source_obj): - """ - Get our ducks in a row. - - source_obj: (Object) A reference to the object being scripted (the child). - """ - self.source_obj = source_obj - - def a_desc(self, values): - """ - Perform this action when someone uses the LOOK command on the object. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Un-comment the line below for an example - #print "SCRIPT TEST: %s looked at %s." % (values["pobject"], self.source_obj) - pass + def __init__(self, source_obj): + """ + Get our ducks in a row. + + source_obj: (Object) A reference to the object being scripted (the child). + """ + self.source_obj = source_obj + + def a_desc(self, values): + """ + Perform this action when someone uses the LOOK command on the object. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Un-comment the line below for an example + #print "SCRIPT TEST: %s looked at %s." % (values["pobject"], self.source_obj) + pass - def return_appearance(self, values): - """ - Returns a string representation of an object's appearance when LOOKed at. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - target_obj = self.source_obj - pobject = values["pobject"] - retval = "\r\n%s\r\n%s" % ( - target_obj.get_name(), - target_obj.get_description(), - ) + def return_appearance(self, values): + """ + Returns a string representation of an object's appearance when LOOKed at. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + target_obj = self.source_obj + pobject = values["pobject"] + description = target_obj.get_description() + if description is not None: + retval = "%s\r\n%s" % ( + target_obj.get_name(), + target_obj.get_description(), + ) + else: + retval = "%s" % ( + target_obj.get_name(), + ) - con_players = [] - con_things = [] - con_exits = [] - - for obj in target_obj.get_contents(): - if obj.is_player(): - if obj != pobject and obj.is_connected_plr(): - con_players.append(obj) - elif obj.is_exit(): - con_exits.append(obj) - else: - con_things.append(obj) - - if con_players: - retval += "\n\r%sPlayers:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) - for player in con_players: - retval +='\n\r%s' %(player.get_name(),) - if con_things: - retval += "\n\r%sContents:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) - for thing in con_things: - retval += '\n\r%s' %(thing.get_name(),) - if con_exits: - retval += "\n\r%sExits:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) - for exit in con_exits: - retval += '\n\r%s' %(exit.get_name(),) + con_players = [] + con_things = [] + con_exits = [] + + for obj in target_obj.get_contents(): + if obj.is_player(): + if obj != pobject and obj.is_connected_plr(): + con_players.append(obj) + elif obj.is_exit(): + con_exits.append(obj) + else: + con_things.append(obj) + + if not con_players == []: + retval += "\n\r%sPlayers:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) + for player in con_players: + retval +='\n\r%s' %(player.get_name(),) + if not con_things == []: + retval += "\n\r%sContents:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) + for thing in con_things: + retval += '\n\r%s' %(thing.get_name(),) + if not con_exits == []: + retval += "\n\r%sExits:%s" % (ansi.ansi["hilite"], ansi.ansi["normal"],) + for exit in con_exits: + retval += '\n\r%s' %(exit.get_name(),) - return retval + return retval - def a_get(self, values): - """ - Perform this action when someone uses the GET command on the object. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Un-comment the line below for an example - #print "SCRIPT TEST: %s got %s." % (values["pobject"], self.source_obj) - pass + def a_get(self, values): + """ + Perform this action when someone uses the GET command on the object. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Un-comment the line below for an example + #print "SCRIPT TEST: %s got %s." % (values["pobject"], self.source_obj) + pass - def a_drop(self, values): - """ - Perform this action when someone uses the GET command on the object. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Un-comment the line below for an example - #print "SCRIPT TEST: %s dropped %s." % (values["pobject"], self.source_obj) - pass + def a_drop(self, values): + """ + Perform this action when someone uses the GET command on the object. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Un-comment the line below for an example + #print "SCRIPT TEST: %s dropped %s." % (values["pobject"], self.source_obj) + pass - def default_lock(self, values): - """ - This method returns a True or False boolean value to determine whether - the actor passes the lock. This is generally used for picking up - objects or traversing exits. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Assume everyone passes the default lock by default. - return True + def default_lock(self, values): + """ + This method returns a True or False boolean value to determine whether + the actor passes the lock. This is generally used for picking up + objects or traversing exits. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Assume everyone passes the default lock by default. + return True - def use_lock(self, values): - """ - This method returns a True or False boolean value to determine whether - the actor passes the lock. This is generally used for seeing whether - a player can use an object or any of its commands. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Assume everyone passes the use lock by default. - return True + def use_lock(self, values): + """ + This method returns a True or False boolean value to determine whether + the actor passes the lock. This is generally used for seeing whether + a player can use an object or any of its commands. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Assume everyone passes the use lock by default. + return True - def enter_lock(self, values): - """ - This method returns a True or False boolean value to determine whether - the actor passes the lock. This is generally used for seeing whether - a player can enter another object. - - values: (Dict) Script arguments with keys: - * pobject: The object requesting the action. - """ - # Assume everyone passes the enter lock by default. - return True - + def enter_lock(self, values): + """ + This method returns a True or False boolean value to determine whether + the actor passes the lock. This is generally used for seeing whether + a player can enter another object. + + values: (Dict) Script arguments with keys: + * pobject: The object requesting the action. + """ + # Assume everyone passes the enter lock by default. + return True + def class_factory(source_obj): - """ - This method is called any script you retrieve (via the scripthandler). It - creates an instance of the class and returns it transparently. I'm not - sure how well this will scale, but we'll find out. We may need to - re-factor this eventually. - - source_obj: (Object) A reference to the object being scripted (the child). - """ - return BasicObject(source_obj) \ No newline at end of file + """ + This method is called any script you retrieve (via the scripthandler). It + creates an instance of the class and returns it transparently. I'm not + sure how well this will scale, but we'll find out. We may need to + re-factor this eventually. + + source_obj: (Object) A reference to the object being scripted (the child). + """ + return BasicObject(source_obj)