diff --git a/ev.py b/ev.py index 2b78afb725..34006b9bc2 100644 --- a/ev.py +++ b/ev.py @@ -6,7 +6,7 @@ This basically a set of shortcuts to the main modules in src/. Import this from ./manage.py shell or set DJANGO_SETTINGS_MODULE manually for proper functionality. - 1) You should import things excplicitly from the root of this module - you can generally + 1) You should import things explicitly from the root of this module - you can generally not use dot-notation to import deeper. Hence, to access a default command, you can do the following: diff --git a/game/gamesrc/commands/examples/cmdset.py b/game/gamesrc/commands/examples/cmdset.py new file mode 100644 index 0000000000..0ffb2b9d85 --- /dev/null +++ b/game/gamesrc/commands/examples/cmdset.py @@ -0,0 +1,116 @@ +""" +Example command set template module. + +To create new commands to populate the cmdset, see +examples/command.py. + +To extend the default command set: + - copy this file up one level to gamesrc/commands and name it + something fitting. + - change settings.CMDSET_DEFAULT to point to the new module's + DefaultCmdSet + - import/add commands at the end of DefaultCmdSet's add() method. + +To add a new command set + - copy this file up one level to gamesrc/commands and name it + something fitting. + - add a new cmdset class + - add it objects with obj.cmdset.add(path.to.the.module.and.class) + +""" + +from ev import CmdSet, Command +from ev import default_cmds + +#from contrib import menusystem, lineeditor +#from contrib import misc_commands +#from contrib import chargen + +class ExampleCmdSet(CmdSet): + """ + Implements an empty, example cmdset. + """ + + key = "ExampleSet" + + def at_cmdset_creation(self): + """ + This is the only method defined in a cmdset, called during + its creation. It should populate the set with command instances. + + Here we just add the empty base Command object. It prints some info. + """ + self.add(Command()) + + +class DefaultCmdSet(default_cmds.DefaultCmdSet): + """ + This is an example of how to overload the default command + set defined in src/commands/default/cmdset_default.py. + + Here we copy everything by calling the parent, but you can + copy&paste any combination of the default command to customize + your default set. Next you change settings.CMDSET_DEFAULT to point + to this class. + """ + key = "DefaultMUX" + + def at_cmdset_creation(self): + """ + Populates the cmdset + """ + # calling setup in src.commands.default.cmdset_default + super(DefaultCmdSet, self).at_cmdset_creation() + + # + # any commands you add below will overload the default ones. + # + #self.add(menusystem.CmdMenuTest()) + #self.add(lineeditor.CmdEditor()) + #self.add(misc_commands.CmdQuell()) + +class UnloggedinCmdSet(default_cmds.UnloggedinCmdSet): + """ + This is an example of how to overload the command set of the + unloggedin commands, defined in + src/commands/default/cmdset_unloggedin.py. + + Here we copy everything by calling the parent, but you can + copy&paste any combination of the default command to customize + your default set. Next you change settings.CMDSET_UNLOGGEDIN to + point to this class. + """ + key = "Unloggedin" + + def at_cmdset_creation(self): + """ + Populates the cmdset + """ + # calling setup in src.commands.default.cmdset_unloggedin + super(UnloggedinCmdSet, self).at_cmdset_creation() + + # + # any commands you add below will overload the default ones. + # + +class OOCCmdSet(default_cmds.OOCCmdSet): + """ + This is set is available to the player when they have no + character connected to them (i.e. they are out-of-character, ooc). + """ + key = "OOC" + + def at_cmdset_creation(self): + """ + Populates the cmdset + """ + # calling setup in src.commands.default.cmdset_ooc + super(OOCCmdSet, self).at_cmdset_creation() + # + # any commands you add below will overload the default ones. + # + + + + + diff --git a/game/gamesrc/commands/examples/command.py b/game/gamesrc/commands/examples/command.py new file mode 100644 index 0000000000..0130c70269 --- /dev/null +++ b/game/gamesrc/commands/examples/command.py @@ -0,0 +1,132 @@ +""" +Example command module template + +Copy this module up one level to gamesrc/commands/ and name it as +befits your use. You can then use it as a template to define your new +commands. To use them you also need to group them in a CommandSet (see +examples/cmdset.py) + +""" + +from ev import Command as BaseCommand +from ev import default_cmd +from ev import utils + +class Command(BaseCommand): + """ + Inherit from this if you want to create your own + command styles. Note that Evennia's default commands + use MuxCommand instead (next in this module) + + Note that the class's __doc__ string (this text) is + used by Evennia to create the automatic help entry for + the command, so make sure to document consistently here. + + """ + # these need to be specified + + key = "MyCommand" + aliases = ["mycmd", "myc"] + locks = "cmd:all()" + help_category = "General" + + # auto_help = False # uncomment to deactive auto-help for this command. + # arg_regex = r"\s.*?|$" # optional regex detailing how the part after + # the cmdname must look to match this command. + + + # (we don't implement hook method access() here, you don't need to + # modify that unless you want to change how the lock system works + # (in that case see src.commands.command.Command)) + + def at_pre_cmd(self): + """ + This hook is called before self.parse() on all commands + """ + pass + + def parse(self): + """ + This method is called by the cmdhandler once the command name + has been identified. It creates a new set of member variables + that can be later accessed from self.func() (see below) + + The following variables are available to us: + # class variables: + + self.key - the name of this command ('mycommand') + self.aliases - the aliases of this cmd ('mycmd','myc') + self.locks - lock string for this command ("cmd:all()") + self.help_category - overall category of command ("General") + + # added at run-time by cmdhandler: + + self.caller - the object calling this command + self.cmdstring - the actual command name used to call this + (this allows you to know which alias was used, + for example) + self.args - the raw input; everything following self.cmdstring. + self.cmdset - the cmdset from which this command was picked. Not + often used (useful for commands like 'help' or to + list all available commands etc) + self.obj - the object on which this command was defined. It is often + the same as self.caller. + """ + pass + + def func(self): + """ + This is the hook function that actually does all the work. It is called + by the cmdhandler right after self.parser() finishes, and so has access + to all the variables defined therein. + """ + self.caller.msg("Command called!") + + def at_post_cmd(self): + """ + This hook is called after self.func(). + """ + pass + + +class MuxCommand(default_cmd.MuxCommand): + """ + This sets up the basis for a Evennia's 'MUX-like' command + style. The idea is that most other Mux-related commands should + just inherit from this and don't have to implement parsing of + their own unless they do something particularly advanced. + + A MUXCommand command understands the following possible syntax: + + name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]] + + The 'name[ with several words]' part is already dealt with by the + cmdhandler at this point, and stored in self.cmdname. The rest is stored + in self.args. + + The MuxCommand parser breaks self.args into its constituents and stores them in the + following variables: + self.switches = optional list of /switches (without the /) + self.raw = This is the raw argument input, including switches + self.args = This is re-defined to be everything *except* the switches + self.lhs = Everything to the left of = (lhs:'left-hand side'). If + no = is found, this is identical to self.args. + self.rhs: Everything to the right of = (rhs:'right-hand side'). + If no '=' is found, this is None. + self.lhslist - self.lhs split into a list by comma + self.rhslist - list of self.rhs split into a list by comma + self.arglist = list of space-separated args (including '=' if it exists) + + All args and list members are stripped of excess whitespace around the + strings, but case is preserved. + """ + + def func(self): + """ + This is the hook function that actually does all the work. It is called + by the cmdhandler right after self.parser() finishes, and so has access + to all the variables defined therein. + """ + # this can be removed in your child class, it's just + # printing the ingoing variables as a demo. + super(MuxCommand, self).func() diff --git a/game/gamesrc/objects/examples/character.py b/game/gamesrc/objects/examples/character.py new file mode 100644 index 0000000000..a6ba8b72df --- /dev/null +++ b/game/gamesrc/objects/examples/character.py @@ -0,0 +1,41 @@ +""" + +Template for Characters + +Copy this module up one level and name it as you like, then +use it as a template to create your own Character class. + +To make new logins default to creating characters +of your new type, change settings.BASE_CHARACTER_TYPECLASS to point to +your new class, e.g. + +settings.BASE_CHARACTER_TYPECLASS = "game.gamesrc.objects.mychar.MyChar" + +Note that objects already created in the database will not notice +this change, you have to convert them manually e.g. with the +@typeclass command. + +""" +from ev import Character + +class ExampleCharacter(Character): + """ + The Character is like any normal Object (see example/object.py for + a list of properties and methods), except it actually implements + some of its hook methods to do some work: + + at_basetype_setup - always assigns the default_cmdset to this object type + (important!)sets locks so character cannot be picked up + and its commands only be called by itself, not anyone else. + (to change things, use at_object_creation() instead) + at_after_move - launches the "look" command + at_disconnect - stores the current location, so the "unconnected" character + object does not need to stay on grid but can be given a + None-location while offline. + at_post_login - retrieves the character's old location and puts it back + on the grid with a "charname has connected" message echoed + to the room + + """ + pass + diff --git a/game/gamesrc/objects/examples/exit.py b/game/gamesrc/objects/examples/exit.py new file mode 100644 index 0000000000..0a9f996990 --- /dev/null +++ b/game/gamesrc/objects/examples/exit.py @@ -0,0 +1,43 @@ +""" + +Template module for Exits + +Copy this module up one level and name it as you like, then +use it as a template to create your own Exits. + +To make the default commands (such as @dig/@open) default to creating exits +of your new type, change settings.BASE_EXIT_TYPECLASS to point to +your new class, e.g. + +settings.BASE_EXIT_TYPECLASS = "game.gamesrc.objects.myexit.MyExit" + +Note that objects already created in the database will not notice +this change, you have to convert them manually e.g. with the +@typeclass command. + +""" +from ev import Exit + +class ExampleExit(Exit): + """ + Exits are connectors between rooms. Exits are normal Objects except + they defines the 'destination' property. It also does work in the + following methods: + + basetype_setup() - sets default exit locks (to change, use at_object_creation instead) + at_cmdset_get() - this auto-creates and caches a command and a command set on itself + with the same name as the Exit object. This + allows users to use the exit by only giving its + name alone on the command line. + at_failed_traverse() - gives a default error message ("You cannot + go there") if exit traversal fails and an + attribute err_traverse is not defined. + + Relevant hooks to overload (compared to other types of Objects): + at_before_traverse(traveller) - called just before traversing + at_after_traverse(traveller, source_loc) - called just after traversing + at_failed_traverse(traveller) - called if traversal failed for some reason. Will + not be called if the attribute 'err_traverse' is + defined, in which case that will simply be echoed. + """ + pass diff --git a/game/gamesrc/objects/examples/object.py b/game/gamesrc/objects/examples/object.py new file mode 100644 index 0000000000..95f58a294a --- /dev/null +++ b/game/gamesrc/objects/examples/object.py @@ -0,0 +1,123 @@ +""" + +Template for Objects + +Copy this module up one level and name it as you like, then +use it as a template to create your own Objects. + +To make the default commands default to creating objects of your new +type (and also change the "fallback" object used when typeclass +creation fails), change settings.BASE_OBJECT_TYPECLASS to point to +your new class, e.g. + +settings.BASE_OBJECT_TYPECLASS = "game.gamesrc.objects.myobj.MyObj" + +Note that objects already created in the database will not notice +this change, you have to convert them manually e.g. with the +@typeclass command. + +""" +from ev import Object + +class ExampleObject(Object): + """ + This is the root typeclass object, implementing an in-game Evennia + game object, such as having a location, being able to be + manipulated or looked at, etc. If you create a new typeclass, it + must always inherit from this object (or any of the other objects + in this file, since they all actually inherit from BaseObject, as + seen in src.object.objects). + + The BaseObject class implements several hooks tying into the game + engine. By re-implementing these hooks you can control the + system. You should never need to re-implement special Python + methods, such as __init__ and especially never __getattribute__ and + __setattr__ since these are used heavily by the typeclass system + of Evennia and messing with them might well break things for you. + + + * Base properties defined/available on all Objects + + key (string) - name of object + name (string)- same as key + aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings. + dbref (int, read-only) - unique #id-number. Also "id" can be used. + dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class + typeclass (Object, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch. + date_created (string) - time stamp of object creation + permissions (list of strings) - list of permission strings + + player (Player) - controlling player (will also return offline player) + location (Object) - current location. Is None if this is a room + home (Object) - safety start-location + sessions (list of Sessions, read-only) - returns all sessions connected to this object + has_player (bool, read-only)- will only return *connected* players + contents (list of Objects, read-only) - returns all objects inside this object (including exits) + exits (list of Objects, read-only) - returns all exits from this object, if any + destination (Object) - only set if this object is an exit. + is_superuser (bool, read-only) - True/False if this user is a superuser + + * Handlers available + + locks - lock-handler: use locks.add() to add new lock strings + db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr + ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data + scripts - script-handler. Add new scripts to object with scripts.add() + cmdset - cmdset-handler. Use cmdset.add() to add new cmdsets to object + nicks - nick-handler. New nicks with nicks.add(). + + * Helper methods (see src.objects.objects.py for full headers) + + search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) + execute_cmd(raw_string) + msg(message, from_obj=None, data=None) + msg_contents(message, exclude=None, from_obj=None, data=None) + move_to(destination, quiet=False, emit_to_obj=None, use_destination=True) + copy(new_key=None) + delete() + is_typeclass(typeclass, exact=False) + swap_typeclass(new_typeclass, clean_attributes=False, no_default=True) + access(accessing_obj, access_type='read', default=False) + check_permstring(permstring) + + * Hooks (these are class methods, so their arguments should also start with self): + + basetype_setup() - only called once, used for behind-the-scenes setup. Normally not modified. + basetype_posthook_setup() - customization in basetype, after the object has been created; Normally not modified. + + at_object_creation() - only called once, when object is first created. Object customizations 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_init() - called whenever typeclass is cached from memory, at least once every server restart/reload + at_cmdset_get() - this is called just before the command handler requests a cmdset from this object + at_first_login() - (player-controlled objects only) called once, the very first time user logs in. + at_pre_login() - (player-controlled objects only) called every time the user connects, after they have identified, before other setup + at_post_login() - (player-controlled objects only) called at the end of login, just before setting the player loose in the world. + at_disconnect() - (player-controlled objects only) called just before the user disconnects (or goes linkless) + at_server_reload() - called before server is reloaded + at_server_shutdown() - called just before server is fully shut down + + at_before_move(destination) - called just before moving object to the destination. If returns False, move is cancelled. + announce_move_from(destination) - called in old location, just before move, if obj.move_to() has quiet=False + announce_move_to(source_location) - called in new location, just after move, if obj.move_to() has quiet=False + at_after_move(source_location) - always called after a move has been successfully performed. + at_object_leave(obj, target_location) - called when an object leaves this object in any fashion + at_object_receive(obj, source_location) - called when this object receives another object + + at_before_traverse(traversing_object) - (exit-objects only) called just before an object traverses this object + at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened. + at_failed_traverse(traversing_object) - (exit-objects only) called if traversal fails and property err_traverse is not defined. + + at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj. + If returns false, aborts send. + at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg(). + + return_appearance(looker) - describes this object. Used by "look" command by default + at_desc(looker=None) - called by 'look' whenever the appearance is requested. + at_get(getter) - called after object has been picked up. Does not stop pickup. + at_drop(dropper) - called when this object has been dropped. + at_say(speaker, message) - by default, called if an object inside this object speaks + + """ + pass diff --git a/game/gamesrc/objects/examples/player.py b/game/gamesrc/objects/examples/player.py new file mode 100644 index 0000000000..e3de1e2d32 --- /dev/null +++ b/game/gamesrc/objects/examples/player.py @@ -0,0 +1,90 @@ +""" + +Template module for Players + +Copy this module up one level and name it as you like, then +use it as a template to create your own Player class. + +To make the default account login default to using a Player +of your new type, change settings.BASE_PLAYER_TYPECLASS to point to +your new class, e.g. + +settings.BASE_PLAYER_TYPECLASS = "game.gamesrc.objects.myplayer.MyPlayer" + +Note that objects already created in the database will not notice +this change, you have to convert them manually e.g. with the +@typeclass command. + +""" +from ev import Player + +class ExamplePlayer(Player): + """ + This class describes the actual OOC player (i.e. the user connecting + to the MUD). It does NOT have visual appearance in the game world (that + is handled by the character which is connected to this). Comm channels + are attended/joined using this object. + + It can be useful e.g. for storing configuration options for your game, but + should generally not hold any character-related info (that's best handled + on the character level). + + Can be set using BASE_PLAYER_TYPECLASS. + + + * available properties + + key (string) - name of player + name (string)- wrapper for user.username + aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings. + dbref (int, read-only) - unique #id-number. Also "id" can be used. + dbobj (Player, read-only) - link to database model. dbobj.typeclass points back to this class + typeclass (Player, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch. + date_created (string) - time stamp of object creation + permissions (list of strings) - list of permission strings + + user (User, read-only) - django User authorization object + obj (Object) - game object controlled by player. 'character' can also be used. + sessions (list of Sessions) - sessions connected to this player + is_superuser (bool, read-only) - if the connected user is a superuser + + * Handlers + + locks - lock-handler: use locks.add() to add new lock strings + db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr + ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data + scripts - script-handler. Add new scripts to object with scripts.add() + cmdset - cmdset-handler. Use cmdset.add() to add new cmdsets to object + nicks - nick-handler. New nicks with nicks.add(). + + * Helper methods + + msg(outgoing_string, from_obj=None, data=None) + swap_character(new_character, delete_old_character=False) + execute_cmd(raw_string) + search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) + is_typeclass(typeclass, exact=False) + swap_typeclass(new_typeclass, clean_attributes=False, no_default=True) + access(accessing_obj, access_type='read', default=False) + check_permstring(permstring) + + * Hook methods (when re-implementation, remember methods need to have self as first arg) + + basetype_setup() + at_player_creation() + + - note that the following hooks are also found on Objects and are + usually handled on the character level: + + at_init() + at_cmdset_get() + at_first_login() + at_post_login() + at_disconnect() + at_message_receive() + at_message_send() + at_server_reload() + at_server_shutdown() + + """ + pass diff --git a/game/gamesrc/objects/examples/room.py b/game/gamesrc/objects/examples/room.py new file mode 100644 index 0000000000..852be40ba3 --- /dev/null +++ b/game/gamesrc/objects/examples/room.py @@ -0,0 +1,32 @@ +""" + +Template module for Rooms + +Copy this module up one level and name it as you like, then +use it as a template to create your own Objects. + +To make the default commands (such as @dig) default to creating rooms +of your new type, change settings.BASE_ROOM_TYPECLASS to point to +your new class, e.g. + +settings.BASE_ROOM_TYPECLASS = "game.gamesrc.objects.myroom.MyRoom" + +Note that objects already created in the database will not notice +this change, you have to convert them manually e.g. with the +@typeclass command. + +""" + +from ev import Room + +class ExampleRoom(Room): + """ + Rooms are like any Object, except their location is None + (which is default). They also use basetype_setup() to + add locks so they cannot be puppeted or picked up. + (to change that, use at_object_creation instead) + + See examples/object.py for a list of + properties and methods available on all Objects. + """ + pass diff --git a/game/gamesrc/scripts/basescript.py b/game/gamesrc/scripts/basescript.py index 950dd95001..68058210df 100644 --- a/game/gamesrc/scripts/basescript.py +++ b/game/gamesrc/scripts/basescript.py @@ -1,5 +1,13 @@ """ -The base object to inherit from when implementing new Scripts. + +Template module for Scripts + +Copy this module up one level to gamesrc/scripts and name it +appropriately, then use that as a template to create your own script. + +Test scripts in-game e.g. with the @script command. In code you can +create new scripts of a given class with + script = ev.create.script("path.to.module.and.class") Scripts are objects that handle everything in the game having a time-component (i.e. that may change with time, with or without @@ -10,17 +18,13 @@ checking if its state changes, so as to update it. Evennia use several in-built scripts to keep track of things like time, to clean out dropped connections etc. -New Script objects (from these classes) are created using the -src.utils.create.create_script(scriptclass, ...) where scriptclass -is the python path to the specific class of script you want to use. """ from ev import Script as BaseScript class Script(BaseScript): """ - All scripts should inherit from this class and implement - some or all of its hook functions and variables. + A script type is customized by redefining some or all of its hook methods and variables. * available properties diff --git a/game/gamesrc/scripts/examples/script.py b/game/gamesrc/scripts/examples/script.py new file mode 100644 index 0000000000..99a3cd206a --- /dev/null +++ b/game/gamesrc/scripts/examples/script.py @@ -0,0 +1,87 @@ +""" + +Template module for Scripts + +Copy this module up one level to gamesrc/scripts and name it +appropriately, then use that as a template to create your own script. + +Test scripts in-game e.g. with the @script command. In code you can +create new scripts of a given class with + script = ev.create.script("path.to.module.and.class") + +Scripts are objects that handle everything in the game having +a time-component (i.e. that may change with time, with or without +a player being involved in the change). Scripts can work like "events", +in that they are triggered at regular intervals to do a certain script, +but an Script set on an object can also be responsible for silently +checking if its state changes, so as to update it. Evennia use several +in-built scripts to keep track of things like time, to clean out +dropped connections etc. + +""" + +from ev import Script + +class ExampleScript(BaseScript): + """ + A script type is customized by redefining some or all of its hook methods and variables. + + * available properties + + key (string) - name of object + name (string)- same as key + aliases (list of strings) - aliases to the object. Will be saved to database as AliasDB entries but returned as strings. + dbref (int, read-only) - unique #id-number. Also "id" can be used. + dbobj (Object, read-only) - link to database model. dbobj.typeclass points back to this class + typeclass (Object, read-only) - this links back to this class as an identified only. Use self.swap_typeclass() to switch. + date_created (string) - time stamp of object creation + permissions (list of strings) - list of permission strings + + desc (string) - optional description of script, shown in listings + obj (Object) - optional object that this script is connected to and acts on (set automatically by obj.scripts.add()) + interval (int) - how often script should run, in seconds. <0 turns off ticker + start_delay (bool) - if the script should start repeating right away or wait self.interval seconds + repeats (int) - how many times the script should repeat before stopping. 0 means infinite repeats + persistent (bool) - if script should survive a server shutdown or not + is_active (bool) - if script is currently running + + * Handlers + + locks - lock-handler: use locks.add() to add new lock strings + db - attribute-handler: store/retrieve database attributes on this self.db.myattr=val, val=self.db.myattr + ndb - non-persistent attribute handler: same as db but does not create a database entry when storing data + + * Helper methods + + start() - start script (this usually happens automatically at creation and obj.script.add() etc) + stop() - stop script, and delete it + pause() - put the script on hold, until unpause() is called. If script is persistent, the pause state will survive a shutdown. + unpause() - restart a previously paused script. The script will continue as if it was never paused. + time_until_next_repeat() - if a timed script (interval>0), returns time until next tick + + * Hook methods (should also include self as the first argument): + + at_script_creation() - called only once, when an object of this + class is first created. + is_valid() - is called to check if the script is valid to be running + at the current time. If is_valid() returns False, the running + script is stopped and removed from the game. You can use this + to check state changes (i.e. an script tracking some combat + stats at regular intervals is only valid to run while there is + actual combat going on). + at_start() - Called every time the script is started, which for persistent + scripts is at least once every server start. Note that this is + unaffected by self.delay_start, which only delays the first call + to at_repeat(). + at_repeat() - Called every self.interval seconds. It will be called immediately + upon launch unless self.delay_start is True, which will delay + the first call of this method by self.interval seconds. If + self.interval==0, this method will never be called. + at_stop() - Called as the script object is stopped and is about to be removed from + the game, e.g. because is_valid() returned False. + at_server_reload() - Called when server reloads. Can be used to save temporary + variables you want should survive a reload. + at_server_shutdown() - called at a full server shutdown. + + """ + pass diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 3dc0a8f390..ee806b665d 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -1066,6 +1066,7 @@ class TypedObject(SharedMemoryModel): to create a new object and just swap the player over to that one instead. + Arguments: new_typeclass (path/classobj) - type to switch to clean_attributes (bool/list) - will delete all attributes stored on this object (but not any @@ -1079,6 +1080,9 @@ class TypedObject(SharedMemoryModel): swapping to a default typeclass in case the given one fails for some reason. Instead the old one will be preserved. + Returns: + boolean True/False depending on if the swap worked or not. + """ if callable(new_typeclass): # this is an actual class object - build the path diff --git a/src/utils/create.py b/src/utils/create.py index 0476fc79f2..7e40f876a4 100644 --- a/src/utils/create.py +++ b/src/utils/create.py @@ -32,10 +32,13 @@ from src.utils.utils import is_iter, has_parent, inherits_from # limit symbol import from API __all__ = ("object", "script", "help_entry", "message", "channel", "player") +GA = object.__getattribute__ + # # Game Object creation # + def create_object(typeclass, key=None, location=None, home=None, player=None, permissions=None, locks=None, aliases=None, destination=None): @@ -81,7 +84,7 @@ def create_object(typeclass, key=None, location=None, new_object = new_db_object.typeclass - if not object.__getattribute__(new_db_object, "is_typeclass")(typeclass, exact=True): + if not GA(new_db_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) return None @@ -190,7 +193,7 @@ def create_script(typeclass, key=None, obj=None, locks=None, # this will either load the typeclass or the default one new_script = new_db_script.typeclass - if not object.__getattribute__(new_db_script, "is_typeclass")(typeclass, exact=True): + if not GA(new_db_script, "is_typeclass")(typeclass, exact=True): # this will fail if we gave a typeclass as input and it still gave us a default print "failure:", new_db_script, typeclass SharedMemoryModel.delete(new_db_script) @@ -462,7 +465,7 @@ def create_player(name, email, password, # this will either load the typeclass or the default one new_player = new_db_player.typeclass - if not object.__getattribute__(new_db_player, "is_typeclass")(typeclass, exact=True): + if not GA(new_db_player, "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_player) return None @@ -494,7 +497,6 @@ def create_player(name, email, password, return new_player except Exception,e: # a failure in creating the character - print e if not user: # in there was a failure we clean up everything we can logger.log_trace() @@ -510,6 +512,7 @@ def create_player(name, email, password, del new_character except Exception: pass + raise # alias player = create_player