Exemplo n.º 1
0
    def run_init_hooks(self):
        """
        Called every server start
        """
        from evennia.objects.models import ObjectDB
        #from evennia.players.models import PlayerDB

        #update eventual changed defaults
        self.update_defaults()

        #print "run_init_hooks:", ObjectDB.get_all_cached_instances()
        [o.at_init() for o in ObjectDB.get_all_cached_instances()]
        [p.at_init() for p in PlayerDB.get_all_cached_instances()]

        with open(SERVER_RESTART, 'r') as f:
            mode = f.read()
        if mode in ('True', 'reload'):
            from evennia.server.oobhandler import OOB_HANDLER
            OOB_HANDLER.restore()

        from evennia.scripts.tickerhandler import TICKER_HANDLER
        TICKER_HANDLER.restore()

        # call correct server hook based on start file value
        if mode in ('True', 'reload'):
            # True was the old reload flag, kept for compatibilty
            self.at_server_reload_start()
        elif mode in ('reset', 'shutdown'):
            self.at_server_cold_start()
            # clear eventual lingering session storages
            ObjectDB.objects.clear_all_sessids()
        # always call this regardless of start type
        self.at_server_start()
Exemplo n.º 2
0
    def data_in(self, sessid, text="", **kwargs):
        """
        Data Portal -> Server.
        We also intercept OOB communication here.

        Args:
            sessid (int): Session id.

        Kwargs:
            text (str): Text from protocol.
            kwargs (any): Other data from protocol.

        """
        #from evennia.server.profiling.timetrace import timetrace
        #text = timetrace(text, "ServerSessionHandler.data_in")
        session = self.sessions.get(sessid, None)
        if session:
            text = text and to_unicode(strip_control_sequences(text), encoding=session.encoding)
            if "oob" in kwargs:
                # incoming data is always on the form (cmdname, args, kwargs)
                global _OOB_HANDLER
                if not _OOB_HANDLER:
                    from evennia.server.oobhandler import OOB_HANDLER as _OOB_HANDLER
                funcname, args, kwargs = kwargs.pop("oob")
                #print "OOB session.data_in:", funcname, args, kwargs
                if funcname:
                    _OOB_HANDLER.execute_cmd(session, funcname, *args, **kwargs)

            # pass the rest off to the session
            session.data_in(text=text, **kwargs)
Exemplo n.º 3
0
def oob_unreport(session, *args, **kwargs):
    """
    This removes tracking for the given data.

    Args:
        session (Session): Session controling this command.

    """
    obj = session.get_puppet_or_player()
    if obj:
        for name in (a.upper() for a in args if a):
            propname = OOB_REPORTABLE.get(name, None)
            if not propname:
                oob_error(
                    session,
                    "No Un-Reportable property '%s'. Use LIST REPORTABLE_VARIABLES."
                    % propname)
            elif propname.startswith("db_"):
                OOB_HANDLER.remove_field_monitor(obj, session, propname,
                                                 "oob_return_field_report")
            else:  # assume attribute
                OOB_HANDLER.remove_attribute_monitor(
                    obj, session, propname, "oob_return_attribute_report")
    else:
        oob_error(session, "You must log in first.")
Exemplo n.º 4
0
    def data_in(self, sessid, text="", **kwargs):
        """
        Data Portal -> Server.
        We also intercept OOB communication here.

        Args:
            sessid (int): Session id.

        Kwargs:
            text (str): Text from protocol.
            kwargs (any): Other data from protocol.

        """
        session = self.sessions.get(sessid, None)
        if session:
            text = text and to_unicode(strip_control_sequences(text),
                                       encoding=session.encoding)
            if "oob" in kwargs:
                # incoming data is always on the form (cmdname, args, kwargs)
                global _OOB_HANDLER
                if not _OOB_HANDLER:
                    from evennia.server.oobhandler import OOB_HANDLER as _OOB_HANDLER
                funcname, args, kwargs = kwargs.pop("oob")
                #print "OOB session.data_in:", funcname, args, kwargs
                if funcname:
                    _OOB_HANDLER.execute_cmd(session, funcname, *args,
                                             **kwargs)

            # pass the rest off to the session
            session.data_in(text=text, **kwargs)
