Esempio n. 1
0
    def _load_script(self, key):
        self.load_data()

        typeclass = self.typeclass_storage[key]
        found = typeclass.objects.filter(db_key=key).first()
        interval = self.loaded_data[key].get('interval', None)
        start_delay = self.loaded_data[key].get('start_delay', None)
        repeats = self.loaded_data[key].get('repeats', 0)
        desc = self.loaded_data[key].get('desc', '')

        if not found:
            logger.log_info(
                f"GLOBAL_SCRIPTS: (Re)creating {key} ({typeclass}).")
            new_script, errors = typeclass.create(key=key,
                                                  persistent=True,
                                                  interval=interval,
                                                  start_delay=start_delay,
                                                  repeats=repeats,
                                                  desc=desc)
            if errors:
                logger.log_err("\n".join(errors))
                return None

            new_script.start()
            return new_script

        if ((found.interval != interval) or (found.start_delay != start_delay)
                or (found.repeats != repeats)):
            found.restart(interval=interval,
                          start_delay=start_delay,
                          repeats=repeats)
        if found.desc != desc:
            found.desc = desc
        return found
    def set_password(self, password, force=False):
        """
        Applies the given password to the account if it passes validation checks.
        Can be overridden by using the 'force' flag.

        Args:
            password (str): Password to set

        Kwargs:
            force (bool): Sets password without running validation checks.

        Raises:
            ValidationError

        Returns:
            None (None): Does not return a value.

        """
        if not force:
            # Run validation checks
            valid, error = self.validate_password(password, account=self)
            if error: raise error

        super(DefaultAccount, self).set_password(password)
        logger.log_info("Password succesfully changed for %s." % self)
        self.at_password_change()
