Fixed the entire first_init script process with the new typeclass system.

This commit is contained in:
Griatch 2014-12-26 13:31:23 +01:00
parent 11449f3d62
commit b839614259
6 changed files with 114 additions and 121 deletions

View file

@ -45,9 +45,74 @@ class Channel(ChannelDB):
if cdict["desc"]: if cdict["desc"]:
self.attributes.add("desc", cdict["desc"]) self.attributes.add("desc", cdict["desc"])
def at_channel_creation(self):
"""
Called once, when the channel is first created.
"""
pass
# helper methods, for easy overloading # helper methods, for easy overloading
def has_connection(self, player):
"""
Checks so this player is actually listening
to this channel.
"""
if hasattr(player, "player"):
player = player.player
player = player.dbobj
return player in self.db_subscriptions.all()
def connect(self, player):
"Connect the user to this channel. This checks access."
if hasattr(player, "player"):
player = player.player
# check access
if not self.access(player, 'listen'):
return False
# pre-join hook
connect = self.pre_join_channel(player)
if not connect:
return False
# subscribe
self.db_subscriptions.add(player)
# post-join hook
self.post_join_channel(player)
return True
def disconnect(self, player):
"Disconnect user from this channel."
if hasattr(player, "player"):
player = player.player
# pre-disconnect hook
disconnect = self.pre_leave_channel(player)
if not disconnect:
return False
# disconnect
self.db_subscriptions.remove(player.dbobj)
# post-disconnect hook
self.post_leave_channel(player.dbobj)
return True
def access(self, accessing_obj, access_type='listen', default=False):
"""
Determines if another object has permission to access.
accessing_obj - object trying to access this one
access_type - type of access sought
default - what to return if no lock of access_type was found
"""
return self.locks.check(accessing_obj, access_type=access_type, default=default)
def delete(self):
"""
Deletes channel while also cleaning up channelhandler
"""
self.attributes.clear()
self.aliases.clear()
super(Channel, self).delete()
from src.comms.channelhandler import CHANNELHANDLER
CHANNELHANDLER.update()
def channel_prefix(self, msg=None, emit=False): def channel_prefix(self, msg=None, emit=False):
""" """
How the channel should prefix itself for users. Return a string. How the channel should prefix itself for users. Return a string.
@ -134,12 +199,6 @@ class Channel(ChannelDB):
msg.message = body msg.message = body
return msg return msg
def at_channel_create(self):
"""
Run at channel creation.
"""
pass
def pre_join_channel(self, joiner): def pre_join_channel(self, joiner):
""" """
Run right before a channel is joined. If this returns a false value, Run right before a channel is joined. If this returns a false value,

View file

@ -363,69 +363,5 @@ class ChannelDB(TypedObject):
verbose_name = "Channel" verbose_name = "Channel"
verbose_name_plural = "Channels" verbose_name_plural = "Channels"
#
# Channel class methods
#
def __str__(self): def __str__(self):
return "Channel '%s' (%s)" % (self.key, self.db.desc) return "Channel '%s' (%s)" % (self.key, self.db.desc)
def has_connection(self, player):
"""
Checks so this player is actually listening
to this channel.
"""
if hasattr(player, "player"):
player = player.player
player = player.dbobj
return player in self.db_subscriptions.all()
def connect(self, player):
"Connect the user to this channel. This checks access."
if hasattr(player, "player"):
player = player.player
# check access
if not self.access(player, 'listen'):
return False
# pre-join hook
connect = self.pre_join_channel(player)
if not connect:
return False
# subscribe
self.db_subscriptions.add(player.dbobj)
# post-join hook
self.post_join_channel(player)
return True
def disconnect(self, player):
"Disconnect user from this channel."
if hasattr(player, "player"):
player = player.player
# pre-disconnect hook
disconnect = self.pre_leave_channel(player)
if not disconnect:
return False
# disconnect
self.db_subscriptions.remove(player.dbobj)
# post-disconnect hook
self.post_leave_channel(player.dbobj)
return True
def access(self, accessing_obj, access_type='listen', default=False):
"""
Determines if another object has permission to access.
accessing_obj - object trying to access this one
access_type - type of access sought
default - what to return if no lock of access_type was found
"""
return self.locks.check(accessing_obj, access_type=access_type, default=default)
def delete(self):
"""
Deletes channel while also cleaning up channelhandler
"""
_GA(self, "attributes").clear()
_GA(self, "aliases").clear()
super(ChannelDB, self).delete()
from src.comms.channelhandler import CHANNELHANDLER
CHANNELHANDLER.update()