Exemplo n.º 5
0
    def run_init_hooks(self):
        """
        Called every server start
        """
        from evennia.objects.models import ObjectDB
        #from evennia.players.models import PlayerDB

        #update eventual changed defaults
        self.update_defaults()

        [o.at_init() for o in ObjectDB.get_all_cached_instances()]
        [p.at_init() for p in PlayerDB.get_all_cached_instances()]

        with open(SERVER_RESTART, 'r') as f:
            mode = f.read()
        if mode in ('True', 'reload'):
            from evennia.server.oobhandler import OOB_HANDLER
            OOB_HANDLER.restore()

        from evennia.scripts.tickerhandler import TICKER_HANDLER
        TICKER_HANDLER.restore()

        # call correct server hook based on start file value
        if mode in ('True', 'reload'):
            # True was the old reload flag, kept for compatibilty
            self.at_server_reload_start()
        elif mode == 'reset':
            # only run hook, don't purge sessions
            self.at_server_cold_start()
        elif mode in ('reset', 'shutdown'):
            self.at_server_cold_start()
            # clear eventual lingering session storages
            ObjectDB.objects.clear_all_sessids()
        # always call this regardless of start type
        self.at_server_start()
Exemplo n.º 6
0
def oob_report(session, *args, **kwargs):
    """
    Called with the `REPORT PROPNAME` MSDP command.
    Monitors the changes of given property name. Assumes reporting
    happens on an object controlled by the session.

    Args:
        session (Session): The Session doing the monitoring. The
            property is assumed to sit on the entity currently
            controlled by the Session. If puppeting, this is an
            Object, otherwise the object will be the Player the
            Session belongs to.
        args (str or list): One or more property names to monitor changes in.
            If a name starts with `db_`, the property is assumed to
            be a field, otherwise an Attribute of the given name will
            be monitored (if it exists).

    Notes:
        When the property updates, the monitor will send a MSDP_ARRAY
        to the session of the form `(SEND, fieldname, new_value)`

    Examples:
        ("REPORT", "CHARACTER_NAME")
        ("MSDP_TABLE", "CHARACTER_NAME", "Amanda")

    """
    obj = session.get_puppet_or_player()
    if obj:
        ret = []
        for name in args:
            propname = OOB_REPORTABLE.get(name, None)
            if not propname:
                oob_error(
                    session,
                    "No Reportable property '%s'. Use LIST REPORTABLE_VARIABLES."
                    % propname)
            # the field_monitors require an oob function as a callback when they report a change.
            elif propname.startswith("db_"):
                OOB_HANDLER.add_field_monitor(obj, session.sessid, propname,
                                              "return_field_report")
                ret.append(to_str(_GA(obj, propname), force_string=True))
            else:
                OOB_HANDLER.add_attribute_monitor(obj, session.sessid,
                                                  propname,
                                                  "return_attribute_report")
                ret.append(_GA(obj, "db_value"))
        #print "ret:", ret
        session.msg(oob=("MSDP_ARRAY", ret))
    else:
        oob_error(session, "You must log in first.")
Exemplo n.º 7
0
def oob_unreport(session, *args, **kwargs):
    """
    This removes tracking for the given data.
    """
    obj = session.get_puppet_or_player()
    if obj:
        for name in (a.upper() for a in args if a):
            propname = OOB_REPORTABLE.get(name, None)
            if not propname:
                oob_error(session, "No Un-Reportable property '%s'. Use LIST REPORTABLE_VARIABLES." % propname)
            elif propname.startswith("db_"):
                OOB_HANDLER.remove_field_monitor(obj, session.sessid, propname, "oob_return_field_report")
            else:  # assume attribute
                OOB_HANDLER.remove_attribute_monitor(obj, session.sessid, propname, "oob_return_attribute_report")
    else:
        oob_error(session, "You must log in first.")
