Refactored signals with better names and more of them. Put them after hook calls.

This commit is contained in:
Andrew Bastien 2019-04-13 18:05:15 -04:00
parent 11dc2ee561
commit 72faf039cf
6 changed files with 79 additions and 30 deletions

View file

@ -29,8 +29,8 @@ from evennia.utils import class_from_module, create, logger
from evennia.utils.utils import (lazy_property, to_str,
make_iter, is_iter,
variable_from_module)
from evennia.utils.signals import (ACCOUNT_CREATE, OBJECT_PUPPET,
OBJECT_UNPUPPET, ACCOUNT_LOGOUT)
from evennia.server.signals import (SIGNAL_ACCOUNT_POST_CREATE, SIGNAL_OBJECT_POST_PUPPET,
SIGNAL_OBJECT_POST_UNPUPPET)
from evennia.typeclasses.attributes import NickHandler
from evennia.scripts.scripthandler import ScriptHandler
from evennia.commands.cmdsethandler import CmdSetHandler
@ -230,8 +230,6 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
if not _SESSIONS:
from evennia.server.sessionhandler import SESSIONS as _SESSIONS
_SESSIONS.disconnect(session, reason)
if not self.sessions.all():
ACCOUNT_LOGOUT.send(sender=self)
# puppeting operations
@ -306,8 +304,8 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
# re-cache locks to make sure superuser bypass is updated
obj.locks.cache_lock_bypass(obj)
# final hook
OBJECT_PUPPET.send(sender=obj, account=self, session=session)
obj.at_post_puppet()
SIGNAL_OBJECT_POST_PUPPET.send(sender=obj, account=self, session=session)
def unpuppet_object(self, session):
"""
@ -329,8 +327,8 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
obj.sessions.remove(session)
if not obj.sessions.count():
del obj.account
OBJECT_UNPUPPET.send(sender=obj, session=session, account=self)
obj.at_post_unpuppet(self, session=session)
SIGNAL_OBJECT_POST_UNPUPPET.send(sender=obj, session=session, account=self)
# Just to be sure we're always clear.
session.puppet = None
session.puid = None
@ -745,7 +743,7 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
# Update the throttle to indicate a new account was created from this IP
if ip and not guest:
CREATION_THROTTLE.update(ip, 'Too many accounts being created.')
ACCOUNT_CREATE.send(sender=account)
SIGNAL_ACCOUNT_POST_CREATE.send(sender=account, ip=ip)
return account, errors
def delete(self, *args, **kwargs):

View file

@ -25,7 +25,7 @@ from django.utils.encoding import smart_str
from evennia.accounts.manager import AccountDBManager
from evennia.typeclasses.models import TypedObject
from evennia.utils.utils import make_iter
from evennia.utils.signals import ACCOUNT_RENAME
from evennia.server.signals import SIGNAL_ACCOUNT_POST_RENAME
__all__ = ("AccountDB",)
@ -150,7 +150,7 @@ class AccountDB(TypedObject, AbstractUser):
old_name = self.username
self.username = value
self.save(update_fields=["username"])
ACCOUNT_RENAME.send(self, old_name=old_name, new_name=value)
SIGNAL_ACCOUNT_POST_RENAME.send(self, old_name=old_name, new_name=value)
def __username_del(self):
del self.username

View file

@ -20,13 +20,12 @@ from django.conf import settings
from evennia.commands.cmdhandler import CMD_LOGINSTART
from evennia.utils.logger import log_trace
from evennia.utils.utils import (variable_from_module, is_iter,
to_str, make_iter, delay, callables_from_module)
from evennia.utils.signals import ACCOUNT_LOGIN
make_iter, delay, callables_from_module)
from evennia.server.signals import SIGNAL_ACCOUNT_POST_LOGIN, SIGNAL_ACCOUNT_POST_LOGOUT
from evennia.server.signals import SIGNAL_ACCOUNT_POST_CONNECT, SIGNAL_ACCOUNT_POST_DISCONNECT
from evennia.utils.inlinefuncs import parse_inlinefunc
from codecs import decode as codecs_decode
import pickle
_INLINEFUNC_ENABLED = settings.INLINEFUNC_ENABLED
# delayed imports
@ -518,9 +517,10 @@ class ServerSessionHandler(SessionHandler):
operation=SLOGIN,
sessiondata={"logged_in": True,
"uid": session.uid})
if nsess < 2:
ACCOUNT_LOGIN.send(sender=account, session=session)
account.at_post_login(session=session)
if nsess < 2:
SIGNAL_ACCOUNT_POST_LOGIN.send(sender=account, session=session)
SIGNAL_ACCOUNT_POST_CONNECT.send(sender=account, session=session)
def disconnect(self, session, reason="", sync_portal=True):
"""
@ -547,7 +547,11 @@ class ServerSessionHandler(SessionHandler):
string = string.format(reason=sreason, account=session.account, address=session.address, nsessions=nsess)
session.log(string)
if nsess == 0:
SIGNAL_ACCOUNT_POST_LOGOUT.send(sender=session.account, session=session)
session.at_disconnect(reason)
SIGNAL_ACCOUNT_POST_DISCONNECT.send(sender=session.account, session=session)
sessid = session.sessid
if sessid in self and not hasattr(self, "_disconnect_all"):
del self[sessid]