Esempio n. 3
0
def create_objects():
    """
    Creates the #1 account and Limbo room.

    """

    logger.log_info("Initial setup: Sanitizing God Account...")

    # grab the Athanor API. We'll be using it a bit for setting things up.
    # This will also create the grid defined via Fixtures.
    import athanor
    api = athanor.api()

    # Set the initial User's account object's username on the #1 object.
    # This object is pure django and only holds name, email and password.
    god_account = get_god_account()

    # Create an Account 'user profile' object to hold eventual
    # mud-specific settings for the AccountDB object.
    account_typeclass = settings.BASE_ACCOUNT_TYPECLASS

    # run all creation hooks on god_account (we must do so manually
    # since the manage.py command does not)
    god_account.swap_typeclass(account_typeclass, clean_attributes=True)
    god_account.basetype_setup()
    god_account.at_account_creation()
    god_account.locks.add(
        "examine:perm(Developer);edit:false();delete:false();boot:false();msg:all()"
    )
    # this is necessary for quelling to work correctly.
    god_account.permissions.add("Developer")
    """
Esempio n. 4
0
    def _send_to_connect_channel(self, message):
        """
        Helper method for loading and sending to the comm channel
        dedicated to connection messages.

        Args:
            message (str): A message to send to the connect channel.

        """
        from django.conf import settings
        from evennia.utils import logger
        from evennia.comms.models import ChannelDB
        from django.utils import timezone

        global _MUDINFO_CHANNEL
        if not _MUDINFO_CHANNEL:
            try:
                _MUDINFO_CHANNEL = ChannelDB.objects.filter(
                    db_key=settings.CHANNEL_MUDINFO["key"])[0]
            except Exception:
                logger.log_trace()
        now = timezone.now()
        now = "%02i-%02i-%02i(%02i:%02i)" % (
            now.year,
            now.month,
            now.day,
            now.hour,
            now.minute,
        )
        if _MUDINFO_CHANNEL:
            _MUDINFO_CHANNEL.tempmsg(
                f"[{_MUDINFO_CHANNEL.key}, {now}]: {message}")
        else:
            logger.log_info(f"[{now}]: {message}")
Esempio n. 5
0
 def sell_materials(self):
     """Attempt to sell the materials we made the deal for"""
     if self.resource_type:
         if not self.caller.player_ob.pay_resources(self.resource_type,
                                                    amt=self.amount):
             raise HaggleError("You do not have enough resources to sell.")
     else:  # crafting materials
         err = "You do not have enough %s to sell." % self.material
         try:
             mats = self.caller.player_ob.Dominion.assets.owned_materials.get(
                 type=self.material)
             if mats.amount < self.amount:
                 raise HaggleError(err)
             mats.amount -= self.amount
             mats.save()
         except OwnedMaterial.DoesNotExist:
             raise HaggleError(err)
     silver = self.silver_value
     self.caller.pay_money(-silver)
     self.caller.msg("You have sold %s %s and gained %s silver." %
                     (self.amount, self.material_display, silver))
     log_msg = "%s has sold %s %s and gained %s silver." % (
         self.caller,
         self.amount,
         self.material_display,
         silver,
     )
     log_info("Haggle Log: %s" % log_msg)
Esempio n. 6
0
 def buy_materials(self):
     """Attempt to buy the materials we made the deal for"""
     err = "You cannot afford the silver cost of %s."
     if self.resource_type:
         cost = self.silver_value
         if cost > self.caller.currency:
             raise HaggleError(err % cost)
         self.caller.player_ob.gain_resources(self.resource_type,
                                              self.amount)
     else:
         cost = self.silver_value
         if cost > self.caller.currency:
             raise HaggleError(err % cost)
         (
             mat,
             _,
         ) = self.caller.player_ob.Dominion.assets.owned_materials.get_or_create(
             type=self.material)
         mat.amount += self.amount
         mat.save()
     self.caller.pay_money(cost)
     self.caller.msg("You have bought %s %s for %s silver." %
                     (self.amount, self.material_display, cost))
     log_msg = "%s has bought %s %s for %s silver." % (
         self.caller,
         self.amount,
         self.material_display,
         cost,
     )
     log_info("Haggle Log: %s" % log_msg)
Esempio n. 7
0
    def advance_weekly_resonance(self, practitioner):

        mana_base = round_up(practitioner.character.traits.mana / 2.0)
        resonance_base = int((practitioner.potential ** (1 / 10.0))) ** 6
        resonance_weekly = (resonance_base * mana_base) / 4.0

        new_resonance = min(
            practitioner.potential, practitioner.unspent_resonance + resonance_weekly
        )
        practitioner.unspent_resonance = new_resonance
        practitioner.save()
        if _MAGIC_LOG_ENABLED:
            logger.log_info(
                "Magic: {} gained {} unspent resonance, now {} of {} max".format(
                    str(practitioner),
                    new_resonance,
                    resonance_weekly,
                    practitioner.potential,
                )
            )

        return {
            "name": str(practitioner),
            "gain": resonance_weekly,
            "resonance": new_resonance,
            "potential": practitioner.potential,
        }
Esempio n. 8
0
    def set_password(self, password, force=False):
        """
        Applies the given password to the account if it passes validation checks.
        Can be overridden by using the 'force' flag.

        Args:
            password (str): Password to set

        Kwargs:
            force (bool): Sets password without running validation checks.

        Raises:
            ValidationError

        Returns:
            None (None): Does not return a value.

        """
        if not force:
            # Run validation checks
            valid, error = self.validate_password(password, account=self)
            if error: raise error

        super(DefaultAccount, self).set_password(password)
        logger.log_info("Password succesfully changed for %s." % self)
        self.at_password_change()
Esempio n. 9
0
    def data_in(self, data, **kwargs):
        """
        Send data grapevine -> Evennia

        Keyword Args:
            data (dict): Converted json data.

        """
        event = data["event"]
        if event == "authenticate":
            # server replies to our auth handshake
            if data["status"] != "success":
                log_err("Grapevine authentication failed.")
                self.disconnect()
            else:
                log_info("Connected and authenticated to Grapevine network.")
        elif event == "heartbeat":
            # server sends heartbeat - we have to send one back
            self.send_heartbeat()
        elif event == "restart":
            # set the expected downtime
            self.restart_downtime = data["payload"]["downtime"]
        elif event == "channels/subscribe":
            # subscription verification
            if data.get("status", "success") == "failure":
                err = data.get("error", "N/A")
                self.sessionhandler.data_in(
                    bot_data_in=((f"Grapevine error: {err}"), {
                        "event": event
                    }))
        elif event == "channels/unsubscribe":
            # unsubscribe-verification
            pass
        elif event == "channels/broadcast":
            # incoming broadcast from network
            payload = data["payload"]

            print("channels/broadcast:", payload["channel"], self.channel)
            if str(payload["channel"]) != self.channel:
                # only echo from channels this particular bot actually listens to
                return
            else:
                # correct channel
                self.sessionhandler.data_in(
                    self,
                    bot_data_in=(
                        str(payload["message"]),
                        {
                            "event": event,
                            "grapevine_channel": str(payload["channel"]),
                            "sender": str(payload["name"]),
                            "game": str(payload["game"]),
                        },
                    ),
                )
        elif event == "channels/send":
            pass
        else:
            self.sessionhandler.data_in(self, bot_data_in=("", kwargs))
Esempio n. 10
0
def create_objects():
    """
    Creates the #1 player and Limbo room.

    """

    logger.log_info("Creating objects (Player #1 and Limbo room) ...")

    # Set the initial User's account object's username on the #1 object.
    # This object is pure django and only holds name, email and password.
    god_player = get_god_player()

    # Create a Player 'user profile' object to hold eventual
    # mud-specific settings for the PlayerDB object.
    player_typeclass = settings.BASE_PLAYER_TYPECLASS

    # run all creation hooks on god_player (we must do so manually
    # since the manage.py command does not)
    god_player.swap_typeclass(player_typeclass, clean_attributes=True)
    god_player.basetype_setup()
    god_player.at_player_creation()
    god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()")
    # this is necessary for quelling to work correctly.
    god_player.permissions.add("Immortals")

    # Limbo is the default "nowhere" starting room

    # Create the in-game god-character for player #1 and set
    # it to exist in Limbo.
    character_typeclass = settings.BASE_CHARACTER_TYPECLASS
    god_character = create.create_object(character_typeclass, key=god_player.username, nohome=True)

    god_character.id = 1
    god_character.save()
    god_character.db.desc = _("This is User #1.")
    god_character.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all();puppet:false()")
    god_character.permissions.add("Immortals")

    god_player.attributes.add("_first_login", True)
    god_player.attributes.add("_last_puppet", god_character)

    try:
        god_player.db._playable_characters.append(god_character)
    except AttributeError:
        god_player.db_playable_characters = [god_character]

    room_typeclass = settings.BASE_ROOM_TYPECLASS
    limbo_obj = create.create_object(room_typeclass, _("Limbo"), nohome=True)
    limbo_obj.id = 2
    limbo_obj.save()
    limbo_obj.db.desc = LIMBO_DESC.strip()
    limbo_obj.save()

    # Now that Limbo exists, try to set the user up in Limbo (unless
    # the creation hooks already fixed this).
    if not god_character.location:
        god_character.location = limbo_obj
    if not god_character.home:
        god_character.home = limbo_obj
Esempio n. 11
0
    def advance_weekly_practice(self, practitioner):

        potential_factor = int(practitioner.potential ** (1 / 10.0))

        max_spend = min(
            practitioner.potential / ((potential_factor ** 2) * 10),
            practitioner.unspent_resonance,
        )
        nodes = practitioner.node_resonances.filter(practicing=True)
        if nodes.count() == 0:
            return None

        noderesults = []
        nodenames = []

        # Get a floating point value of how much resonance to add to each node
        spend_each = max_spend / (nodes.count() * 1.0)
        for node in nodes.all():
            nodenames.append(node.node.name)
            add_node = spend_each
            extra = ""
            teacher = ""
            if node.teaching_multiplier:
                add_node *= node.teaching_multiplier
                teacher = node.taught_by
                extra = "(taught by {} for bonus of {}x)".format(
                    str(node.taught_by), node.teaching_multiplier
                )

            if _MAGIC_LOG_ENABLED:
                logger.log_info(
                    "Magic: {} spent {} resonance on node {} for gain of {} {}".format(
                        str(practitioner), spend_each, node.node.name, add_node, extra
                    )
                )

            node.raw_resonance = node.raw_resonance + add_node

            noderesults.append(
                {
                    "node": node.node.name,
                    "gain": add_node,
                    "resonance": node.raw_resonance,
                    "teacher": teacher,
                }
            )

            node.teaching_multiplier = None
            node.taught_by = None
            node.taught_on = None
            node.save()

        self.inform_creator.add_player_inform(
            player=practitioner.character.dompc.player,
            msg="You practiced {} this week.".format(commafy(nodenames)),
            category="Magic",
        )

        return {"name": str(practitioner), "practices": noderesults}
Esempio n. 12
0
def collectstatic():
    """
    Run collectstatic to make sure all web assets are loaded.

    """
    from django.core.management import call_command
    logger.log_info("Initial setup: Gathering static resources using 'collectstatic'")
    call_command('collectstatic', '--noinput')
Esempio n. 13
0
def collectstatic():
    """
    Run collectstatic to make sure all web assets are loaded.

    """
    from django.core.management import call_command
    logger.log_info("Initial setup: Gathering static resources using 'collectstatic'")
    call_command('collectstatic', '--noinput')
Esempio n. 14
0
    def startedConnecting(self, connector):
        """
        Tracks reconnections for debugging.

        Args:
            connector (Connector): Represents the connection.

        """
        log_info("(re)connecting to grapevine channel '%s'" % self.channel)
Esempio n. 15
0
    def startedConnecting(self, connector):
        """
        Tracks reconnections for debugging.

        Args:
            connector (Connector): Represents the connection.

        """
        logger.log_info("(re)connecting to %s" % self.channel)
Esempio n. 16
0
def create_channels():
    """
    Creates some sensible default channels.

    """
    logger.log_info("Initial setup: Creating default channels ...")

    goduser = get_god_account()
    for channeldict in settings.DEFAULT_CHANNELS:
        channel = create.create_channel(**channeldict)
        channel.connect(goduser)
Esempio n. 17
0
def create_channels():
    """
    Creates some sensible default channels.

    """
    logger.log_info("Creating default channels ...")

    goduser = get_god_player()
    for channeldict in settings.DEFAULT_CHANNELS:
        channel = create.create_channel(**channeldict)
        channel.connect(goduser)
Esempio n. 18
0
def reset_server():
    """
    We end the initialization by resetting the server. This makes sure
    the first login is the same as all the following ones,
    particularly it cleans all caches for the special objects.  It
    also checks so the warm-reset mechanism works as it should.

    """
    from evennia.server.sessionhandler import SESSIONS
    logger.log_info(" Initial setup complete. Restarting Server once.")
    SESSIONS.server.shutdown(mode='reset')
Esempio n. 19
0
 def func(self):
     """Define function"""
     # Only allow shutdown if caller has session
     if not self.caller.sessions.get():
         return
     self.msg("Shutting down server ...")
     announcement = "\nServer is being SHUT DOWN!\n"
     if self.args:
         announcement += "%s\n" % self.args
     logger.log_info("Server shutdown by %s." % self.caller.name)
     SESSIONS.announce_all(announcement)
     SESSIONS.portal_shutdown()
Esempio n. 20
0
    def clientConnectionLost(self, connector, reason):
        """
        Called when the AMP connection to the MUD server is lost.

        Args:
            connector (Connector): Twisted Connector instance representing
                this connection.
            reason (str): Eventual text describing why connection was lost.

        """
        logger.log_info("Server disconnected from the portal.")
        protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
Esempio n. 21
0
    def clientConnectionLost(self, connector, reason):
        """
        Called when the AMP connection to the MUD server is lost.

        Args:
            connector (Connector): Twisted Connector instance representing
                this connection.
            reason (str): Eventual text describing why connection was lost.

        """
        logger.log_info("Server disconnected from the portal.")
        protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
Esempio n. 22
0
 def func(self):
     """Define function"""
     # Only allow shutdown if caller has session
     if not self.caller.sessions.get():
         return
     self.msg('Shutting down server ...')
     announcement = "\nServer is being SHUT DOWN!\n"
     if self.args:
         announcement += "%s\n" % self.args
     logger.log_info('Server shutdown by %s.' % self.caller.name)
     SESSIONS.announce_all(announcement)
     SESSIONS.server.shutdown(mode='shutdown')
     SESSIONS.portal_shutdown()
Esempio n. 23
0
    def empty_threadpool(self):
        """
        Converts our _pending_requests list of deferreds into a DeferredList

        Returns:
            deflist (DeferredList): Contains all deferreds of pending requests.

        """
        self.pool.lock()
        if self._pending_requests and self._echo_log:
            self._echo_log = False  # just to avoid multiple echoes
            msg = "Webserver waiting for %i requests ... "
            logger.log_info(msg % len(self._pending_requests))
        return defer.DeferredList(self._pending_requests, consumeErrors=True)
Esempio n. 24
0
    def empty_threadpool(self):
        """
        Converts our _pending_requests list of deferreds into a DeferredList

        Returns:
            deflist (DeferredList): Contains all deferreds of pending requests.

        """
        self.pool.lock()
        if self._pending_requests and self._echo_log:
            self._echo_log = False  # just to avoid multiple echoes
            msg = "Webserver waiting for %i requests ... "
            logger.log_info(msg % len(self._pending_requests))
        return defer.DeferredList(self._pending_requests, consumeErrors=True)
Esempio n. 25
0
    def all_to_category(self, default_category):
        """
        Shifts all help entries in database to default_category.  This
        action cannot be reverted. It is used primarily by the engine
        when importing a default help database, making sure this ends
        up in one easily separated category.

        Args:
            default_category (str): Category to move entries to.

        """
        topics = self.all()
        for topic in topics:
            topic.help_category = default_category
            topic.save()
        string = "Help database moved to category %s" % default_category
        logger.log_info(string)
Esempio n. 26
0
    def signedOn(self):
        """
        This is called when we successfully connect to the network. We
        make sure to now register with the game as a full session.

        """
        self.join(self.channel)
        self.stopping = False
        self.factory.bot = self
        address = "%s@%s" % (self.channel, self.network)
        self.init_session("ircbot", address, self.factory.sessionhandler)
        # we link back to our bot and log in
        self.uid = int(self.factory.uid)
        self.logged_in = True
        self.factory.sessionhandler.connect(self)
        logger.log_info("IRC bot '%s' connected to %s at %s:%s." %
                        (self.nickname, self.channel, self.network, self.port))
Esempio n. 27
0
    def signedOn(self):
        """
        This is called when we successfully connect to the network. We
        make sure to now register with the game as a full session.

        """
        self.join(self.channel)
        self.stopping = False
        self.factory.bot = self
        address = "%s@%s" % (self.channel, self.network)
        self.init_session("ircbot", address, self.factory.sessionhandler)
        # we link back to our bot and log in
        self.uid = int(self.factory.uid)
        self.logged_in = True
        self.factory.sessionhandler.connect(self)
        logger.log_info("IRC bot '%s' connected to %s at %s:%s." % (self.nickname, self.channel,
                                                                    self.network, self.port))
Esempio n. 28
0
    def connectionMade(self):
        """
        Triggered after connecting to the IMC2 network.

        """

        self.stopping = False
        self.factory.bot = self
        address = "%s@%s" % (self.mudname, self.network)
        self.init_session("ircbot", address, self.factory.sessionhandler)
        # link back and log in
        self.uid = int(self.factory.uid)
        self.logged_in = True
        self.factory.sessionhandler.connect(self)
        logger.log_info("IMC2 bot connected to %s." % self.network)
        # Send authentication packet. The reply will be caught by lineReceived
        self._send_packet(pck.IMC2PacketAuthPlaintext())
Esempio n. 29
0
    def connectionMade(self):
        """
        Triggered after connecting to the IMC2 network.

        """

        self.stopping = False
        self.factory.bot = self
        address = "%s@%s" % (self.mudname, self.network)
        self.init_session("ircbot", address, self.factory.sessionhandler)
        # link back and log in
        self.uid = int(self.factory.uid)
        self.logged_in = True
        self.factory.sessionhandler.connect(self)
        logger.log_info("IMC2 bot connected to %s." % self.network)
        # Send authentication packet. The reply will be caught by lineReceived
        self._send_packet(pck.IMC2PacketAuthPlaintext())
Esempio n. 30
0
 def _upgrade(self):
     """
     Internal function to upgrade from the old gametime script
     """
     from evennia.utils import logger
     if not ServerConfig.objects.conf(key="run_time", default=None):
         logger.log_info(
             "Upgrading or configuring gametime as ServerConfig value...")
         run_time = self.attributes.get("run_time", default=0.0)
         ServerConfig.objects.conf(key="run_time", value=run_time)
     if not self.attributes.has("intervals"):
         # Convert from old script style
         run_time = ServerConfig.objects.conf("run_time", default=0.0)
         game_time = run_time * 2
         self.mark_time(runtime=run_time,
                        gametime=game_time,
                        multiplier=TIMEFACTOR)
Esempio n. 31
0
    def all_to_category(self, default_category):
        """
        Shifts all help entries in database to default_category.  This
        action cannot be reverted. It is used primarily by the engine
        when importing a default help database, making sure this ends
        up in one easily separated category.

        Args:
            default_category (str): Category to move entries to.

        """
        topics = self.all()
        for topic in topics:
            topic.help_category = default_category
            topic.save()
        string = "Help database moved to category %s" % default_category
        logger.log_info(string)
Esempio n. 32
0
def at_initial_setup():
    """
    Custom hook for users to overload some or all parts of the initial
    setup. Called very last in the sequence. It tries to import and
    srun a module settings.AT_INITIAL_SETUP_HOOK_MODULE and will fail
    silently if this does not exist or fails to load.

    """
    modname = settings.AT_INITIAL_SETUP_HOOK_MODULE
    if not modname:
        return
    try:
        mod = __import__(modname, fromlist=[None])
    except (ImportError, ValueError):
        return
    logger.log_info(" Running at_initial_setup() hook.")
    if mod.__dict__.get("at_initial_setup", None):
        mod.at_initial_setup()
Esempio n. 33
0
    def log(self, message, channel=True):
        """
        Emits session info to the appropriate outputs and info channels.

        Args:
            message (str): The message to log.
            channel (bool, optional): Log to the CHANNEL_CONNECTINFO channel
                in addition to the server log.

        """
        if channel:
            try:
                cchan = settings.CHANNEL_CONNECTINFO
                cchan = ChannelDB.objects.get_channel(cchan[0])
                cchan.msg("[%s]: %s" % (cchan.key, message))
            except Exception:
                pass
        logger.log_info(message)
Esempio n. 34
0
def at_initial_setup():
    """
    Custom hook for users to overload some or all parts of the initial
    setup. Called very last in the sequence. It tries to import and
    srun a module settings.AT_INITIAL_SETUP_HOOK_MODULE and will fail
    silently if this does not exist or fails to load.

    """
    modname = settings.AT_INITIAL_SETUP_HOOK_MODULE
    if not modname:
        return
    try:
        mod = __import__(modname, fromlist=[None])
    except (ImportError, ValueError):
        return
    logger.log_info("Initial setup: Running at_initial_setup() hook.")
    if mod.__dict__.get("at_initial_setup", None):
        mod.at_initial_setup()
Esempio n. 35
0
    def log(self, message, channel=True):
        """
        Emits session info to the appropriate outputs and info channels.

        Args:
            message (str): The message to log.
            channel (bool, optional): Log to the CHANNEL_CONNECTINFO channel
                in addition to the server log.

        """
        cchan = channel and settings.CHANNEL_CONNECTINFO
        if cchan:
            try:
                cchan = ChannelDB.objects.get_channel(cchan["key"])
                cchan.msg("[%s]: %s" % (cchan.key, message))
            except Exception:
                logger.log_trace()
        logger.log_info(message)
Esempio n. 36
0
def _create_new_room(caller, raw_string, **kwargs):

    # create a random name, retrying until we find
    # a unique one
    key = create_fantasy_word(length=5, capitalize=True)
    while EvscapeRoom.objects.filter(db_key=key):
        key = create_fantasy_word(length=5, capitalize=True)
    room = create.create_object(EvscapeRoom, key=key)
    # we must do this once manually for the new room
    room.statehandler.init_state()
    _move_to_room(caller, "", room=room)

    nrooms = EvscapeRoom.objects.all().count()
    logger.log_info(
        f"Evscaperoom: {caller.key} created room '{key}' (#{room.id}). Now {nrooms} room(s) active."
    )

    room.log(f"JOIN: {caller.key} created and joined room")
    return "node_quit", {"quiet": True}
Esempio n. 37
0
    def mark_time(self, runtime=0.0, gametime=0.0, multiplier=TIMEFACTOR):
        """
        Mark a time interval
        :param runtime: The amount of RL time the game has been running, in seconds,
                        minus downtime.
        :param gametime: The IC timestamp since the IC epoch, in seconds.
        :param multiplier: The multiplier.
        :return:
        """
        tdict = {
            'run': runtime,
            'game': gametime,
            "multiplier": multiplier,
            "real": time.time()
        }
        times = list(self.intervals)
        times.append(tdict)
        self.attributes.add("intervals", times)

        from evennia.utils import logger
        logger.log_info("Gametime: Marked new time {}".format(tdict))
Esempio n. 38
0
    def advance_weekly_resonance(self, practitioner):

        mana_base = round_up(practitioner.character.db.mana / 2.)
        resonance_base = int((practitioner.potential**(1 / 10.)))**6
        resonance_weekly = (resonance_base * mana_base) / 4.

        new_resonance = min(practitioner.potential,
                            practitioner.unspent_resonance + resonance_weekly)
        practitioner.unspent_resonance = new_resonance
        practitioner.save()
        if _MAGIC_LOG_ENABLED:
            logger.log_info(
                "Magic: {} gained {} unspent resonance, now {} of {} max".
                format(str(practitioner), new_resonance, resonance_weekly,
                       practitioner.potential))

        return {
            'name': str(practitioner),
            'gain': resonance_weekly,
            'resonance': new_resonance,
            'potential': practitioner.potential
        }
Esempio n. 39
0
    def _send_to_connect_channel(self, message):
        """
        Helper method for loading and sending to the comm channel
        dedicated to connection messages.

        Args:
            message (str): A message to send to the connect channel.

        """
        global _CONNECT_CHANNEL
        if not _CONNECT_CHANNEL:
            try:
                _CONNECT_CHANNEL = ChannelDB.objects.filter(db_key=settings.DEFAULT_CHANNELS[1]["key"])[0]
            except Exception:
                logger.log_trace()
        now = timezone.now()
        now = "%02i-%02i-%02i(%02i:%02i)" % (now.year, now.month,
                                             now.day, now.hour, now.minute)
        if _CONNECT_CHANNEL:
            _CONNECT_CHANNEL.tempmsg("[%s, %s]: %s" % (_CONNECT_CHANNEL.key, now, message))
        else:
            logger.log_info("[%s]: %s" % (now, message))
Esempio n. 40
0
def create_channels():
    """
    Creates some sensible default channels.

    """
    logger.log_info("Initial setup: Creating default channels ...")

    goduser = get_god_account()

    channel_mudinfo = settings.CHANNEL_MUDINFO
    if not channel_mudinfo:
        raise RuntimeError("settings.CHANNEL_MUDINFO must be defined.")
    channel = create.create_channel(**channel_mudinfo)
    channel.connect(goduser)

    channel_connectinfo = settings.CHANNEL_CONNECTINFO
    if channel_connectinfo:
        channel = create.create_channel(**channel_connectinfo)

    for channeldict in settings.DEFAULT_CHANNELS:
        channel = create.create_channel(**channeldict)
        channel.connect(goduser)
Esempio n. 41
0
    def _send_to_connect_channel(self, message):
        """
        Helper method for loading and sending to the comm channel
        dedicated to connection messages.

        Args:
            message (str): A message to send to the connect channel.

        """
        global _CONNECT_CHANNEL
        if not _CONNECT_CHANNEL:
            try:
                _CONNECT_CHANNEL = ChannelDB.objects.filter(db_key=settings.DEFAULT_CHANNELS[1]["key"])[0]
            except Exception:
                logger.log_trace()
        now = timezone.now()
        now = "%02i-%02i-%02i(%02i:%02i)" % (now.year, now.month,
                                             now.day, now.hour, now.minute)
        if _CONNECT_CHANNEL:
            _CONNECT_CHANNEL.tempmsg("[%s, %s]: %s" % (_CONNECT_CHANNEL.key, now, message))
        else:
            logger.log_info("[%s]: %s" % (now, message))
Esempio n. 42
0
    def onClose(self, wasClean, code=None, reason=None):
        """
        This is executed when the connection is lost for whatever
        reason. it can also be called directly, from the disconnect
        method.

        Args:
            wasClean (bool): ``True`` if the WebSocket was closed cleanly.
            code (int or None): Close status as sent by the WebSocket peer.
            reason (str or None): Close reason as sent by the WebSocket peer.

        """
        self.disconnect(reason)

        if code == GRAPEVINE_HEARTBEAT_FAILURE:
            log_err("Grapevine connection lost (Heartbeat error)")
        elif code == GRAPEVINE_AUTH_ERROR:
            log_err("Grapevine connection lost (Auth error)")
        elif self.restart_downtime:
            # server previously warned us about downtime and told us to be
            # ready to reconnect.
            log_info("Grapevine connection lost (Server restart).")
Esempio n. 43
0
    def add(self, scriptclass, key=None, autostart=True):
        """
        Add a script to this object.

        Args:
            scriptclass (Scriptclass, Script or str): Either a class
                object inheriting from DefaultScript, an instantiated
                script object or a python path to such a class object.
            key (str, optional): Identifier for the script (often set
                in script definition and listings)
            autostart (bool, optional): Start the script upon adding it.

        """
        if self.obj.__dbclass__.__name__ == "AccountDB":
            # we add to an Account, not an Object
            script = create.create_script(scriptclass,
                                          key=key,
                                          account=self.obj,
                                          autostart=autostart)
        else:
            # the normal - adding to an Object. We wait to autostart so we can differentiate
            # a failing creation from a script that immediately starts/stops.
            script = create.create_script(scriptclass,
                                          key=key,
                                          obj=self.obj,
                                          autostart=False)
        if not script:
            logger.log_err("Script %s failed to be created/started." %
                           scriptclass)
            return False
        if autostart:
            script.start()
        if not script.id:
            # this can happen if the script has repeats=1 or calls stop() in at_repeat.
            logger.log_info("Script %s started and then immediately stopped; "
                            "it could probably be a normal function." %
                            scriptclass)
        return True
Esempio n. 44
0
    def _imc_login(self, line):
        """
        Connect and identify to imc network as per the
        `self.auth_type` setting.

        Args:
            line (str): Incoming text.

        """

        if self.auth_type == "plaintext":
            # Only support Plain text passwords.
            # SERVER Sends: PW <servername> <serverpw> version=<version#> <networkname>

            logger.log_info("IMC2: AUTH< %s" % line)

            line_split = line.split(' ')
            pw_present = line_split[0] == 'PW'
            autosetup_present = line_split[0] == 'autosetup'

            if "reject" in line_split:
                auth_message = _("IMC2 server rejected connection.")
                logger.log_info(auth_message)
                return

            if pw_present:
                self.server_name = line_split[1]
                self.network_name = line_split[4]
            elif autosetup_present:
                logger.log_info(_("IMC2: Autosetup response found."))
                self.server_name = line_split[1]
                self.network_name = line_split[3]
            self.is_authenticated = True
            self.sequence = int(time())

            # Log to stdout and notify over MUDInfo.
            logger.log_info('IMC2: Authenticated to %s' % self.factory.network)

            # Ask to see what other MUDs are connected.
            self._send_packet(pck.IMC2PacketKeepAliveRequest())
            # IMC2 protocol states that KeepAliveRequests should be followed
            # up by the requester sending an IsAlive packet.
            self._send_packet(pck.IMC2PacketIsAlive())
            # Get a listing of channels.
            self._send_packet(pck.IMC2PacketIceRefresh())
Esempio n. 45
0
    def _imc_login(self, line):
        """
        Connect and identify to imc network as per the
        `self.auth_type` setting.

        Args:
            line (str): Incoming text.

        """

        if self.auth_type == "plaintext":
            # Only support Plain text passwords.
            # SERVER Sends: PW <servername> <serverpw> version=<version#> <networkname>

            logger.log_info("IMC2: AUTH< %s" % line)

            line_split = line.split(' ')
            pw_present = line_split[0] == 'PW'
            autosetup_present = line_split[0] == 'autosetup'

            if "reject" in line_split:
                auth_message = _("IMC2 server rejected connection.")
                logger.log_info(auth_message)
                return

            if pw_present:
                self.server_name = line_split[1]
                self.network_name = line_split[4]
            elif autosetup_present:
                logger.log_info(_("IMC2: Autosetup response found."))
                self.server_name = line_split[1]
                self.network_name = line_split[3]
            self.is_authenticated = True
            self.sequence = int(time())

            # Log to stdout and notify over MUDInfo.
            logger.log_info('IMC2: Authenticated to %s' % self.factory.network)

            # Ask to see what other MUDs are connected.
            self._send_packet(pck.IMC2PacketKeepAliveRequest())
            # IMC2 protocol states that KeepAliveRequests should be followed
            # up by the requester sending an IsAlive packet.
            self._send_packet(pck.IMC2PacketIsAlive())
            # Get a listing of channels.
            self._send_packet(pck.IMC2PacketIceRefresh())
Esempio n. 46
0
def parse_inlinefunc(string, strip=False, available_funcs=None, stacktrace=False, **kwargs):
    """
    Parse the incoming string.

    Args:
        string (str): The incoming string to parse.
        strip (bool, optional): Whether to strip function calls rather than
            execute them.
        available_funcs (dict, optional): Define an alternative source of functions to parse for.
            If unset, use the functions found through `settings.INLINEFUNC_MODULES`.
        stacktrace (bool, optional): If set, print the stacktrace to log.
    Kwargs:
        session (Session): This is sent to this function by Evennia when triggering
            it. It is passed to the inlinefunc.
        kwargs (any): All other kwargs are also passed on to the inlinefunc.


    """
    global _PARSING_CACHE
    usecache = False
    if not available_funcs:
        available_funcs = _INLINE_FUNCS
        usecache = True
    else:
        # make sure the default keys are available, but also allow overriding
        tmp = _DEFAULT_FUNCS.copy()
        tmp.update(available_funcs)
        available_funcs = tmp

    if usecache and string in _PARSING_CACHE:
        # stack is already cached
        stack = _PARSING_CACHE[string]
    elif not _RE_STARTTOKEN.search(string):
        # if there are no unescaped start tokens at all, return immediately.
        return string
    else:
        # no cached stack; build a new stack and continue
        stack = ParseStack()

        # process string on stack
        ncallable = 0
        nlparens = 0
        nvalid = 0

        if stacktrace:
            out = "STRING: {} =>".format(string)
            print(out)
            logger.log_info(out)

        for match in _RE_TOKEN.finditer(string):
            gdict = match.groupdict()

            if stacktrace:
                out = " MATCH: {}".format({key: val for key, val in gdict.items() if val})
                print(out)
                logger.log_info(out)

            if gdict["singlequote"]:
                stack.append(gdict["singlequote"])
            elif gdict["doublequote"]:
                stack.append(gdict["doublequote"])
            elif gdict["leftparens"]:
                # we have a left-parens inside a callable
                if ncallable:
                    nlparens += 1
                stack.append("(")
            elif gdict["end"]:
                if nlparens > 0:
                    nlparens -= 1
                    stack.append(")")
                    continue
                if ncallable <= 0:
                    stack.append(")")
                    continue
                args = []
                while stack:
                    operation = stack.pop()
                    if callable(operation):
                        if not strip:
                            stack.append((operation, [arg for arg in reversed(args)]))
                        ncallable -= 1
                        break
                    else:
                        args.append(operation)
            elif gdict["start"]:
                funcname = _RE_STARTTOKEN.match(gdict["start"]).group(1)
                try:
                    # try to fetch the matching inlinefunc from storage
                    stack.append(available_funcs[funcname])
                    nvalid += 1
                except KeyError:
                    stack.append(available_funcs["nomatch"])
                    stack.append(funcname)
                    stack.append(None)
                ncallable += 1
            elif gdict["escaped"]:
                # escaped tokens
                token = gdict["escaped"].lstrip("\\")
                stack.append(token)
            elif gdict["comma"]:
                if ncallable > 0:
                    # commas outside strings and inside a callable are
                    # used to mark argument separation - we use None
                    # in the stack to indicate such a separation.
                    stack.append(None)
                else:
                    # no callable active - just a string
                    stack.append(",")
            else:
                # the rest
                stack.append(gdict["rest"])

        if ncallable > 0:
            # this means not all inlinefuncs were complete
            return string

        if _STACK_MAXSIZE > 0 and _STACK_MAXSIZE < nvalid:
            # if stack is larger than limit, throw away parsing
            return string + available_funcs["stackfull"](*args, **kwargs)
        elif usecache:
            # cache the stack - we do this also if we don't check the cache above
            _PARSING_CACHE[string] = stack

    # run the stack recursively
    def _run_stack(item, depth=0):
        retval = item
        if isinstance(item, tuple):
            if strip:
                return ""
            else:
                func, arglist = item
                args = [""]
                for arg in arglist:
                    if arg is None:
                        # an argument-separating comma - start a new arg
                        args.append("")
                    else:
                        # all other args should merge into one string
                        args[-1] += _run_stack(arg, depth=depth + 1)
                # execute the inlinefunc at this point or strip it.
                kwargs["inlinefunc_stack_depth"] = depth
                retval = "" if strip else func(*args, **kwargs)
        return utils.to_str(retval, force_string=True)
    retval = "".join(_run_stack(item) for item in stack)
    if stacktrace:
        out = "STACK: \n{} => {}\n".format(stack, retval)
        print(out)
        logger.log_info(out)

    # execute the stack
    return retval