Exemplo n.º 8
0
def oob_unrepeat(session, oobfuncname, interval):
    """
    Called with UNREPEAT <oobfunc> <interval>
    Disable repeating callback.

    Args:
        session (Session): Session controlling the repeater
        oobfuncname (str): OOB function called every interval seconds
        interval (int): Interval of repeater, in seconds.

    Notes:
        The command checks so that it cannot repeat itself.


    """
    obj = session.get_puppet_or_player()
    if obj:
        OOB_HANDLER.remove_repeater(obj, session.sessid, oobfuncname, interval)
Exemplo n.º 9
0
def oob_unrepeat(session, oobfuncname, interval):
    """
    Called with UNREPEAT <oobfunc> <interval>
    Disable repeating callback.

    Args:
        session (Session): Session controlling the repeater
        oobfuncname (str): OOB function called every interval seconds
        interval (int): Interval of repeater, in seconds.

    Notes:
        The command checks so that it cannot repeat itself.


    """
    obj = session.get_puppet_or_player()
    if obj:
        OOB_HANDLER.remove_repeater(obj, session, oobfuncname, interval)
Exemplo n.º 10
0
def oob_report(session, *args, **kwargs):
    """
    Called with the `REPORT PROPNAME` MSDP command.
    Monitors the changes of given property name. Assumes reporting
    happens on an object controlled by the session.

    Args:
        session (Session): The Session doing the monitoring. The
            property is assumed to sit on the entity currently
            controlled by the Session. If puppeting, this is an
            Object, otherwise the object will be the Player the
            Session belongs to.
        args (str or list): One or more property names to monitor changes in.
            If a name starts with `db_`, the property is assumed to
            be a field, otherwise an Attribute of the given name will
            be monitored (if it exists).

    Notes:
        When the property updates, the monitor will send a MSDP_ARRAY
        to the session of the form `(SEND, fieldname, new_value)`

    Examples:
        ("REPORT", "CHARACTER_NAME")
        ("MSDP_TABLE", "CHARACTER_NAME", "Amanda")

    """
    obj = session.get_puppet_or_player()
    if obj:
        ret = []
        for name in args:
            propname = OOB_REPORTABLE.get(name, None)
            if not propname:
                oob_error(session, "No Reportable property '%s'. Use LIST REPORTABLE_VARIABLES." % propname)
            # the field_monitors require an oob function as a callback when they report a change.
            elif propname.startswith("db_"):
                OOB_HANDLER.add_field_monitor(obj, session.sessid, propname, "return_field_report")
                ret.append(to_str(_GA(obj, propname), force_string=True))
            else:
                OOB_HANDLER.add_attribute_monitor(obj, session.sessid, propname, "return_attribute_report")
                ret.append(_GA(obj, "db_value"))
        #print "ret:", ret
        session.msg(oob=("MSDP_ARRAY", ret))
    else:
        oob_error(session, "You must log in first.")
Exemplo n.º 11
0
    def data_in(self, sessid, text="", **kwargs):
        """
        Data Portal -> Server.
        We also intercept OOB communication here.
        """
        session = self.sessions.get(sessid, None)
        if session:
            text = text and to_unicode(strip_control_sequences(text), encoding=session.encoding)
            if "oob" in kwargs:
                # incoming data is always on the form (cmdname, args, kwargs)
                global _OOB_HANDLER
                if not _OOB_HANDLER:
                    from evennia.server.oobhandler import OOB_HANDLER as _OOB_HANDLER
                funcname, args, kwargs = kwargs.pop("oob")
                #print "OOB session.data_in:", funcname, args, kwargs
                if funcname:
                    _OOB_HANDLER.execute_cmd(session, funcname, *args, **kwargs)

            # pass the rest off to the session
            session.data_in(text=text, **kwargs)
Exemplo n.º 12
0
def oob_repeat(session, oobfuncname, interval, *args, **kwargs):
    """
    Called as REPEAT <oobfunc> <interval> <args>
    Repeats a given OOB command with a certain frequency.

    Args:
        session (Session): Session creating the repeat
        oobfuncname (str): OOB function called every interval seconds
        interval (int): Interval of repeat, in seconds.

    Notes:
        The command checks so that it cannot repeat itself.

    """
    if not oobfuncname:
        oob_error(session, "Usage: REPEAT <oobfuncname>, <interval>")
        return
    # limit repeat actions to minimum 5 seconds interval
    interval = 20 if not interval else (max(5, interval))
    obj = session.get_puppet_or_player()
    if obj and oobfuncname != "REPEAT":
        OOB_HANDLER.add_repeater(obj, session.sessid, oobfuncname, interval, *args, **kwargs)
