diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 82e087bb4a..2906ecbed2 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -304,11 +304,14 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): at_object_creation() - only called once, when object is first created. Object customizations go here. + at_object_post_creation() - only called once, when object is first created. + Additional setup involving e.g. prototype-set attributes can go here. at_object_delete() - called just before deleting an object. If returning False, deletion is aborted. Note that all objects inside a deleted object are automatically moved to their , they don't need to be removed here. - + at_object_post_spawn() - called when object is spawned from a prototype or updated + by the spawner to apply prototype changes. at_init() - called whenever typeclass is cached from memory, at least once every server restart/reload at_first_save() @@ -1924,9 +1927,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): self.init_evennia_properties() if hasattr(self, "_createdict"): - # this will only be set if the utils.create function - # was used to create the object. We want the create - # call's kwargs to override the values set by hooks. + # this will be set if the object was created by the utils.create function + # or the spawner. We want these kwargs to override the values set by + # the initial hooks. cdict = self._createdict updates = [] if not cdict.get("key"): @@ -1969,6 +1972,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): self.nattributes.add(key, value) del self._createdict + + # run the post-setup hook + self.at_object_post_creation() self.basetype_posthook_setup() @@ -2027,6 +2033,15 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): """ pass + def at_object_post_creation(self): + """ + Called once, when this object is first created and after any attributes, tags, etc. + that were passed to the `create_object` function or defined in a prototype have been + applied. + + """ + pass + def at_object_delete(self): """ Called just before the database object is persistently @@ -2036,6 +2051,16 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): """ return True + def at_object_post_spawn(self, prototype=None): + """ + Called when this object is spawned or updated from a prototype, after all other + hooks have been run. + + Keyword Args: + prototype (dict): The prototype that was used to spawn or update this object. + """ + pass + def at_init(self): """ This is always called whenever this object is initiated -- diff --git a/evennia/prototypes/spawner.py b/evennia/prototypes/spawner.py index 3dfad73b31..5e8897b6dd 100644 --- a/evennia/prototypes/spawner.py +++ b/evennia/prototypes/spawner.py @@ -803,6 +803,8 @@ def batch_update_objects_with_prototype( if do_save: changed += 1 obj.save() + if spawn_hook := getattr(obj, "at_object_post_spawn", None): + spawn_hook(prototype=prototype) return changed @@ -869,6 +871,9 @@ def batch_create_object(*objparams): for code in objparam[7]: if code: exec(code, {}, {"evennia": evennia, "obj": obj}) + # run the spawned hook + if spawn_hook := getattr(obj, "at_object_post_spawn", None): + spawn_hook() objs.append(obj) return objs