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)