def create_object(typeclass=None, key=None, location=None, home=None, permissions=None, locks=None, aliases=None, destination=None, report_to=None, nohome=False): """ Create a new in-game object. Any game object is a combination of a database object that stores data persistently to the database, and a typeclass, which on-the-fly 'decorates' the database object into whataver different type of object it is supposed to be in the game. See src.objects.managers for methods to manipulate existing objects in the database. src.objects.objects holds the base typeclasses and src.objects.models hold the database model. report_to is an optional object for reporting errors to in string form. If report_to is not set, errors will be raised as en Exception containing the error message. If set, this method will return None upon errors. nohome - this allows the creation of objects without a default home location; this only used when creating the default location itself or during unittests """ global _Object, _ObjectDB if not _Object: from src.objects.objects import Object as _Object if not _ObjectDB: from src.objects.models import ObjectDB as _ObjectDB # input validation if not typeclass: typeclass = settings.BASE_OBJECT_TYPECLASS elif isinstance(typeclass, _ObjectDB): # this is already an objectdb instance, extract its typeclass typeclass = typeclass.typeclass.path elif isinstance(typeclass, _Object) or utils.inherits_from( typeclass, _Object): # this is already an object typeclass, extract its path typeclass = typeclass.path typeclass = utils.to_unicode(typeclass) # Setup input for the create command location = handle_dbref(location, _ObjectDB) destination = handle_dbref(destination, _ObjectDB) home = handle_dbref(home, _ObjectDB) if not home: try: home = handle_dbref(settings.DEFAULT_HOME, _ObjectDB) if not nohome else None except _ObjectDB.DoesNotExist: raise _ObjectDB.DoesNotExist( "settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed." % settings.DEFAULT_HOME) # create new database object all in one go new_db_object = _ObjectDB(db_key=key, db_location=location, db_destination=destination, db_home=home, db_typeclass_path=typeclass) if not key: # the object should always have a key, so if not set we give a default new_db_object.key = "#%i" % new_db_object.dbid # this will either load the typeclass or the default one (will also save object) new_object = new_db_object.typeclass if not _GA(new_object, "is_typeclass")(typeclass, exact=True): # this will fail if we gave a typeclass as input and it still # gave us a default try: SharedMemoryModel.delete(new_db_object) except AssertionError: # this happens if object was never created pass if report_to: report_to = handle_dbref(report_to, _ObjectDB) _GA(report_to, "msg")("Error creating %s (%s).\n%s" % (new_db_object.key, typeclass, _GA(new_db_object, "typeclass_last_errmsg"))) return None else: raise Exception(_GA(new_db_object, "typeclass_last_errmsg")) # from now on we can use the typeclass object # as if it was the database object. # call the hook methods. This is where all at_creation # customization happens as the typeclass stores custom # things on its database object. # note - this may override input keys, locations etc! new_object.basetype_setup() # setup the basics of Exits, Characters etc. new_object.at_object_creation() # we want the input to override that set in the hooks, so # we re-apply those if needed if new_object.key != key: new_object.key = key if new_object.location != location: new_object.location = location if new_object.home != home: new_object.home = home if new_object.destination != destination: new_object.destination = destination # custom-given perms/locks do overwrite hooks if permissions: new_object.permissions.add(permissions) if locks: new_object.locks.add(locks) if aliases: new_object.aliases.add(aliases) # trigger relevant move_to hooks in order to display messages. if location: new_object.at_object_receive(new_object, None) new_object.at_after_move(new_object) # post-hook setup (mainly used by Exits) new_object.basetype_posthook_setup() return new_object
def create_object(typeclass=None, key=None, location=None, home=None, permissions=None, locks=None, aliases=None, destination=None, report_to=None, nohome=False): """ Create a new in-game object. Any game object is a combination of a database object that stores data persistently to the database, and a typeclass, which on-the-fly 'decorates' the database object into whataver different type of object it is supposed to be in the game. See src.objects.managers for methods to manipulate existing objects in the database. src.objects.objects holds the base typeclasses and src.objects.models hold the database model. report_to is an optional object for reporting errors to in string form. If report_to is not set, errors will be raised as en Exception containing the error message. If set, this method will return None upon errors. nohome - this allows the creation of objects without a default home location; this only used when creating default location itself or during unittests """ global _Object, _ObjectDB if not _Object: from src.objects.objects import Object as _Object if not _ObjectDB: from src.objects.models import ObjectDB as _ObjectDB # input validation if not typeclass: typeclass = settings.BASE_OBJECT_TYPECLASS elif isinstance(typeclass, _ObjectDB): # this is already an objectdb instance, extract its typeclass typeclass = typeclass.typeclass.path elif isinstance(typeclass, _Object) or utils.inherits_from( typeclass, _Object): # this is already an object typeclass, extract its path typeclass = typeclass.path # handle eventual #dbref input location = handle_dbref(location, _ObjectDB) home = handle_dbref(home, _ObjectDB) destination = handle_dbref(destination, _ObjectDB) report_to = handle_dbref(report_to, _ObjectDB) # create new database object new_db_object = _ObjectDB() # assign the typeclass typeclass = utils.to_unicode(typeclass) new_db_object.typeclass_path = typeclass # the name/key is often set later in the typeclass. This # is set here as a failsafe. if key: new_db_object.key = key else: new_db_object.key = "#%i" % new_db_object.dbid # this will either load the typeclass or the default one new_object = new_db_object.typeclass if not _GA(new_object, "is_typeclass")(typeclass, exact=True): # this will fail if we gave a typeclass as input and it still # gave us a default SharedMemoryModel.delete(new_db_object) if report_to: _GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_object.key, typeclass, _GA(new_db_object, "typeclass_last_errmsg"))) return None else: raise Exception(_GA(new_db_object, "typeclass_last_errmsg")) # from now on we can use the typeclass object # as if it was the database object. new_object.destination = destination # call the hook method. This is where all at_creation # customization happens as the typeclass stores custom # things on its database object. new_object.basetype_setup() # setup the basics of Exits, Characters etc. new_object.at_object_creation() # custom-given perms/locks overwrite hooks if permissions: new_object.permissions.add(permissions) if locks: new_object.locks.add(locks) if aliases: new_object.aliases.add(aliases) if home: new_object.home = home else: # we shouldn't need to handle dbref here (home handler should fix it), but some have # reported issues here (issue 446). try: new_object.home = handle_dbref(settings.DEFAULT_HOME, _ObjectDB) if not nohome else None except _ObjectDB.DoesNotExist: raise _ObjectDB.DoesNotExist( "settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed." % settings.DEFAULT_HOME) # perform a move_to in order to display eventual messages. if location: new_object.move_to(location, quiet=True) else: # rooms would have location=None. new_object.location = None # post-hook setup (mainly used by Exits) new_object.basetype_posthook_setup() new_object.save() return new_object