View file

@ -73,7 +73,7 @@ class ScriptDB(TypedObject):
# #
# ScriptDB Database Model setup # ScriptDB Database Model setup
# #
# These databse fields are all set using their corresponding properties, # These database fields are all set using their corresponding properties,
# named same as the field, but withtou the db_* prefix. # named same as the field, but withtou the db_* prefix.
# inherited fields (from TypedObject): # inherited fields (from TypedObject):
@ -100,10 +100,6 @@ class ScriptDB(TypedObject):
# Database manager # Database manager
objects = ScriptDBManager() objects = ScriptDBManager()
# caches for quick lookups
_typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
_default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing"
class Meta: class Meta:
"Define Django meta options" "Define Django meta options"
verbose_name = "Script" verbose_name = "Script"

View file

@ -135,7 +135,7 @@ class ScriptBase(ScriptDB):
if self.db._paused_time: if self.db._paused_time:
# the script was paused; restarting # the script was paused; restarting
callcount = self.db._paused_callcount or 0 callcount = self.db._paused_callcount or 0
self.ndb._task.start(self.dbobj.db_interval, self.ndb._task.start(self.db_interval,
now=False, now=False,
start_delay=self.db._paused_time, start_delay=self.db._paused_time,
count_start=callcount) count_start=callcount)
@ -143,8 +143,8 @@ class ScriptBase(ScriptDB):
del self.db._paused_repeats del self.db._paused_repeats
else: else:
# starting script anew # starting script anew
self.ndb._task.start(self.dbobj.db_interval, self.ndb._task.start(self.db_interval,
now=not self.dbobj.db_start_delay) now=not self.db_start_delay)
def _stop_task(self): def _stop_task(self):
"stop task runner" "stop task runner"
@ -159,7 +159,7 @@ class ScriptBase(ScriptDB):
{"key": self.key, "dbid": self.dbid, "cname": cname, {"key": self.key, "dbid": self.dbid, "cname": cname,
"err": e.getErrorMessage()} "err": e.getErrorMessage()}
try: try:
self.dbobj.db_obj.msg(estring) self.db_obj.msg(estring)
except Exception: except Exception:
pass pass
logger.log_errmsg(estring) logger.log_errmsg(estring)
@ -176,7 +176,7 @@ class ScriptBase(ScriptDB):
# check repeats # check repeats
callcount = self.ndb._task.callcount callcount = self.ndb._task.callcount
maxcount = self.dbobj.db_repeats maxcount = self.db_repeats
if maxcount > 0 and maxcount <= callcount: if maxcount > 0 and maxcount <= callcount:
#print "stopping script!" #print "stopping script!"
self.stop() self.stop()
@ -210,7 +210,7 @@ class ScriptBase(ScriptDB):
"Get the number of returning repeats. Returns None if unlimited repeats." "Get the number of returning repeats. Returns None if unlimited repeats."
task = self.ndb._task task = self.ndb._task
if task: if task:
return max(0, self.dbobj.db_repeats - task.callcount) return max(0, self.db_repeats - task.callcount)
def start(self, force_restart=False): def start(self, force_restart=False):
""" """
@ -224,10 +224,7 @@ class ScriptBase(ScriptDB):
Used in counting. Used in counting.
""" """
#print "Script %s (%s) start (active:%s, force:%s) ..." % (self.key, id(self.dbobj), if self.is_active and not force_restart:
# self.is_active, force_restart)
if self.dbobj.is_active and not force_restart:
# script already runs and should not be restarted. # script already runs and should not be restarted.
return 0 return 0
@ -235,11 +232,11 @@ class ScriptBase(ScriptDB):
if obj: if obj:
# check so the scripted object is valid and initalized # check so the scripted object is valid and initalized
try: try:
_GA(obj.dbobj, 'cmdset') obj.cmdset
except AttributeError: except AttributeError:
# this means the object is not initialized. # this means the object is not initialized.
logger.log_trace() logger.log_trace()
self.dbobj.is_active = False self.is_active = False
return 0 return 0
# try to restart a paused script # try to restart a paused script
@ -247,13 +244,13 @@ class ScriptBase(ScriptDB):
return 1 return 1
# start the script from scratch # start the script from scratch
self.dbobj.is_active = True self.is_active = True
try: try:
self.at_start() self.at_start()
except Exception: except Exception:
logger.log_trace() logger.log_trace()
if self.dbobj.db_interval > 0: if self.db_interval > 0:
self._start_task() self._start_task()
return 1 return 1
@ -274,7 +271,7 @@ class ScriptBase(ScriptDB):
logger.log_trace() logger.log_trace()
self._stop_task() self._stop_task()
try: try:
self.dbobj.delete() self.delete()
except AssertionError: except AssertionError:
logger.log_trace() logger.log_trace()
return 0 return 0
@ -292,7 +289,7 @@ class ScriptBase(ScriptDB):
self.db._paused_time = task.next_call_time() self.db._paused_time = task.next_call_time()
self.db._paused_callcount = task.callcount self.db._paused_callcount = task.callcount
self._stop_task() self._stop_task()
self.dbobj.is_active = False self.is_active = False
def unpause(self): def unpause(self):
""" """
@ -300,7 +297,7 @@ class ScriptBase(ScriptDB):
""" """
if self.db._paused_time: if self.db._paused_time:
# only unpause if previously paused # only unpause if previously paused
self.dbobj.is_active = True self.is_active = True
try: try:
self.at_start() self.at_start()
@ -364,10 +361,6 @@ class Script(ScriptBase):
aliases (list of strings) - aliases to the object. Will be saved to aliases (list of strings) - aliases to the object. Will be saved to
database as AliasDB entries but returned as strings. database as AliasDB entries but returned as strings.
dbref (int, read-only) - unique #id-number. Also "id" can be used. 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 date_created (string) - time stamp of object creation
permissions (list of strings) - list of permission strings permissions (list of strings) - list of permission strings
@ -441,7 +434,7 @@ class Script(ScriptBase):
Generally, you don't need to overload this, but only the hooks Generally, you don't need to overload this, but only the hooks
called by this method. called by this method.
""" """
self.at_script_creation(self) self.at_script_creation()
if hasattr(self, "_createdict"): if hasattr(self, "_createdict"):
# this will only be set if the utils.create_script # this will only be set if the utils.create_script
@ -470,14 +463,6 @@ class Script(ScriptBase):
updates.append("db_persistent") updates.append("db_persistent")
if updates: if updates:
self.save(update_fields=updates) self.save(update_fields=updates)
if cdict["permissions"]:
self.permissions.add(cdict["permissions"])
if cdict["locks"]:
self.locks.add(cdict["locks"])
if cdict["aliases"]:
self.aliases.add(cdict["aliases"])
if not cdict["autostart"]: if not cdict["autostart"]:
# don't auto-start the script # don't auto-start the script
return return

