mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 04:27:16 +02:00
Further break out return_appearance functionality into helper hooks
This commit is contained in:
parent
7e53fc5cc9
commit
7ae1258df1
1 changed files with 225 additions and 189 deletions
|
|
@ -314,68 +314,6 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
|
||||
# main methods
|
||||
|
||||
def get_display_name(self, looker=None, **kwargs):
|
||||
"""
|
||||
Displays the name of the object in a viewer-aware manner.
|
||||
|
||||
Args:
|
||||
looker (TypedObject): The object or account that is looking
|
||||
at/getting inforamtion for this object.
|
||||
|
||||
Returns:
|
||||
name (str): A string containing the name of the object,
|
||||
including the DBREF if this user is privileged to control
|
||||
said object.
|
||||
|
||||
Notes:
|
||||
This function could be extended to change how object names
|
||||
appear to users in character, but be wary. This function
|
||||
does not change an object's keys or aliases when
|
||||
searching, and is expected to produce something useful for
|
||||
builders.
|
||||
|
||||
"""
|
||||
if looker and self.locks.check_lockstring(looker, "perm(Builder)"):
|
||||
return "{}(#{})".format(self.name, self.id)
|
||||
return self.name
|
||||
|
||||
def get_numbered_name(self, count, looker, **kwargs):
|
||||
"""
|
||||
Return the numbered (singular, plural) forms of this object's key. This is by default called
|
||||
by return_appearance and is used for grouping multiple same-named of this object. Note that
|
||||
this will be called on *every* member of a group even though the plural name will be only
|
||||
shown once. Also the singular display version, such as 'an apple', 'a tree' is determined
|
||||
from this method.
|
||||
|
||||
Args:
|
||||
count (int): Number of objects of this type
|
||||
looker (Object): Onlooker. Not used by default.
|
||||
Keyword Args:
|
||||
key (str): Optional key to pluralize, if given, use this instead of the object's key.
|
||||
Returns:
|
||||
singular (str): The singular form to display.
|
||||
plural (str): The determined plural form of the key, including the count.
|
||||
|
||||
"""
|
||||
plural_category = "plural_key"
|
||||
key = kwargs.get("key", self.key)
|
||||
key = ansi.ANSIString(key) # this is needed to allow inflection of colored names
|
||||
try:
|
||||
plural = _INFLECT.plural(key, count)
|
||||
plural = "{} {}".format(_INFLECT.number_to_words(count, threshold=12), plural)
|
||||
except IndexError:
|
||||
# this is raised by inflect if the input is not a proper noun
|
||||
plural = key
|
||||
singular = _INFLECT.an(key)
|
||||
if not self.aliases.get(plural, category=plural_category):
|
||||
# we need to wipe any old plurals/an/a in case key changed in the interrim
|
||||
self.aliases.clear(category=plural_category)
|
||||
self.aliases.add(plural, category=plural_category)
|
||||
# save the singular form as an alias here too so we can display "an egg" and also
|
||||
# look at 'an egg'.
|
||||
self.aliases.add(singular, category=plural_category)
|
||||
return singular, plural
|
||||
|
||||
def search(
|
||||
self,
|
||||
searchdata,
|
||||
|
|
@ -1248,6 +1186,225 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
self.at_access(result, accessing_obj, access_type, **kwargs)
|
||||
return result
|
||||
|
||||
# name and return_apperance hooks
|
||||
|
||||
def get_display_name(self, looker=None, **kwargs):
|
||||
"""
|
||||
Displays the name of the object in a viewer-aware manner.
|
||||
|
||||
Args:
|
||||
looker (TypedObject): The object or account that is looking
|
||||
at/getting inforamtion for this object.
|
||||
|
||||
Returns:
|
||||
name (str): A string containing the name of the object,
|
||||
including the DBREF if this user is privileged to control
|
||||
said object.
|
||||
|
||||
Notes:
|
||||
This function could be extended to change how object names
|
||||
appear to users in character, but be wary. This function
|
||||
does not change an object's keys or aliases when
|
||||
searching, and is expected to produce something useful for
|
||||
builders.
|
||||
|
||||
"""
|
||||
if looker and self.locks.check_lockstring(looker, "perm(Builder)"):
|
||||
return "{}(#{})".format(self.name, self.id)
|
||||
return self.name
|
||||
|
||||
def get_numbered_name(self, count, looker, **kwargs):
|
||||
"""
|
||||
Return the numbered (singular, plural) forms of this object's key. This is by default called
|
||||
by return_appearance and is used for grouping multiple same-named of this object. Note that
|
||||
this will be called on *every* member of a group even though the plural name will be only
|
||||
shown once. Also the singular display version, such as 'an apple', 'a tree' is determined
|
||||
from this method.
|
||||
|
||||
Args:
|
||||
count (int): Number of objects of this type
|
||||
looker (Object): Onlooker. Not used by default.
|
||||
Keyword Args:
|
||||
key (str): Optional key to pluralize, if given, use this instead of the object's key.
|
||||
Returns:
|
||||
singular (str): The singular form to display.
|
||||
plural (str): The determined plural form of the key, including the count.
|
||||
|
||||
"""
|
||||
plural_category = "plural_key"
|
||||
key = kwargs.get("key", self.key)
|
||||
key = ansi.ANSIString(key) # this is needed to allow inflection of colored names
|
||||
try:
|
||||
plural = _INFLECT.plural(key, count)
|
||||
plural = "{} {}".format(_INFLECT.number_to_words(count, threshold=12), plural)
|
||||
except IndexError:
|
||||
# this is raised by inflect if the input is not a proper noun
|
||||
plural = key
|
||||
singular = _INFLECT.an(key)
|
||||
if not self.aliases.get(plural, category=plural_category):
|
||||
# we need to wipe any old plurals/an/a in case key changed in the interrim
|
||||
self.aliases.clear(category=plural_category)
|
||||
self.aliases.add(plural, category=plural_category)
|
||||
# save the singular form as an alias here too so we can display "an egg" and also
|
||||
# look at 'an egg'.
|
||||
self.aliases.add(singular, category=plural_category)
|
||||
return singular, plural
|
||||
|
||||
def get_display_header(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'header' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The header display string.
|
||||
|
||||
"""
|
||||
return ""
|
||||
|
||||
def get_display_desc(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'desc' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The desc display string..
|
||||
|
||||
"""
|
||||
return self.db.desc or "You see nothing special."
|
||||
|
||||
def get_display_exits(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'exits' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The exits display data.
|
||||
|
||||
"""
|
||||
|
||||
def _filter_visible(obj_list):
|
||||
return (obj for obj in obj_list if obj != looker and obj.access(looker, "view"))
|
||||
|
||||
exits = _filter_visible(self.contents_get(content_type="exit"))
|
||||
exit_names = list_to_string(exi.get_display_name(looker, **kwargs) for exi in exits)
|
||||
|
||||
return f"|wExits:|n {exit_names}" if exit_names else ""
|
||||
|
||||
def get_display_characters(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'characters' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The character display data.
|
||||
|
||||
"""
|
||||
|
||||
def _filter_visible(obj_list):
|
||||
return (obj for obj in obj_list if obj != looker and obj.access(looker, "view"))
|
||||
|
||||
characters = _filter_visible(self.contents_get(content_type="character"))
|
||||
character_names = list_to_string(
|
||||
char.get_display_name(looker, **kwargs) for char in characters
|
||||
)
|
||||
|
||||
return f"\n|wCharacters:|n {character_names}" if character_names else ""
|
||||
|
||||
def get_display_things(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'things' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The things display data.
|
||||
|
||||
"""
|
||||
|
||||
def _filter_visible(obj_list):
|
||||
return (obj for obj in obj_list if obj != looker and obj.access(looker, "view"))
|
||||
|
||||
# sort and handle same-named things
|
||||
things = _filter_visible(self.contents_get(content_type="object"))
|
||||
|
||||
grouped_things = defaultdict(list)
|
||||
for thing in things:
|
||||
grouped_things[thing.get_display_name(looker, **kwargs)].append(thing)
|
||||
|
||||
thing_names = []
|
||||
for thingname, thinglist in sorted(grouped_things.items()):
|
||||
nthings = len(thinglist)
|
||||
thing = thinglist[0]
|
||||
singular, plural = thing.get_numbered_name(nthings, looker, key=thingname)
|
||||
thing_names.append(singular if nthings == 1 else plural)
|
||||
thing_names = list_to_string(thing_names)
|
||||
return f"\n|wYou see:|n {thing_names}" if thing_names else ""
|
||||
|
||||
def get_display_footer(self, looker, **kwargs):
|
||||
"""
|
||||
Get the 'footer' component of the object description. Called by `return_appearance`.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs: Arbitrary data for use when overriding.
|
||||
Returns:
|
||||
str: The footer display string.
|
||||
|
||||
"""
|
||||
return ""
|
||||
|
||||
def return_appearance(self, looker, **kwargs):
|
||||
"""
|
||||
Main callback used by 'look' for the object to describe itself.
|
||||
This formats a description. By default, this looks for the `appearance_template`
|
||||
string set on this class and populates it with formatting keys
|
||||
'name', 'desc', 'exits', 'characters', 'things' as well as
|
||||
(currently empty) 'header'/'footer'. Each of these values are
|
||||
retrieved by a matching method `.get_display_*`, such as `get_display_name`,
|
||||
`get_display_footer` etc.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking. Passed into all helper methods.
|
||||
**kwargs (dict): Arbitrary, optional arguments for users
|
||||
overriding the call. This is passed into all helper methods.
|
||||
|
||||
Returns:
|
||||
str: The description of this entity. By default this includes
|
||||
the entity's name, description and any contents inside it.
|
||||
|
||||
Notes:
|
||||
To simply change the layout of how the object displays itself (like
|
||||
adding some line decorations or change colors of different sections),
|
||||
you can simply edit `.appearance_template`. You only need to override
|
||||
this method (and/or its helpers) if you want to change what is passed
|
||||
into the template or want the most control over output.
|
||||
|
||||
"""
|
||||
|
||||
if not looker:
|
||||
return ""
|
||||
|
||||
# populate the appearance_template string. It's a good idea to strip it and
|
||||
# let the client add any extra spaces instead.
|
||||
return self.appearance_template.format(
|
||||
name=self.get_display_name(looker, **kwargs),
|
||||
desc=self.get_display_desc(looker, **kwargs),
|
||||
header=self.get_display_header(looker, **kwargs),
|
||||
footer=self.get_display_footer(looker, **kwargs),
|
||||
exits=self.get_display_exits(looker, **kwargs),
|
||||
characters=self.get_display_characters(looker, **kwargs),
|
||||
things=self.get_display_things(looker, **kwargs),
|
||||
).strip()
|
||||
|
||||
#
|
||||
# Hook methods
|
||||
#
|
||||
|
|
@ -1624,7 +1781,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
}
|
||||
)
|
||||
|
||||
location.msg_contents((string, {"type": move_type}), exclude=(self,), from_obj=self, mapping=mapping)
|
||||
location.msg_contents(
|
||||
(string, {"type": move_type}), exclude=(self,), from_obj=self, mapping=mapping
|
||||
)
|
||||
|
||||
def announce_move_to(self, source_location, msg=None, mapping=None, move_type="move", **kwargs):
|
||||
"""
|
||||
|
|
@ -1692,7 +1851,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
}
|
||||
)
|
||||
|
||||
destination.msg_contents((string, {"type": move_type}), exclude=(self,), from_obj=self, mapping=mapping)
|
||||
destination.msg_contents(
|
||||
(string, {"type": move_type}), exclude=(self,), from_obj=self, mapping=mapping
|
||||
)
|
||||
|
||||
def at_post_move(self, source_location, move_type="move", **kwargs):
|
||||
"""
|
||||
|
|
@ -1857,131 +2018,6 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
"""
|
||||
pass
|
||||
|
||||
# hooks called by the default cmdset.
|
||||
|
||||
def get_visible_contents(self, looker, **kwargs):
|
||||
"""
|
||||
Get all contents of this object that a looker can see (whatever that means, by default it
|
||||
checks the 'view' lock), grouped by type. Helper method to return_appearance.
|
||||
|
||||
Args:
|
||||
looker (Object): The entity looking.
|
||||
**kwargs (any): Passed from `return_appearance`. Unused by default.
|
||||
|
||||
Returns:
|
||||
dict: A dict of lists categorized by type. Byt default this
|
||||
contains 'exits', 'characters' and 'things'. The elements of these
|
||||
lists are the actual objects.
|
||||
|
||||
"""
|
||||
|
||||
def filter_visible(obj_list):
|
||||
return [obj for obj in obj_list if obj != looker and obj.access(looker, "view")]
|
||||
|
||||
return {
|
||||
"exits": filter_visible(self.contents_get(content_type="exit")),
|
||||
"characters": filter_visible(self.contents_get(content_type="character")),
|
||||
"things": filter_visible(self.contents_get(content_type="object")),
|
||||
}
|
||||
|
||||
def get_content_names(self, looker, **kwargs):
|
||||
"""
|
||||
Get the proper names for all contents of this object. Helper method
|
||||
for return_appearance.
|
||||
|
||||
Args:
|
||||
looker (Object): The entity looking.
|
||||
**kwargs (any): Passed from `return_appearance`. Passed into
|
||||
`get_display_name` for each found entity.
|
||||
|
||||
Returns:
|
||||
dict: A dict of lists categorized by type. Byt default this
|
||||
contains 'exits', 'characters' and 'things'. The elements
|
||||
of these lists are strings - names of the objects that
|
||||
can depend on the looker and also be grouped in the case
|
||||
of multiple same-named things etc.
|
||||
|
||||
Notes:
|
||||
This method shouldn't add extra coloring to the names beyond what is
|
||||
already given by the .get_display_name() (and the .name field) already.
|
||||
Per-type coloring can be applied in `return_apperance`.
|
||||
|
||||
"""
|
||||
# a mapping {'exits': [...], 'characters': [...], 'things': [...]}
|
||||
contents_map = self.get_visible_contents(looker, **kwargs)
|
||||
|
||||
character_names = [
|
||||
char.get_display_name(looker, **kwargs) for char in contents_map["characters"]
|
||||
]
|
||||
exit_names = [exi.get_display_name(looker, **kwargs) for exi in contents_map["exits"]]
|
||||
|
||||
# group all same-named things under one name
|
||||
things = defaultdict(list)
|
||||
for thing in contents_map["things"]:
|
||||
things[thing.get_display_name(looker, **kwargs)].append(thing)
|
||||
|
||||
# pluralize same-named things
|
||||
thing_names = []
|
||||
for thingname, thinglist in sorted(things.items()):
|
||||
nthings = len(thinglist)
|
||||
thing = thinglist[0]
|
||||
singular, plural = thing.get_numbered_name(nthings, looker, key=thingname)
|
||||
thing_names.append(singular if nthings == 1 else plural)
|
||||
|
||||
return {"exits": exit_names, "characters": character_names, "things": thing_names}
|
||||
|
||||
def return_appearance(self, looker, **kwargs):
|
||||
"""
|
||||
Main callback used by 'look' for the object to describe itself.
|
||||
This formats a description. By default, this looks for the `appearance_template`
|
||||
string set on this class and populates it with formatting keys
|
||||
'name', 'desc', 'exits', 'characters', 'things' as well as
|
||||
(currently empty) 'header'/'footer'.
|
||||
|
||||
Args:
|
||||
looker (Object): Object doing the looking.
|
||||
**kwargs (dict): Arbitrary, optional arguments for users
|
||||
overriding the call. This is passed into the helper
|
||||
methods and into `get_display_name` calls.
|
||||
|
||||
Returns:
|
||||
str: The description of this entity. By default this includes
|
||||
the entity's name, description and any contents inside it.
|
||||
|
||||
Notes:
|
||||
To simply change the layout of how the object displays itself (like
|
||||
adding some line decorations or change colors of different sections),
|
||||
you can simply edit `.appearance_template`. You only need to override
|
||||
this method (and/or its helpers) if you want to change what is passed
|
||||
into the template or want the most control over output.
|
||||
|
||||
"""
|
||||
|
||||
if not looker:
|
||||
return ""
|
||||
|
||||
# ourselves
|
||||
name = self.get_display_name(looker, **kwargs)
|
||||
desc = self.db.desc or "You see nothing special."
|
||||
|
||||
# contents
|
||||
content_names_map = self.get_content_names(looker, **kwargs)
|
||||
exits = list_to_string(content_names_map["exits"])
|
||||
characters = list_to_string(content_names_map["characters"])
|
||||
things = list_to_string(content_names_map["things"])
|
||||
|
||||
# populate the appearance_template string. It's a good idea to strip it and
|
||||
# let the client add any extra spaces instead.
|
||||
return self.appearance_template.format(
|
||||
header="",
|
||||
name=name,
|
||||
desc=desc,
|
||||
exits=f"|wExits:|n {exits}" if exits else "",
|
||||
characters=f"\n|wCharacters:|n {characters}" if characters else "",
|
||||
things=f"\n|wYou see:|n {things}" if things else "",
|
||||
footer="",
|
||||
).strip()
|
||||
|
||||
def at_look(self, target, **kwargs):
|
||||
"""
|
||||
Called when this object performs a look. It allows to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue