diff --git a/src/commands/objmanip.py b/src/commands/objmanip.py index 4194850d18..36556cdd86 100644 --- a/src/commands/objmanip.py +++ b/src/commands/objmanip.py @@ -1022,6 +1022,7 @@ def cmd_dig(command): None, source_object, script_parent=room_parent) + ptext = "" if room_parent: if new_room.get_script_parent() == room_parent: @@ -1277,26 +1278,26 @@ def cmd_destroy(command): switch_override = True for targetname in targetlist: - target_obj = source_object.search_for_object(targetname) + target_obj = source_object.search_for_object_global(targetname) # Use search_for_object to handle duplicate/nonexistant results. if not target_obj: return if target_obj.is_player() or target_obj.has_flag('SAFE'): if source_object.id == target_obj.id: - source_object.emit_to("You can't destroy yourself.") - return + source_object.emit_to("%s: You can't destroy yourself." % targetname) + continue if not switch_override: - source_object.emit_to("You must use @destroy/override on Players and objects with the SAFE flag set.") - return + source_object.emit_to("%s: You must use @destroy/override on Players and objects with the SAFE flag set." % targetname) + continue if target_obj.is_superuser(): - source_object.emit_to("You can't destroy a superuser.") - return + source_object.emit_to("%s: You can't destroy a superuser." % targetname) + continue elif target_obj.is_garbage(): - source_object.emit_to("That object is already destroyed.") - return + source_object.emit_to("%s: That object is already destroyed." % targetname) + continue elif target_obj.is_going() and 'instant' not in switches: - source_object.emit_to("That object is already scheduled for destruction.") - return + source_object.emit_to("%s: That object is already scheduled for destruction." % targetname) + continue # Run any scripted things that happen before destruction. target_obj.scriptlink.at_object_destruction(pobject=source_object) @@ -1370,10 +1371,13 @@ def cmd_lock(command): EnterLock: Players/Things: controls who may enter/teleport into the object. + VisibleLock: Players/Things: controls if the object is visible to + someone using the look command. Fail messages echoed to the player are stored in the attributes 'lock_msg', - 'use_lock_msg' and 'enter_lock_msg' on the locked object in question. If no - such message is stored, a default will be used (or none at all in some cases). + 'use_lock_msg', 'enter_lock_msg' and 'visible_lock_msg' on the locked object + in question. If no such message is stored, a default will be used (or none at + all in some cases). """ source_object = command.source_object @@ -1397,7 +1401,7 @@ def cmd_lock(command): ltype = "DefaultLock" obj_name, ltype = obj_name.strip(), ltype.strip() - if ltype not in ["DefaultLock","UseLock","EnterLock"]: + if ltype not in ["DefaultLock","UseLock","EnterLock","VisibleLock"]: source_object.emit_to("Lock type '%s' not recognized." % ltype) return @@ -1407,7 +1411,7 @@ def cmd_lock(command): obj_locks = obj.get_attribute_value("LOCKS") - if "list" in switches or not switches: + if "list" in switches: if not obj_locks: s = "There are no locks on %s." % obj.get_name() else: diff --git a/src/locks.py b/src/locks.py index 3ab8ce2721..cbee64fa03 100644 --- a/src/locks.py +++ b/src/locks.py @@ -44,10 +44,9 @@ class Key(object): def __str__(self): string = " " if not self.criteria: - string += " " - for crit in self.criteria: - string += " %s," % crit - return string[:-1].strip() + string += " (Impassable)" + string += ", ".join(self.criteria) + return string def _result(self, result): "Return result depending on exact criterion." diff --git a/src/objects/managers/object.py b/src/objects/managers/object.py index 29b3bb2e77..7b973093c4 100644 --- a/src/objects/managers/object.py +++ b/src/objects/managers/object.py @@ -133,21 +133,35 @@ class ObjectManager(models.Manager): except IndexError: return None - def global_object_name_search(self, ostring, exact_match=False, limit_types=[]): + def global_object_name_search(self, ostring, exact_match=True, limit_types=[]): """ Searches through all objects for a name match. limit_types is a list of types as defined in defines_global. """ if self.is_dbref(ostring): - return [self.dbref_search(ostring, limit_types=limit_types)] - + o_query = self.dbref_search(ostring, limit_types=limit_types) + if o_query: + return [o_query] + return None + # get rough match + o_query = self.filter(name__icontains=ostring) + o_query = o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE, + defines_global.OTYPE_GOING]) + if not o_query: + # use list-search to catch N-style queries. Note + # that we want to keep the original ostring since + # search_object_namestr does its own N-string treatment + # on this. + dum, test_ostring = self._parse_match_number(ostring) + o_query = self.filter(name__icontains=test_ostring) + o_query = o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE, + defines_global.OTYPE_GOING]) + match_type = "fuzzy" if exact_match: - o_query = self.filter(name__iexact=ostring) - else: - o_query = self.filter(name__icontains=ostring) - if limit_types is not False: - for limiter in limit_types: - o_query.filter(type=limiter) + match_type = "exact" + return self.list_search_object_namestr(o_query, ostring, + limit_types=limit_types, + match_type=match_type) return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE, defines_global.OTYPE_GOING]) @@ -196,16 +210,16 @@ class ObjectManager(models.Manager): if prospect.dbref_match(ostring)] #search by name - this may return multiple matches. - results = self._list_search_helper1(searchlist,ostring,dbref_only, + results = self._match_name_attribute(searchlist,ostring,dbref_only, limit_types, match_type, attribute_name=attribute_name) match_number = None if not results: #if we have no match, check if we are dealing #with a "N-keyword" query - if so, strip it and run again. - match_number, ostring = self._list_search_helper2(ostring) + match_number, ostring = self._parse_match_number(ostring) if match_number != None and ostring: - results = self._list_search_helper1(searchlist,ostring,dbref_only, + results = self._match_name_attribute(searchlist,ostring,dbref_only, limit_types, match_type, attribute_name=attribute_name) if match_type == "fuzzy": @@ -226,7 +240,7 @@ class ObjectManager(models.Manager): pass return results - def _list_search_helper1(self, searchlist, ostring, dbref_only, + def _match_name_attribute(self, searchlist, ostring, dbref_only, limit_types, match_type, attribute_name=None): """ @@ -261,10 +275,10 @@ class ObjectManager(models.Manager): return [prospect for prospect in searchlist if prospect.name_match(ostring, match_type=match_type)] - def _list_search_helper2(self, ostring): + def _parse_match_number(self, ostring): """ - Hhelper function for list_search_object_namestr - - strips eventual keyword-N endings from a search criterion + Helper function for list_search_object_namestr - + strips eventual N-keyword endings from a search criterion """ if not '-' in ostring: return False, ostring @@ -426,6 +440,7 @@ class ObjectManager(models.Manager): default_desc = defines_global.DESC_PLAYER elif otype == defines_global.OTYPE_ROOM: default_desc = defines_global.DESC_ROOM + location = None elif otype == defines_global.OTYPE_EXIT: default_desc = defines_global.DESC_EXIT else: diff --git a/src/objects/models.py b/src/objects/models.py index ad2ca59834..b54b60ab91 100755 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -221,23 +221,27 @@ class Object(models.Model): else: return results[0] - def search_for_object_global(self, ostring, exact_match=True, limit_types=[]): + def search_for_object_global(self, ostring, exact_match=True, limit_types=[], + emit_to_obj=None): """ Search for ostring in all objects, globally. Handle multiple-matches and no matches gracefully. This is mainly intended to be used by admin and build-type commands. It also accepts #dbref search queries. """ + if not emit_to_obj: + emit_to_obj = self + results = Object.objects.global_object_name_search(ostring, exact_match=exact_match, - limit_types=limit_types) + limit_types=limit_types) if not results: - self.emit_to("No matches found for '%s'." % ostring) + emit_to_obj.emit_to("No matches found for '%s'." % ostring) return if len(results) > 1: string = "More than one match for '%s' (please narrow target):" % ostring for res in results: string += "\n %s" % res.get_name() - self.emit_to(string) + emit_to_obj.emit_to(string) return return results[0] @@ -1157,7 +1161,10 @@ class Object(models.Model): self.clear_all_attributes() self.clear_all_flags() self.clear_state() - + self.home = None + self.owner = None + self.location = None + self.save() # Deferred imports are poopy. This will require some thought to fix. from src import cmdhandler diff --git a/src/script_parents/basicobject.py b/src/script_parents/basicobject.py index 74ea9345c2..66fd84ba2a 100644 --- a/src/script_parents/basicobject.py +++ b/src/script_parents/basicobject.py @@ -133,10 +133,17 @@ class EvenniaBasicObject(object): * pobject: (Object) The object requesting the action. """ # This is the object being looked at. - target_obj = self.scripted_obj + target_obj = self.scripted_obj # See if the envoker sees dbref numbers. lock_msg = "" if pobject: + #check visibility lock + if not target_obj.scriptlink.visible_lock(pobject): + temp = target_obj.get_attribute_value("visible_lock_msg") + if temp: + return temp + return "I don't see that here." + show_dbrefs = pobject.sees_dbrefs() #check for the defaultlock, this shows a lock message after the normal desc, if one is defined. @@ -165,8 +172,11 @@ class EvenniaBasicObject(object): con_exits = [] for obj in target_obj.get_contents(): + # check visible lock. + if pobject and not obj.scriptlink.visible_lock(pobject): + continue if obj.is_player(): - if (obj != pobject and obj.is_connected_plr()) or pobject == None: + if (obj != pobject and obj.is_connected_plr()) or pobject == None: con_players.append(obj) elif obj.is_exit(): con_exits.append(obj) @@ -236,6 +246,21 @@ class EvenniaBasicObject(object): else: return True + def visible_lock(self, pobject): + """ + 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: + * pobject: (Object) The object requesting the action. + """ + locks = self.scripted_obj.get_attribute_value("LOCKS") + if locks: + return locks.check("VisibleLock", pobject) + else: + return True + def lock_func(self, obj): """ This is a custom function called by locks with the FuncKey key. Its diff --git a/src/script_parents/basicplayer.py b/src/script_parents/basicplayer.py index a00db76536..b920fe1360 100644 --- a/src/script_parents/basicplayer.py +++ b/src/script_parents/basicplayer.py @@ -109,3 +109,74 @@ class EvenniaBasicPlayer(object): location = pobject.get_location() if location != None: location.emit_to_contents("%s has disconnected." % (pobject.get_name(show_dbref=False),), exclude=pobject) + + def default_lock(self, pobject): + """ + 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: + * pobject: (Object) The object requesting the action. + """ + locks = self.scripted_obj.get_attribute_value("LOCKS") + if locks: + return locks.check("DefaultLock", pobject) + else: + return True + + def use_lock(self, pobject): + """ + 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: + * pobject: (Object) The object requesting the action. + """ + locks = self.scripted_obj.get_attribute_value("LOCKS") + if locks: + return locks.check("UseLock", pobject) + else: + return True + + def enter_lock(self, pobject): + """ + 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: + * pobject: (Object) The object requesting the action. + """ + locks = self.scripted_obj.get_attribute_value("LOCKS") + if locks: + return locks.check("EnterLock", pobject) + else: + return True + + def visible_lock(self, pobject): + """ + 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: + * pobject: (Object) The object requesting the action. + """ + locks = self.scripted_obj.get_attribute_value("LOCKS") + if locks: + return locks.check("VisibleLock", pobject) + else: + return True + + def lock_func(self, obj): + """ + This is a custom function called by locks with the FuncKey key. Its + return value should match that specified in the lock (so no true/false + lock result is actually determined in here). Default desired return + value is True. Also remember that the comparison in FuncKey is made + using the string representation of the return value, since @lock can + only define string lock criteria. + """ + return False