Exemplo n.º 13
0
def oob_repeat(session, oobfuncname, interval, *args, **kwargs):
    """
    Called as REPEAT <oobfunc> <interval> <args>
    Repeats a given OOB command with a certain frequency.

    Args:
        session (Session): Session creating the repeat
        oobfuncname (str): OOB function called every interval seconds
        interval (int): Interval of repeat, in seconds.

    Notes:
        The command checks so that it cannot repeat itself.

    """
    if not oobfuncname:
        oob_error(session, "Usage: REPEAT <oobfuncname>, <interval>")
        return
    # limit repeat actions to minimum 5 seconds interval
    interval = 20 if not interval else (max(5, interval))
    obj = session.get_puppet_or_player()
    if obj and oobfuncname != "REPEAT":
        OOB_HANDLER.add_repeater(obj, session, oobfuncname, interval, *args, **kwargs)
Exemplo n.º 14
0
def oob_list(session, mode, *args, **kwargs):
    """
    Called with the `LIST <MODE>`  MSDP command.

    Args:
        session (Session): The Session asking for the information
        mode (str): The available properties. One of
            "COMMANDS"               Request an array of commands supported
                                     by the server.
            "LISTS"                  Request an array of lists supported
                                     by the server.
            "CONFIGURABLE_VARIABLES" Request an array of variables the client
                                     can configure.
            "REPORTABLE_VARIABLES"   Request an array of variables the server
                                     will report.
            "REPORTED_VARIABLES"     Request an array of variables currently
                                     being reported.
            "SENDABLE_VARIABLES"     Request an array of variables the server
                                     will send.
    Examples:
        oob in: LIST COMMANDS
        oob out: (COMMANDS, (SEND, REPORT, LIST, ...)

    """
    mode = mode.upper()
    if mode == "COMMANDS":
        session.msg(oob=("COMMANDS", ("LIST",
                                     "REPORT",
                                     "UNREPORT",
                                     # "RESET",
                                     "SEND")))
    elif mode == "REPORTABLE_VARIABLES":
        session.msg(oob=("REPORTABLE_VARIABLES", tuple(key for key in OOB_REPORTABLE.keys())))
    elif mode == "REPORTED_VARIABLES":
        # we need to check so as to use the right return value depending on if it is
        # an Attribute (identified by tracking the db_value field) or a normal database field
        # reported is a list of tuples (obj, propname, args, kwargs)
        reported = OOB_HANDLER.get_all_monitors(session.sessid)
        reported = [rep[0].key if rep[1] == "db_value" else rep[1] for rep in reported]
        session.msg(oob=("REPORTED_VARIABLES", reported))
    elif mode == "SENDABLE_VARIABLES":
        session.msg(oob=("SENDABLE_VARIABLES", tuple(key for key in OOB_REPORTABLE.keys())))
    elif mode == "CONFIGURABLE_VARIABLES":
        # Not implemented (game specific)
        oob_error(session, "Not implemented (game specific)")
    else:
        # mode == "LISTS" or not given
        session.msg(oob=("LISTS",("REPORTABLE_VARIABLES",
                                  "REPORTED_VARIABLES",
                                  # "CONFIGURABLE_VARIABLES",
                                  "SENDABLE_VARIABLES")))