View file

@ -69,7 +69,8 @@ def create_objects():
# it to exist in Limbo. # it to exist in Limbo.
character_typeclass = settings.BASE_CHARACTER_TYPECLASS character_typeclass = settings.BASE_CHARACTER_TYPECLASS
god_character = create.create_object(character_typeclass, god_character = create.create_object(character_typeclass,
key=god_player.username, nohome=True) key=god_player.username,
nohome=True)
god_character.id = 1 god_character.id = 1
god_character.db.desc = _('This is User #1.') god_character.db.desc = _('This is User #1.')
@ -84,14 +85,13 @@ def create_objects():
room_typeclass = settings.BASE_ROOM_TYPECLASS room_typeclass = settings.BASE_ROOM_TYPECLASS
limbo_obj = create.create_object(room_typeclass, _('Limbo'), nohome=True) limbo_obj = create.create_object(room_typeclass, _('Limbo'), nohome=True)
limbo_obj.id = 2 limbo_obj.id = 2
string = " ".join([ string = \
"Welcome to your new {wEvennia{n-based game. From here you are ready", "Welcome to your new {wEvennia{n-based game. From here you are ready " \
"to begin development. Visit http://evennia.com if you should need", "to begin development. Visit http://evennia.com if you should need " \
"help or would like to participate in community discussions. If you", "help or would like to participate in community discussions. If you " \
"are logged in as User #1 you can create a demo/tutorial area with", "are logged in as user #1 you can create a demo/tutorial area with " \
"'@batchcommand contrib.tutorial_world.build'. Log out and create", "{w@batchcommand contrib.tutorial_world.build{n. Use {w@quell{n or login " \
"a new non-admin account at the login screen to play the tutorial", "as normal player to play the demo properly."
"properly."])
string = _(string) string = _(string)
limbo_obj.db.desc = string limbo_obj.db.desc = string
limbo_obj.save() limbo_obj.save()

View file

@ -23,8 +23,7 @@ Models covered:
""" """
from django.conf import settings from django.conf import settings
from django.db import IntegrityError from django.db import IntegrityError
from src.utils.idmapper.models import SharedMemoryModel from src.utils import logger
from src.utils import utils, logger
from src.utils.utils import make_iter, class_from_module, dbid_to_obj from src.utils.utils import make_iter, class_from_module, dbid_to_obj
# delayed imports # delayed imports
@ -71,6 +70,11 @@ def create_object(typeclass=None, key=None, location=None,
nohome - this allows the creation of objects without a default home location; nohome - this allows the creation of objects without a default home location;
only used when creating the default location itself or during unittests only used when creating the default location itself or during unittests
""" """
global _ObjectDB
if not _ObjectDB:
from src.objects.models import ObjectDB as _ObjectDB
typeclass = typeclass if typeclass else settings.BASE_OBJECT_TYPECLASS typeclass = typeclass if typeclass else settings.BASE_OBJECT_TYPECLASS
if isinstance(typeclass, basestring): if isinstance(typeclass, basestring):
@ -141,6 +145,10 @@ def create_script(typeclass, key=None, obj=None, player=None, locks=None,
error will be raised. If set, this method will error will be raised. If set, this method will
return None upon errors. return None upon errors.
""" """
global _ScriptDB
if not _ScriptDB:
from src.scripts.models import ScriptDB as _ScriptDB
typeclass = typeclass if typeclass else settings.BASE_SCRIPT_TYPECLASS typeclass = typeclass if typeclass else settings.BASE_SCRIPT_TYPECLASS
if isinstance(typeclass, basestring): if isinstance(typeclass, basestring):
@ -148,13 +156,18 @@ def create_script(typeclass, key=None, obj=None, player=None, locks=None,
typeclass = class_from_module(typeclass, settings.SCRIPT_TYPECLASS_PATHS) typeclass = class_from_module(typeclass, settings.SCRIPT_TYPECLASS_PATHS)
# validate input # validate input
player = dbid_to_obj(player) kwarg = {}
obj = dbid_to_obj(obj) if key: kwarg["db_key"] = key
if player: kwarg["db_player"] = dbid_to_obj(player, _ScriptDB)
if obj: kwarg["db_obj"] = dbid_to_obj(obj, _ScriptDB)
if interval: kwarg["db_interval"] = interval
if start_delay: kwarg["db_start_delay"] = start_delay
if repeats: kwarg["db_repeats"] = repeats
if persistent: kwarg["db_persistent"] = persistent
# create new instance # create new instance
new_script = typeclass(db_key=key, db_obj=obj, db_player=player, new_script = typeclass(**kwarg)
db_interval=interval, db_start_delay=start_delay,
db_repeats=repeats, db_peristent=persistent)
# store the call signature for the signal # store the call signature for the signal
new_script._createdict = {"key":key, "obj":obj, "player":player, new_script._createdict = {"key":key, "obj":obj, "player":player,
"locks":locks, "interval":interval, "locks":locks, "interval":interval,
@ -326,6 +339,10 @@ def create_player(key, email, password,
operations and is thus not suitable for play-testing the game. operations and is thus not suitable for play-testing the game.
""" """
global _PlayerDB
if not _PlayerDB:
from src.players.models import PlayerDB as _PlayerDB
typeclass = typeclass if typeclass else settings.BASE_PLAYER_TYPECLASS typeclass = typeclass if typeclass else settings.BASE_PLAYER_TYPECLASS
if isinstance(typeclass, basestring): if isinstance(typeclass, basestring):