60
evennia/server/signals.py Normal file
View file

@ -0,0 +1,60 @@
"""
This module brings Django Signals into Evennia. These are events that
can be subscribed to by importing a given Signal and using the
following code.
THIS_SIGNAL.connect(callback, sender_object)
When other code calls THIS_SIGNAL.send(sender, **kwargs), the callback
will be triggered.
Callbacks must be in the following format:
def my_callback(sender, **kwargs):
...
This is used on top of hooks to make certain features easier to
add to contribs without necessitating a full takeover of hooks
that may be in high demand.
"""
from django.dispatch import Signal
# The sender is the created Account. This is triggered at the very end of Account.create()
# after the Account is created.
SIGNAL_ACCOUNT_POST_CREATE = Signal(providing_args=['ip', ])
# The Sender is the renamed Account. This is triggered by the username setter in AccountDB.
SIGNAL_ACCOUNT_POST_RENAME = Signal(providing_args=['old_name', 'new_name'])
# The Sender is the connecting Account. This is triggered when an Account connects cold;
# that is, it had no other sessions connected.
SIGNAL_ACCOUNT_POST_LOGIN = Signal(providing_args=['session', ])
# The Sender is the Account attempting to authenticate. This is triggered whenever a
# session tries to login to an Account but fails.
SIGNAL_ACCOUNT_POST_LOGIN_FAIL = Signal(providing_args=['session', ])
# The sender is the connecting Account. This is triggered whenever a session authenticates
# to an Account regardless of existing sessions.
SIGNAL_ACCOUNT_POST_CONNECT = Signal(providing_args=['session', ])
# The sender is the Account. This is triggered when an Account's final session disconnects.
SIGNAL_ACCOUNT_POST_LOGOUT = Signal(providing_args=['session', ])
# The sender is the disconnecting Account. This is triggered whenever a session disconnects
# from the account, regardless of how many it started with or remain.
SIGNAL_ACCOUNT_POST_DISCONNECT = Signal(providing_args=['session', ])
# The sender is the Object being puppeted. This is triggered after all puppeting hooks have
# been called. The Object has already been puppeted by this point.
SIGNAL_OBJECT_POST_PUPPET = Signal(providing_args=['session', 'account'])
# The sender is the Object being released. This is triggered after all hooks are called.
# The Object is no longer puppeted by this point.
SIGNAL_OBJECT_POST_UNPUPPET = Signal(providing_args=['session', 'account'])
# The sender is the Typed Object being released. This isn't necessarily an Object;
# it could be a script. It fires whenever the value of the Typed object's 'key'
# changes. Will need to use isinstance() or other filtering on things that use this.
SIGNAL_TYPED_OBJECT_POST_RENAME = Signal(providing_args=['old_key', 'new_key'])

View file

@ -42,6 +42,7 @@ from evennia.typeclasses.attributes import Attribute, AttributeHandler, NAttribu
from evennia.typeclasses.tags import Tag, TagHandler, AliasHandler, PermissionHandler
from evennia.utils.idmapper.models import SharedMemoryModel, SharedMemoryModelBase
from evennia.server.signals import SIGNAL_TYPED_OBJECT_POST_RENAME
from evennia.typeclasses import managers
from evennia.locks.lockhandler import LockHandler
@ -326,6 +327,7 @@ class TypedObject(SharedMemoryModel):
self.db_key = value
self.save(update_fields=["db_key"])
self.at_rename(oldname, value)
SIGNAL_TYPED_OBJECT_POST_RENAME.send(sender=self, old_key=oldname, new_key=value)
#
#

View file

@ -1,15 +0,0 @@
from django.dispatch import Signal
ACCOUNT_CREATE = Signal(providing_args=['session', ])
ACCOUNT_RENAME = Signal(providing_args=['old_name', 'new_name'])
ACCOUNT_LOGIN = Signal(providing_args=['session', ])
ACCOUNT_LOGOUT = Signal()
OBJECT_PUPPET = Signal(providing_args=['session', 'account'])
OBJECT_UNPUPPET = Signal(providing_args=['session', 'account'])