Exemplo n.º 15
0
def oob_list(session, mode, *args, **kwargs):
    """
    Called with the `LIST <MODE>`  MSDP command.

    Args:
        session (Session): The Session asking for the information
        mode (str): The available properties. One of
            "COMMANDS"               Request an array of commands supported
                                     by the server.
            "LISTS"                  Request an array of lists supported
                                     by the server.
            "CONFIGURABLE_VARIABLES" Request an array of variables the client
                                     can configure.
            "REPORTABLE_VARIABLES"   Request an array of variables the server
                                     will report.
            "REPORTED_VARIABLES"     Request an array of variables currently
                                     being reported.
            "SENDABLE_VARIABLES"     Request an array of variables the server
                                     will send.
    Examples:
        oob in: LIST COMMANDS
        oob out: (COMMANDS, (SEND, REPORT, LIST, ...)

    """
    mode = mode.upper()
    if mode == "COMMANDS":
        session.msg(oob=("COMMANDS", ("LIST",
                                     "REPORT",
                                     "UNREPORT",
                                     # "RESET",
                                     "SEND")))
    elif mode == "REPORTABLE_VARIABLES":
        session.msg(oob=("REPORTABLE_VARIABLES", tuple(key for key in OOB_REPORTABLE.keys())))
    elif mode == "REPORTED_VARIABLES":
        # we need to check so as to use the right return value depending on if it is
        # an Attribute (identified by tracking the db_value field) or a normal database field
        # reported is a list of tuples (obj, propname, args, kwargs)
        reported = OOB_HANDLER.get_all_monitors(session)
        reported = [rep[0].key if rep[1] == "db_value" else rep[1] for rep in reported]
        session.msg(oob=("REPORTED_VARIABLES", reported))
    elif mode == "SENDABLE_VARIABLES":
        session.msg(oob=("SENDABLE_VARIABLES", tuple(key for key in OOB_REPORTABLE.keys())))
    elif mode == "CONFIGURABLE_VARIABLES":
        # Not implemented (game specific)
        oob_error(session, "Not implemented (game specific)")
    else:
        # mode == "LISTS" or not given
        session.msg(oob=("LISTS",("REPORTABLE_VARIABLES",
                                  "REPORTED_VARIABLES",
                                  # "CONFIGURABLE_VARIABLES",
                                  "SENDABLE_VARIABLES")))
Exemplo n.º 16
0
    def shutdown(self, mode=None, _reactor_stopping=False):
        """
        Shuts down the server from inside it.

        mode - sets the server restart mode.
               'reload' - server restarts, no "persistent" scripts
                          are stopped, at_reload hooks called.
               'reset' - server restarts, non-persistent scripts stopped,
                         at_shutdown hooks called.
               'shutdown' - like reset, but server will not auto-restart.
               None - keep currently set flag from flag file.
        _reactor_stopping - this is set if server is stopped by a kill
                            command OR this method was already called
                             once - in both cases the reactor is
                             dead/stopping already.
        """
        if _reactor_stopping and hasattr(self, "shutdown_complete"):
            # this means we have already passed through this method
            # once; we don't need to run the shutdown procedure again.
            defer.returnValue(None)

        mode = self.set_restart_mode(mode)
        # call shutdown hooks on all cached objects

        from evennia.objects.models import ObjectDB
        #from evennia.players.models import PlayerDB
        from evennia.server.models import ServerConfig

        if mode == 'reload':
            # call restart hooks
            yield [
                o.at_server_reload()
                for o in ObjectDB.get_all_cached_instances()
            ]
            yield [
                p.at_server_reload()
                for p in PlayerDB.get_all_cached_instances()
            ]
            yield [(s.pause(), s.at_server_reload())
                   for s in ScriptDB.get_all_cached_instances()]
            yield self.sessions.all_sessions_portal_sync()
            ServerConfig.objects.conf("server_restart_mode", "reload")

            from evennia.server.oobhandler import OOB_HANDLER
            OOB_HANDLER.save()
            from evennia.scripts.tickerhandler import TICKER_HANDLER
            TICKER_HANDLER.save()

            self.at_server_reload_stop()

        else:
            if mode == 'reset':
                # don't unset the is_connected flag on reset, otherwise
                # same as shutdown
                yield [
                    o.at_server_shutdown()
                    for o in ObjectDB.get_all_cached_instances()
                ]
                yield [
                    p.at_server_shutdown()
                    for p in PlayerDB.get_all_cached_instances()
                ]
            else:  # shutdown
                yield [
                    _SA(p, "is_connected", False)
                    for p in PlayerDB.get_all_cached_instances()
                ]
                yield [
                    o.at_server_shutdown()
                    for o in ObjectDB.get_all_cached_instances()
                ]
                yield [(p.unpuppet_all(), p.at_server_shutdown())
                       for p in PlayerDB.get_all_cached_instances()]
            yield [
                s.at_server_shutdown()
                for s in ScriptDB.get_all_cached_instances()
            ]
            yield ObjectDB.objects.clear_all_sessids()
            ServerConfig.objects.conf("server_restart_mode", "reset")

            self.at_server_cold_stop()

        self.at_server_stop()
        # if _reactor_stopping is true, reactor does not need to
        # be stopped again.
        if os.name == 'nt' and os.path.exists(SERVER_PIDFILE):
            # for Windows we need to remove pid files manually
            os.remove(SERVER_PIDFILE)
        if not _reactor_stopping:
            # this will also send a reactor.stop signal, so we set a
            # flag to avoid loops.
            self.shutdown_complete = True
            reactor.callLater(0, reactor.stop)
