From 0d0146207702c6ab80db1bccdfb53f4b91b9946e Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 24 Mar 2012 23:02:45 +0100 Subject: [PATCH] Adding a new API system to Evennia. This centralizes all access of the evennia driver through a single module "ev". Importing ev one should be able to access (and also importantly, easily explore) Evennia's API much easier. This API goes a long way to "flatten" the structure so that one doesn't need to remember how to find some method in a deeply nested subdirectory. As part of this work, I have also written full listings of all available properties on Typeclassed objects (including those inherited in various ways). Should hopefully make things easier to find. One can of course still import things directly from src/ as before. But this is a first step towards removing the "base" objects in game/gamesrc and instead making those accessible through the core API. --- ev.py | 96 +++++++++++++++++ game/gamesrc/objects/baseobjects.py | 66 +++++++++--- game/manage.py | 7 +- src/commands/default/__init__.py | 19 ++++ src/commands/default/admin.py | 5 + src/commands/default/batchprocess.py | 3 + src/commands/default/building.py | 10 ++ src/commands/default/cmdset_unloggedin.py | 6 +- src/commands/default/comms.py | 7 ++ src/commands/default/general.py | 6 ++ src/commands/default/help.py | 4 + src/commands/default/muxcommand.py | 3 + src/commands/default/system.py | 4 + src/commands/default/unloggedin.py | 9 +- src/comms/__init__.py | 12 +++ src/help/__init__.py | 11 ++ src/objects/__init__.py | 12 +++ src/objects/objects.py | 125 +++++++++++++++++----- src/players/__init__.py | 12 +++ src/players/player.py | 84 +++++++++++---- src/scripts/__init__.py | 12 +++ src/scripts/scripts.py | 85 +++++++++++---- src/server/__init__.py | 11 ++ src/typeclasses/typeclass.py | 3 + 24 files changed, 519 insertions(+), 93 deletions(-) create mode 100644 ev.py diff --git a/ev.py b/ev.py new file mode 100644 index 0000000000..b50e78f5c5 --- /dev/null +++ b/ev.py @@ -0,0 +1,96 @@ +""" + +Central API for Evennia MUD/MUX/MU* system. + +A simple way to explore Evennia's capabilities is to +import it in a python interpreter where all environment +variables have been set. Easiest is to do the following: + +game/manage.py shell +>>> import ev + +Using ipython is recommended since you will then have tab-completion +and the ability to view docstrings much easier than with the regular +python interpreter. + +In code, just import via ev. + +Philosophy is to keep the API as flat as possible, so as to not have +to remember which nested packages to traverse. Most of the important +stuff should be made visible from this module. + +One can of course still import from src/ directly should one prefer! + +""" + +# Stop erroneous direct run (would give a traceback since django is +# not yet initialized) + +if __name__ == "__main__": + print \ +""" + This module gives access to Evennia's programming API. + It should not be run on its own, but be imported and accessed as you develop your game. + To start the server, see game/manage.py and game/evennia.py. + More help can be found at http://www.evennia.com. +""" + import sys + sys.exit() + + +# Start Evennia API (easiest is to import this module interactively to explore it) + +# help entries +from src.help.models import HelpEntry +db_helpentries = HelpEntry.objects + +# players +from src.players.player import Player +from src.players.models import PlayerDB, PlayerAttribute, PlayerNick +db_players = PlayerDB.objects +db_playerattrs = PlayerAttribute.objects +db_playernicks = PlayerNick.objects +del PlayerDB, PlayerAttribute, PlayerNick + +# commands +from src.commands.command import Command +from src.commands.cmdset import CmdSet +from src.commands import default as default_cmds + +# locks +from src.locks import lockfuncs + +# scripts +from src.scripts.scripts import Script +from src.scripts.models import ScriptDB, ScriptAttribute +db_scripts = ScriptDB.objects +db_scriptattrs = ScriptAttribute.objects +del ScriptDB, ScriptAttribute + +# comms +from src.comms.models import Msg, Channel, PlayerChannelConnection, ExternalChannelConnection +db_msgs = Msg.objects +db_channels = Channel.objects +db_connections = PlayerChannelConnection.objects +db_externalconnections = ExternalChannelConnection.objects + +# objects +from src.objects.objects import Object, Character, Room, Exit +from src.objects.models import ObjAttribute, Alias, ObjectNick, ObjectDB +db_objects = ObjectDB.objects +db_aliases = Alias.objects +db_objnicks = ObjectNick.objects +db_objattrs = ObjAttribute.objects +del ObjAttribute, Alias, ObjectNick, ObjectDB + +# server +from src.server.models import ServerConfig +db_serverconfs = ServerConfig.objects +del ServerConfig + +# utils +from src.utils import search +from src.utils import logger +from src.utils import create +from src.utils import utils + diff --git a/game/gamesrc/objects/baseobjects.py b/game/gamesrc/objects/baseobjects.py index 5c2e6d5ccf..d9a2046cab 100644 --- a/game/gamesrc/objects/baseobjects.py +++ b/game/gamesrc/objects/baseobjects.py @@ -181,20 +181,60 @@ class Player(BasePlayer): Can be set using BASE_PLAYER_TYPECLASS. - The following hooks are called by the engine. Note that all of the following - are called on the character object too, and mostly at the same time. - at_player_creation() - This is called once, the very first time - the player is created (i.e. first time they - register with the game). It's a good place - to store attributes all players should have, - like configuration values etc. - at_pre_login() - called every time the user connects, after they have - identified, just before the system actually logs them in. - at_post_login() - called at the end of login, just before setting the - player loose in the world. - at_disconnect() - called just before the use is disconnected (this is also - called if the system determines the player lost their link) + * 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/manage.py b/game/manage.py index 122d4b7cc0..f93f9a7305 100755 --- a/game/manage.py +++ b/game/manage.py @@ -113,7 +113,10 @@ try: except Exception: import traceback string = "\n" + traceback.format_exc() - string += _("""\n + + # note - if this fails, ugettext will also fail, so we cannot translate this string. + + string += """\n Error: Couldn't import the file 'settings.py' in the directory containing %(file)r. There are usually two reasons for this: 1) You moved your settings.py elsewhere. In that case move it back or @@ -124,7 +127,7 @@ except Exception: set up django wrong in some way. If you run a virtual machine, it might be worth to restart it to see if this resolves the issue. Evennia should not require you to define any environment variables manually. - """) % {'file': __file__} + """ % {'file': __file__} print string sys.exit(1) diff --git a/src/commands/default/__init__.py b/src/commands/default/__init__.py index e69de29bb2..a9e174ce13 100644 --- a/src/commands/default/__init__.py +++ b/src/commands/default/__init__.py @@ -0,0 +1,19 @@ +""" +Central package for importing the default commands from the API. + +""" +from src.commands.default.cmdset_default import DefaultCmdSet +from src.commands.default.cmdset_ooc import OOCCmdSet +from src.commands.default.cmdset_unloggedin import UnloggedinCmdSet + +from src.commands.default.muxcommand import MuxCommand + +from src.commands.default.admin import * +from src.commands.default.batchprocess import * +from src.commands.default.building import * +from src.commands.default.comms import * +from src.commands.default.general import * +from src.commands.default.help import * +from src.commands.default import syscommands +from src.commands.default.system import * +from src.commands.default.unloggedin import * diff --git a/src/commands/default/admin.py b/src/commands/default/admin.py index 907246c079..72630d75cd 100644 --- a/src/commands/default/admin.py +++ b/src/commands/default/admin.py @@ -15,6 +15,11 @@ from src.commands.default.muxcommand import MuxCommand PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY] +# limit members for API inclusion +__all__ = ("CmdBoot", "CmdBan", "CmdUnban", "CmdDelPlayer", "CmdEmit", "CmdNewPassword", + "CmdPerm", "CmdWall") + + class CmdBoot(MuxCommand): """ @boot diff --git a/src/commands/default/batchprocess.py b/src/commands/default/batchprocess.py index 7966f2313d..5aa6eddfb2 100644 --- a/src/commands/default/batchprocess.py +++ b/src/commands/default/batchprocess.py @@ -28,6 +28,9 @@ from src.commands.cmdset import CmdSet from src.commands.default.muxcommand import MuxCommand from src.utils import utils +# limit symbols for API inclusion +__all__ = ("CmdBatchCommands", "CmdBatchCode") + HEADER_WIDTH = 70 UTF8_ERROR = \ """ diff --git a/src/commands/default/building.py b/src/commands/default/building.py index 679a2b218e..bb254dbf6a 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -11,6 +11,16 @@ from src.utils import create, utils, debug from src.commands.default.muxcommand import MuxCommand from src.commands.cmdhandler import get_and_merge_cmdsets +# limit symbol import for API +__all__ = ("ObjManipCommand", "CmdSetObjAlias", "CmdCopy", + "CmdCpAttr", "CmdMvAttr", "CmdCreate", "CmdDebug", + "CmdDesc", "CmdDestroy", "CmdDig", "CmdTunnel", "CmdLink", + "CmdUnLink", "CmdHome", "CmdListCmdSets", "CmdName", + "CmdOpen", "CmdSetAttribute", "CmdTypeclass", "CmdWipe", + "CmdLock", "CmdExamine", "CmdFind", "CmdTeleport", + "CmdScript") + + # used by @find CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS diff --git a/src/commands/default/cmdset_unloggedin.py b/src/commands/default/cmdset_unloggedin.py index 1e189ed460..f62946d0d7 100644 --- a/src/commands/default/cmdset_unloggedin.py +++ b/src/commands/default/cmdset_unloggedin.py @@ -15,8 +15,8 @@ class UnloggedinCmdSet(CmdSet): def at_cmdset_creation(self): "Populate the cmdset" - self.add(unloggedin.CmdConnect()) - self.add(unloggedin.CmdCreate()) - self.add(unloggedin.CmdQuit()) + self.add(unloggedin.CmdUnconnectedConnect()) + self.add(unloggedin.CmdUnconnectedCreate()) + self.add(unloggedin.CmdUnconnectedQuit()) self.add(unloggedin.CmdUnconnectedLook()) self.add(unloggedin.CmdUnconnectedHelp()) diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index 32e6bb437e..adc20a406a 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -14,6 +14,13 @@ from src.comms.channelhandler import CHANNELHANDLER from src.utils import create, utils from src.commands.default.muxcommand import MuxCommand +# limit symbol import for API +__all__ = ("CommCommand", "CmdAddCom", "CmdDelCom", "CmdAllCom", + "CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit", + "CmdCWho", "CmdChannelCreate", "CmdCset", "CmdCdesc", + "CmdPage", "CmdIRC2Chan", "CmdIMC2Chan", "CmdIMCInfo", + "CmdIMCTell", "CmdRSS2Chan") + def find_channel(caller, channelname, silent=False, noaliases=False): """ Helper function for searching for a single channel with diff --git a/src/commands/default/general.py b/src/commands/default/general.py index 0483aa1802..01d9877b1e 100644 --- a/src/commands/default/general.py +++ b/src/commands/default/general.py @@ -9,6 +9,12 @@ from src.utils import utils from src.objects.models import ObjectNick as Nick from src.commands.default.muxcommand import MuxCommand +# limit symbol import for API +__all__ = ("CmdHome", "CmdLook", "CmdPassword", "CmdNick", + "CmdInventory", "CmdGet", "CmdDrop", "CmdQuit", "CmdWho", + "CmdSay", "CmdPose", "CmdEncoding", "CmdAccess", + "CmdOOCLook", "CmdIC", "CmdOOC") + AT_SEARCH_RESULT = utils.mod_import(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) BASE_PLAYER_TYPECLASS = settings.BASE_PLAYER_TYPECLASS diff --git a/src/commands/default/help.py b/src/commands/default/help.py index 91ce86f163..6fabddae7e 100644 --- a/src/commands/default/help.py +++ b/src/commands/default/help.py @@ -12,6 +12,10 @@ from src.help.models import HelpEntry from src.utils import create from src.commands.default.muxcommand import MuxCommand +# limit symbol import for API +__all__ = ("CmdHelp", "CmdSetHelp") + + LIST_ARGS = ("list", "all") SEP = "{C" + "-"*78 + "{n" diff --git a/src/commands/default/muxcommand.py b/src/commands/default/muxcommand.py index d1787eb1f9..5753b4bf3c 100644 --- a/src/commands/default/muxcommand.py +++ b/src/commands/default/muxcommand.py @@ -5,6 +5,9 @@ The command template for the default MUX-style command set from src.utils import utils from src.commands.command import Command +# limit symbol import for API +__all__ = ("MuxCommand",) + class MuxCommand(Command): """ This sets up the basis for a MUX command. The idea diff --git a/src/commands/default/system.py b/src/commands/default/system.py index 396950c6c6..4fa43b4282 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -18,6 +18,10 @@ from src.server.models import ServerConfig from src.utils import create, logger, utils, gametime from src.commands.default.muxcommand import MuxCommand +# limit symbol import for API +__all__ = ("CmdReload", "CmdReset", "CmdShutdown", "CmdPy", + "CmdScripts", "CmdObjects", "CmdService", "CmdVersion", + "CmdTime", "CmdServerLoad", "CmdPs") class CmdReload(MuxCommand): """ diff --git a/src/commands/default/unloggedin.py b/src/commands/default/unloggedin.py index 32444f5f3f..694d09f578 100644 --- a/src/commands/default/unloggedin.py +++ b/src/commands/default/unloggedin.py @@ -15,9 +15,12 @@ from src.utils import create, logger, utils, ansi from src.commands.default.muxcommand import MuxCommand from src.commands.cmdhandler import CMD_LOGINSTART +# limit symbol import for API +__all__ = ("CmdUnconnectedConnect", "CmdUnconnectedCreate", "CmdUnconnectedQuit", "CmdUnconnectedLook", "CmdUnconnectedHelp") + CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE -class CmdConnect(MuxCommand): +class CmdUnconnectedConnect(MuxCommand): """ Connect to the game. @@ -86,7 +89,7 @@ class CmdConnect(MuxCommand): player.execute_cmd("look") -class CmdCreate(MuxCommand): +class CmdUnconnectedCreate(MuxCommand): """ Create a new account. @@ -215,7 +218,7 @@ its and @/./+/-/_ only.") # this echoes the restrictions made by django's auth m session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc()) -class CmdQuit(MuxCommand): +class CmdUnconnectedQuit(MuxCommand): """ We maintain a different version of the quit command here for unconnected players for the sake of simplicity. The logged in diff --git a/src/comms/__init__.py b/src/comms/__init__.py index e69de29bb2..6338f63c97 100644 --- a/src/comms/__init__.py +++ b/src/comms/__init__.py @@ -0,0 +1,12 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.comms +Also, the initiated object manager is available as src.comms.msgmanager and src.comms.channelmanager. + +""" + +from src.comms.models import * + +msgmanager = Msg.objects +channelmanager = Channel.objects diff --git a/src/help/__init__.py b/src/help/__init__.py index e69de29bb2..95dd700232 100644 --- a/src/help/__init__.py +++ b/src/help/__init__.py @@ -0,0 +1,11 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.help +Also, the initiated object manager is available as src.help.manager. + +""" + +from src.help.models import * + +manager = HelpEntry.objects diff --git a/src/objects/__init__.py b/src/objects/__init__.py index e69de29bb2..87a96402ab 100644 --- a/src/objects/__init__.py +++ b/src/objects/__init__.py @@ -0,0 +1,12 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.objects +Also, the initiated object manager is available as src.objects.manager. + +""" + +from src.objects.objects import * +from src.objects.models import ObjectDB + +manager = ObjectDB.objects diff --git a/src/objects/objects.py b/src/objects/objects.py index 9bea5cc4ee..c9658d4da9 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -29,35 +29,104 @@ class Object(TypeClass): objects in the game. """ - ## available properties + def __init__(self, dbobj): + """ + 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). + + + Object Typeclass API: + + * Available properties (only available on initiated typeclass 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) + + * Hook methods + + 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 + + """ + super(Object, self).__init__(dbobj) - # 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 - # 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(). - ## methods inherited from the database object (overload them here) def search(self, ostring, diff --git a/src/players/__init__.py b/src/players/__init__.py index e69de29bb2..fb882aa549 100644 --- a/src/players/__init__.py +++ b/src/players/__init__.py @@ -0,0 +1,12 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.player +Also, the initiated object manager is available as src.players.manager. + +""" + +from src.players.player import * +from src.players.models import PlayerDB + +manager = PlayerDB.objects diff --git a/src/players/player.py b/src/players/player.py index 7d0a17937b..3a5c0e0aa4 100644 --- a/src/players/player.py +++ b/src/players/player.py @@ -18,33 +18,73 @@ class Player(TypeClass): """ Base typeclass for all Players. """ + def __init__(self, dbobj): + """ + This is the base Typeclass for all Players. Players represent + the person playing the game and tracks account info, password + etc. They are OOC entities without presence in-game. A Player + can connect to a Character Object in order to "enter" the + game. - ## available properties + Player Typeclass API: - # 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 + * Available properties (only available on initiated typeclass objects) - # 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 + 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(). - ## Handlers + * 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 + + 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() + + """ + super(Player, self).__init__(dbobj) - # 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(). - - ## methods inherited from database model def msg(self, outgoing_string, from_obj=None, data=None): diff --git a/src/scripts/__init__.py b/src/scripts/__init__.py index e69de29bb2..5f15860a10 100644 --- a/src/scripts/__init__.py +++ b/src/scripts/__init__.py @@ -0,0 +1,12 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.scripts +Also, the initiated object manager is available as src.scripts.manager. + +""" + +from src.scripts.scripts import * +from src.scripts.models import ScriptDB + +manager = ScriptDB.objects diff --git a/src/scripts/scripts.py b/src/scripts/scripts.py index b3c8d4db46..bcb137c588 100644 --- a/src/scripts/scripts.py +++ b/src/scripts/scripts.py @@ -20,9 +20,8 @@ from src.utils import logger # class ScriptClass(TypeClass): """ - Base class for scripts + Base class for scripts. Don't inherit from this, inherit from Script instead. """ - # private methods def __eq__(self, other): @@ -253,31 +252,73 @@ class Script(ScriptClass): the hooks called by the script machinery. """ - ## available properties + def __init__(self, dbobj): + """ + This is the base TypeClass for all Scripts. Scripts describe events, timers and states in game, + they can have a time component or describe a state that changes under certain conditions. - # 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 + Script API: - # 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 + * Available properties (only available on initiated Typeclass objects) - ## Handlers + 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 - # 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 + 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 + + 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. + + + """ + super(Script, self).__init__(dbobj) def at_script_creation(self): """ diff --git a/src/server/__init__.py b/src/server/__init__.py index e69de29bb2..1e2c610945 100644 --- a/src/server/__init__.py +++ b/src/server/__init__.py @@ -0,0 +1,11 @@ +""" +Makes it easier to import by grouping all relevant things already at this level. + +You can henceforth import most things directly from src.server +Also, the initiated object manager is available as src.server.manager. + +""" + +from src.server.models import * + +manager = ServerConfig.objects diff --git a/src/typeclasses/typeclass.py b/src/typeclasses/typeclass.py index 67acd8c6f2..edd0a94301 100644 --- a/src/typeclasses/typeclass.py +++ b/src/typeclasses/typeclass.py @@ -44,6 +44,9 @@ class MetaTypeClass(type): super(MetaTypeClass, mcs).__init__(*args, **kwargs) mcs.typename = mcs.__name__ mcs.path = "%s.%s" % (mcs.__module__, mcs.__name__) + + + def __str__(cls): return "%s" % cls.__name__