Exemplo n.º 17
0
    def shutdown(self, mode=None, _reactor_stopping=False):
        """
        Shuts down the server from inside it.

        mode - sets the server restart mode.
               'reload' - server restarts, no "persistent" scripts
                          are stopped, at_reload hooks called.
               'reset' - server restarts, non-persistent scripts stopped,
                         at_shutdown hooks called but sessions will not
                         be disconnected.
               'shutdown' - like reset, but server will not auto-restart.
               None - keep currently set flag from flag file.
        _reactor_stopping - this is set if server is stopped by a kill
                            command OR this method was already called
                             once - in both cases the reactor is
                             dead/stopping already.
        """
        if _reactor_stopping and hasattr(self, "shutdown_complete"):
            # this means we have already passed through this method
            # once; we don't need to run the shutdown procedure again.
            defer.returnValue(None)

        mode = self.set_restart_mode(mode)

        from evennia.objects.models import ObjectDB
        #from evennia.players.models import PlayerDB
        from evennia.server.models import ServerConfig

        if mode == 'reload':
            # call restart hooks
            ServerConfig.objects.conf("server_restart_mode", "reload")
            yield [o.at_server_reload() for o in ObjectDB.get_all_cached_instances()]
            yield [p.at_server_reload() for p in PlayerDB.get_all_cached_instances()]
            yield [(s.pause(), s.at_server_reload()) for s in ScriptDB.get_all_cached_instances()]
            yield self.sessions.all_sessions_portal_sync()
            self.at_server_reload_stop()
            # only save OOB state on reload, not on shutdown/reset
            from evennia.server.oobhandler import OOB_HANDLER
            OOB_HANDLER.save()
        else:
            if mode == 'reset':
                # like shutdown but don't unset the is_connected flag and don't disconnect sessions
                yield [o.at_server_shutdown() for o in ObjectDB.get_all_cached_instances()]
                yield [p.at_server_shutdown() for p in PlayerDB.get_all_cached_instances()]
                if self.amp_protocol:
                    yield self.sessions.all_sessions_portal_sync()
            else:  # shutdown
                yield [_SA(p, "is_connected", False) for p in PlayerDB.get_all_cached_instances()]
                yield [o.at_server_shutdown() for o in ObjectDB.get_all_cached_instances()]
                yield [(p.unpuppet_all(), p.at_server_shutdown())
                                       for p in PlayerDB.get_all_cached_instances()]
                yield ObjectDB.objects.clear_all_sessids()
            yield [(s.pause(), s.at_server_reload()) for s in ScriptDB.get_all_cached_instances()]
            ServerConfig.objects.conf("server_restart_mode", "reset")
            self.at_server_cold_stop()

        # tickerhandler state should always be saved.
        from evennia.scripts.tickerhandler import TICKER_HANDLER
        TICKER_HANDLER.save()

        # always called, also for a reload
        self.at_server_stop()

        # if _reactor_stopping is true, reactor does not need to
        # be stopped again.
        if os.name == 'nt' and os.path.exists(SERVER_PIDFILE):
            # for Windows we need to remove pid files manually
            os.remove(SERVER_PIDFILE)
        if not _reactor_stopping:
            # this will also send a reactor.stop signal, so we set a
            # flag to avoid loops.
            self.shutdown_complete = True
            # kill the server
            reactor.callLater(0, reactor.stop)