Exemplo n.º 1
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this object. This method is a copy of the execute_
        cmd method on the session. This is never called normally, it's only
        used when wanting specifically to let an object be the caller of a
        command. It makes use of nicks of eventual connected players as well.

        Argument:
        raw_string (string) - raw command input
        sessid (int) - optional session id to return results to

        Returns Deferred - this is an asynchronous Twisted object that will
            not fire until the command has actually finished executing. To
            overload this one needs to attach callback functions to it, with
            addCallback(function). This function will be called with an
            eventual return value from the command execution.

            This return is not used at all by Evennia by default, but might
            be useful for coders intending to implement some sort of nested
            command structure.
        """
        # nick replacement - we require full-word matching.

        # do text encoding conversion
        raw_string = to_unicode(raw_string)
        raw_string = self.nicks.nickreplace(raw_string, categories=("inputline", "channel"), include_player=True)
        return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, callertype="object", sessid=sessid)
Exemplo n.º 2
0
    def __new__(cls, *args, **kwargs):
        """
        When creating a new ANSIString, you may use a custom parser that has
        the same attributes as the standard one, and you may declare the
        string to be handled as already decoded. It is important not to double
        decode strings, as escapes can only be respected once.
        """
        string = args[0]
        if not isinstance(string, basestring):
            string = to_str(string, force_string=True)
        parser = kwargs.get('parser', ANSI_PARSER)
        decoded = kwargs.get('decoded', False) or hasattr(string, '_raw_string')
        if not decoded:
            # Completely new ANSI String
            clean_string = to_unicode(parser.parse_ansi(string, strip_ansi=True))
            string = parser.parse_ansi(string)
        elif hasattr(string, '_clean_string'):
            # It's already an ANSIString
            clean_string = string._clean_string
            string = string._raw_string
        else:
            # It's a string that has been pre-ansi decoded.
            clean_string = parser.strip_raw_codes(string)

        if not isinstance(string, unicode):
            string = string.decode('utf-8')
        else:
            # Do this to prevent recursive ANSIStrings.
            string = unicode(string)
        ansi_string = super(ANSIString, cls).__new__(ANSIString, to_str(clean_string), "utf-8")
        ansi_string._raw_string = string
        ansi_string._clean_string = clean_string
        return ansi_string
Exemplo n.º 3
0
    def reload(self, filename=None, form=None, **kwargs):
        """
        Creates the form from a stored file name
        """
        # clean kwargs (these cannot be overridden)
        kwargs.pop("enforce_size", None)
        kwargs.pop("width", None)
        kwargs.pop("height", None)

        if form or self.input_form_dict:
            datadict = form if form else self.input_form_dict
            self.input_form_dict = datadict
        elif filename or self.filename:
            filename = filename if filename else self.filename
            datadict = all_from_module(filename)
            self.filename = filename
        else:
            datadict = {}

        cellchar = to_str(datadict.get("FORMCHAR", "x"))
        self.cellchar = to_str(cellchar[0] if len(cellchar) > 1 else cellchar)
        tablechar = datadict.get("TABLECHAR", "c")
        self.tablechar = tablechar[0] if len(tablechar) > 1 else tablechar

        # split into a list of list of lines. Form can be indexed with form[iy][ix]
        self.raw_form = to_unicode(datadict.get("FORM", "")).split("\n")
        # strip first line
        self.raw_form = self.raw_form[1:] if self.raw_form else self.raw_form

        self.options.update(kwargs)

        # parse and replace
        self.mapping = self._parse_rectangles(self.cellchar, self.tablechar, self.raw_form, **kwargs)
        self.form = self._populate_form(self.raw_form, self.mapping)
Exemplo n.º 4
0
 def get_objs_with_db_property_value(self,
                                     property_name,
                                     property_value,
                                     candidates=None,
                                     typeclasses=None):
     """
     Returns all objects having a given db field property.
     candidates - list of objects to search
     typeclasses - list of typeclass-path strings to restrict matches with
     """
     if isinstance(property_value, basestring):
         property_value = to_unicode(property_value)
     if isinstance(property_name, basestring):
         if not property_name.startswith('db_'):
             property_name = "db_%s" % property_name
     if hasattr(property_value, 'dbobj'):
         property_value = property_value.dbobj
     querykwargs = {property_name: property_value}
     cand_restriction = candidates != None and Q(
         pk__in=[_GA(obj, "id")
                 for obj in make_iter(candidates) if obj]) or Q()
     type_restriction = typeclasses and Q(
         db_typeclass_path__in=make_iter(typeclasses)) or Q()
     try:
         return list(
             self.filter(cand_restriction & type_restriction
                         & Q(**querykwargs)))
     except exceptions.FieldError:
         return []
     except ValueError:
         from src.utils import logger
         logger.log_errmsg(
             "The property '%s' does not support search criteria of the type %s."
             % (property_name, type(property_value)))
         return []
Exemplo n.º 5
0
    def reload(self, filename=None, form=None, **kwargs):
        """
        Creates the form from a stored file name
        """
        # clean kwargs (these cannot be overridden)
        kwargs.pop("enforce_size", None)
        kwargs.pop("width", None)
        kwargs.pop("height", None)

        if form or self.input_form_dict:
            datadict = form if form else self.input_form_dict
            self.input_form_dict = datadict
        elif filename or self.filename:
            filename = filename if filename else self.filename
            datadict = all_from_module(filename)
            self.filename = filename
        else:
            datadict = {}

        cellchar = to_str(datadict.get("FORMCHAR", "x"))
        self.cellchar = to_str(cellchar[0] if len(cellchar) > 1 else cellchar)
        tablechar = datadict.get("TABLECHAR", "c")
        self.tablechar = tablechar[0] if len(tablechar) > 1 else tablechar

        # split into a list of list of lines. Form can be indexed with form[iy][ix]
        self.raw_form = _to_ansi(to_unicode(datadict.get("FORM", "")).split("\n"))
        # strip first line
        self.raw_form = self.raw_form[1:] if self.raw_form else self.raw_form

        self.options.update(kwargs)

        # parse and replace
        self.mapping = self._parse_rectangles(self.cellchar, self.tablechar, self.raw_form, **kwargs)
        self.form = self._populate_form(self.raw_form, self.mapping)
Exemplo n.º 6
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this player. This method is never called normally,
        but only when the player object itself is supposed to execute the
        command. It does not take nicks on eventual puppets into account.

        raw_string - raw command input coming from the command line.
        """
        # nick replacement - we require full-word matching.

        raw_string = utils.to_unicode(raw_string)

        raw_list = raw_string.split(None)
        raw_list = [" ".join(raw_list[:i + 1]) for i in range(len(raw_list)) if raw_list[:i + 1]]
        # get the nick replacement data directly from the database to be
        # able to use db_category__in
        nicks = self.db_attributes.filter(db_category__in=("nick_inputline", "nick_channel"))
        for nick in nicks:
            if nick.db_key in raw_list:
                raw_string = raw_string.replace(nick.db_key, nick.db_strvalue, 1)
                break
        if not sessid and _MULTISESSION_MODE in (0, 1):
            # in this case, we should either have only one sessid, or the sessid
            # should not matter (since the return goes to all of them we can
            # just use the first one as the source)
            sessid = self.get_all_sessions()[0].sessid
        return cmdhandler.cmdhandler(self.typeclass, raw_string,
                                     callertype="player", sessid=sessid)
Exemplo n.º 7
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this object. This method is a copy of the execute_
        cmd method on the session. This is never called normally, it's only
        used when wanting specifically to let an object be the caller of a
        command. It makes use of nicks of eventual connected players as well.

        Argument:
        raw_string (string) - raw command input
        sessid (int) - optional session id to return results to

        Returns Deferred - this is an asynchronous Twisted object that will
            not fire until the command has actually finished executing. To
            overload this one needs to attach callback functions to it, with
            addCallback(function). This function will be called with an
            eventual return value from the command execution.

            This return is not used at all by Evennia by default, but might
            be useful for coders intending to implement some sort of nested
            command structure.
        """
        # nick replacement - we require full-word matching.

        # do text encoding conversion
        raw_string = to_unicode(raw_string)
        raw_string = self.nicks.nickreplace(raw_string,
                                            categories=("inputline",
                                                        "channel"),
                                            include_player=True)
        return cmdhandler.cmdhandler(_GA(self, "typeclass"),
                                     raw_string,
                                     callertype="object",
                                     sessid=sessid)
Exemplo n.º 8
0
    def execute_cmd(self, raw_string, sessid=None, **kwargs):
        """
        Do something as this player. This method is never called normally,
        but only when the player object itself is supposed to execute the
        command. It takes player nicks into account, but not nicks of
        eventual puppets.

        raw_string - raw command input coming from the command line.
        sessid - the optional session id to be responsible for the command-send
        **kwargs - other keyword arguments will be added to the found command
                   object instace as variables before it executes. This is
                   unused by default Evennia but may be used to set flags and
                   change operating paramaters for commands at run-time.
        """
        raw_string = utils.to_unicode(raw_string)
        raw_string = self.nicks.nickreplace(raw_string,
                          categories=("inputline", "channel"), include_player=False)
        if not sessid and _MULTISESSION_MODE in (0, 1):
            # in this case, we should either have only one sessid, or the sessid
            # should not matter (since the return goes to all of them we can
            # just use the first one as the source)
            try:
                sessid = self.get_all_sessions()[0].sessid
            except IndexError:
                # this can happen for bots
                sessid = None
        return cmdhandler.cmdhandler(self.typeclass, raw_string,
                                     callertype="player", sessid=sessid, **kwargs)
Exemplo n.º 9
0
 def data_out(self, session, text="", **kwargs):
     """
     Sending data Server -> Portal
     """
     text = text and to_str(to_unicode(text), encoding=session.encoding)
     self.server.amp_protocol.call_remote_MsgServer2Portal(
         sessid=session.sessid, msg=text, data=kwargs)
Exemplo n.º 10
0
    def get_objs_with_db_property_value(self, property_name, property_value, candidates=None, typeclasses=None):
        """
        Returns all objects having a given db field property.
        candidates - list of objects to search
        typeclasses - list of typeclass-path strings to restrict matches with
        """
        if isinstance(property_value, basestring):
            property_value = to_unicode(property_value)
        if isinstance(property_name, basestring):
            if not property_name.startswith("db_"):
                property_name = "db_%s" % property_name
        if hasattr(property_value, "dbobj"):
            property_value = property_value.dbobj
        querykwargs = {property_name: property_value}
        cand_restriction = (
            candidates != None and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
        )
        type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q()
        try:
            return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs)))
        except exceptions.FieldError:
            return []
        except ValueError:
            from src.utils import logger

            logger.log_errmsg(
                "The property '%s' does not support search criteria of the type %s."
                % (property_name, type(property_value))
            )
            return []
Exemplo n.º 11
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this player. This method is never called normally,
        but only when the player object itself is supposed to execute the
        command. It takes player nicks into account, but not nicks of
        eventual puppets.

        raw_string - raw command input coming from the command line.
        """
        raw_string = utils.to_unicode(raw_string)
        raw_string = self.nicks.nickreplace(raw_string,
                                            categories=("inputline",
                                                        "channel"),
                                            include_player=False)
        if not sessid and _MULTISESSION_MODE in (0, 1):
            # in this case, we should either have only one sessid, or the sessid
            # should not matter (since the return goes to all of them we can
            # just use the first one as the source)
            try:
                sessid = self.get_all_sessions()[0].sessid
            except IndexError:
                # this can happen for bots
                sessid = None
        return cmdhandler.cmdhandler(self.typeclass,
                                     raw_string,
                                     callertype="player",
                                     sessid=sessid)
Exemplo n.º 12
0
 def get_object_with_player(self, ostring, exact=True, candidates=None):
     """
     Search for an object based on its player's name or dbref.
     This search
     is sometimes initiated by appending a * to the beginning of
     the search criterion (e.g. in local_and_global_search).
     search_string:  (string) The name or dbref to search for.
     """
     ostring = to_unicode(ostring).lstrip("*")
     # simplest case - search by dbref
     dbref = self.dbref(ostring)
     if dbref:
         return dbref
     # not a dbref. Search by name.
     cand_restriction = (
         candidates != None and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
     )
     if exact:
         return self.filter(cand_restriction & Q(db_player__username__iexact=ostring))
     else:  # fuzzy matching
         ply_cands = self.filter(cand_restriction & Q(playerdb__username__istartswith=ostring)).values_list(
             "db_key", flat=True
         )
         if candidates:
             index_matches = string_partial_matching(ply_cands, ostring, ret_index=True)
             return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches]
         else:
             return string_partial_matching(ply_cands, ostring, ret_index=False)
Exemplo n.º 13
0
    def execute_cmd(self, raw_string):
        """
        Do something as this object. This command transparently
        lets its typeclass execute the command. Evennia also calls
        this method whenever the player sends a command on the command line.

        Argument:
        raw_string (string) - raw command input

        Returns Deferred - this is an asynchronous Twisted object that will
            not fire until the command has actually finished executing. To overload
            this one needs to attach callback functions to it, with addCallback(function).
            This function will be called with an eventual return value from the command
            execution.

            This return is not used at all by Evennia by default, but might be useful
            for coders intending to implement some sort of nested command structure.
        """
        # nick replacement - we require full-word matching.

        # do text encoding conversion
        raw_string = to_unicode(raw_string)

        raw_list = raw_string.split(None)
        raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
        nicks = ObjectNick.objects.filter(db_obj=self, db_type__in=("inputline", "channel"))
        if self.has_player:
            nicks = list(nicks) + list(PlayerNick.objects.filter(db_obj=self.db_player, db_type__in=("inputline","channel")))
        for nick in nicks:
            if nick.db_nick in raw_list:
                raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
                break
        return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string)
Exemplo n.º 14
0
 def data_out(self, session, text="", **kwargs):
     """
     Sending data Server -> Portal
     """
     text = text and to_str(to_unicode(text), encoding=session.encoding)
     self.server.amp_protocol.call_remote_MsgServer2Portal(sessid=session.sessid,
                                                           msg=text,
                                                           data=kwargs)
Exemplo n.º 15
0
def _to_ansi(obj, regexable=False):
    "convert to ANSIString"
    if isinstance(obj, dict):
        return dict((key, _to_ansi(value, regexable=regexable)) for key, value in obj.items())
    elif hasattr(obj, "__iter__"):
        return [_to_ansi(o) for o in obj]
    else:
        return ANSIString(to_unicode(obj), regexable=regexable)
Exemplo n.º 16
0
 def data_in(self, sessid, text="", **kwargs):
     """
     Data Portal -> Server
     """
     session = self.sessions.get(sessid, None)
     if session:
         text = text and to_unicode(strip_control_sequences(text), encoding=session.encoding)
         session.data_in(text=text, **kwargs)
Exemplo n.º 17
0
    def __new__(cls, *args, **kwargs):
        """
        When creating a new ANSIString, you may use a custom parser that has
        the same attributes as the standard one, and you may declare the
        string to be handled as already decoded. It is important not to double
        decode strings, as escapes can only be respected once.

        Internally, ANSIString can also passes itself precached code/character
        indexes and clean strings to avoid doing extra work when combining
        ANSIStrings.
        """
        string = args[0]
        if not isinstance(string, basestring):
            string = to_str(string, force_string=True)
        parser = kwargs.get('parser', ANSI_PARSER)
        decoded = kwargs.get('decoded', False) or hasattr(
            string, '_raw_string')
        code_indexes = kwargs.pop('code_indexes', None)
        char_indexes = kwargs.pop('char_indexes', None)
        clean_string = kwargs.pop('clean_string', None)
        # All True, or All False, not just one.
        checks = map(lambda x: x is None,
                     [code_indexes, char_indexes, clean_string])
        if not len(set(checks)) == 1:
            raise ValueError("You must specify code_indexes, char_indexes, "
                             "and clean_string together, or not at all.")
        if not all(checks):
            decoded = True
        if not decoded:
            # Completely new ANSI String
            clean_string = to_unicode(
                parser.parse_ansi(string, strip_ansi=True))
            string = parser.parse_ansi(string)
        elif clean_string is not None:
            # We have an explicit clean string.
            pass
        elif hasattr(string, '_clean_string'):
            # It's already an ANSIString
            clean_string = string._clean_string
            code_indexes = string._code_indexes
            char_indexes = string._char_indexes
            string = string._raw_string
        else:
            # It's a string that has been pre-ansi decoded.
            clean_string = parser.strip_raw_codes(string)

        if not isinstance(string, unicode):
            string = string.decode('utf-8')

        ansi_string = super(ANSIString, cls).__new__(ANSIString,
                                                     to_str(clean_string),
                                                     "utf-8")
        ansi_string._raw_string = string
        ansi_string._clean_string = clean_string
        ansi_string._code_indexes = code_indexes
        ansi_string._char_indexes = char_indexes
        return ansi_string
Exemplo n.º 18
0
 def data_in(self, sessid, text="", **kwargs):
     """
     Data Portal -> Server
     """
     session = self.sessions.get(sessid, None)
     if session:
         text = text and to_unicode(strip_control_sequences(text),
                                    encoding=session.encoding)
         session.data_in(text=text, **kwargs)
 def forwards(self, orm):
     "Write your forwards methods here."
     for attr in orm.ScriptAttribute.objects.all():
         try:
             # repack attr into new format, and reimport
             val = pickle.loads(to_str(attr.db_value))
             attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
             attr.save()
         except TypeError, RuntimeError:
             pass
    def forwards(self, orm):
        "Write your forwards methods here."

        for attr in orm.ObjAttribute.objects.all():
            # repack attr into new format, and reimport
            try:
                val = pickle.loads(to_str(attr.db_value))
                attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
                attr.save()
            except TypeError, RuntimeError:
                pass
Exemplo n.º 21
0
 def get_objs_with_db_property_value(self, property_name, property_value, candidates=None):
     """
     Returns all objects having a given db field property
     """
     if isinstance(property_value, basestring):
         property_value = to_unicode(property_value)
     property_name = "db_%s" % property_name.lstrip('db_')
     cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q()
     try:
         return self.filter(cand_restriction & Q(property_name=property_value))
     except exceptions.FieldError:
         return []
Exemplo n.º 22
0
    def __new__(cls, *args, **kwargs):
        """
        When creating a new ANSIString, you may use a custom parser that has
        the same attributes as the standard one, and you may declare the
        string to be handled as already decoded. It is important not to double
        decode strings, as escapes can only be respected once.

        Internally, ANSIString can also passes itself precached code/character
        indexes and clean strings to avoid doing extra work when combining
        ANSIStrings.
        """
        string = args[0]
        if not isinstance(string, basestring):
            string = to_str(string, force_string=True)
        parser = kwargs.get('parser', ANSI_PARSER)
        decoded = kwargs.get('decoded', False) or hasattr(string, '_raw_string')
        code_indexes = kwargs.pop('code_indexes', None)
        char_indexes = kwargs.pop('char_indexes', None)
        clean_string = kwargs.pop('clean_string', None)
        # All True, or All False, not just one.
        checks = map(lambda x: x is None, [code_indexes, char_indexes, clean_string])
        if not len(set(checks)) == 1:
            raise ValueError("You must specify code_indexes, char_indexes, "
                             "and clean_string together, or not at all.")
        if not all(checks):
            decoded = True
        if not decoded:
            # Completely new ANSI String
            clean_string = to_unicode(parser.parse_ansi(string, strip_ansi=True))
            string = parser.parse_ansi(string)
        elif clean_string is not None:
            # We have an explicit clean string.
            pass
        elif hasattr(string, '_clean_string'):
            # It's already an ANSIString
            clean_string = string._clean_string
            code_indexes = string._code_indexes
            char_indexes = string._char_indexes
            string = string._raw_string
        else:
            # It's a string that has been pre-ansi decoded.
            clean_string = parser.strip_raw_codes(string)

        if not isinstance(string, unicode):
            string = string.decode('utf-8')

        ansi_string = super(ANSIString, cls).__new__(ANSIString, to_str(clean_string), "utf-8")
        ansi_string._raw_string = string
        ansi_string._clean_string = clean_string
        ansi_string._code_indexes = code_indexes
        ansi_string._char_indexes = char_indexes
        return ansi_string
Exemplo n.º 23
0
 def forwards(self, orm):
     "Write your forwards methods here."
     for attr in orm['players.PlayerAttribute'].objects.all():
         try:
             # repack attr into new format, and reimport
             val = pickle.loads(to_str(attr.db_value))
             if hasattr(val, '__iter__'):
                 val = ("iter", val)
             elif type(val) == PackedDBobject:
                 val = ("dbobj", val)
             else:
                 val = ("simple", val)
             attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
             attr.save()
         except TypeError, RuntimeError:
             pass
 def forwards(self, orm):
     "Write your forwards methods here."
     for attr in orm.PlayerAttribute.objects.all():
         try:
             # repack attr into new format, and reimport
             val = pickle.loads(to_str(attr.db_value))
             if hasattr(val, '__iter__'):
                 val = ("iter", val)
             elif type(val) == PackedDBobject:
                 val = ("dbobj", val)
             else:
                 val = ("simple", val)
             attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
             attr.save()
         except TypeError, RuntimeError:
             pass
Exemplo n.º 25
0
    def execute_cmd(self, raw_string):
        """
        Do something as this player. This command transparently
        lets its typeclass execute the command.
        raw_string - raw command input coming from the command line.
        """
        # nick replacement - we require full-word matching.

        raw_string = utils.to_unicode(raw_string)

        raw_list = raw_string.split(None)
        raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
        for nick in PlayerNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")):
            if nick.db_nick in raw_list:
                raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
                break
        return cmdhandler.cmdhandler(self.typeclass, raw_string)
Exemplo n.º 26
0
    def data_in(self, text=None, **kwargs):
        """
        Send User->Evennia. This will in effect
        execute a command string on the server.

        Especially handled keywords:

        oob - this should hold a dictionary of oob command calls from
              the oob-supporting protocol.
        """
        if text:
            # this is treated as a command input
            text = to_unicode(text)
            # handle the 'idle' command
            if text.strip() == IDLE_COMMAND:
                self.update_session_counters(idle=True)
                return
            if self.player:
                # nick replacement
                puppet = self.player.get_puppet(self.sessid)
                if puppet:
                    text = puppet.nicks.nickreplace(text,
                                                    categories=("inputline",
                                                                "channel"),
                                                    include_player=True)
                else:
                    text = self.player.nicks.nickreplace(
                        text,
                        categories=("inputline", "channels"),
                        include_player=False)
            cmdhandler.cmdhandler(self,
                                  text,
                                  callertype="session",
                                  sessid=self.sessid)
            self.update_session_counters()
        if "oob" in kwargs:
            # handle oob instructions
            global _OOB_HANDLER
            if not _OOB_HANDLER:
                from src.server.oobhandler import OOB_HANDLER as _OOB_HANDLER
            oobstruct = self.sessionhandler.oobstruct_parser(
                kwargs.pop("oob", None))
            #print "session.data_in: oobstruct:",oobstruct
            for (funcname, args, kwargs) in oobstruct:
                if funcname:
                    _OOB_HANDLER.execute_cmd(self, funcname, *args, **kwargs)
Exemplo n.º 27
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this player. This command transparently
        lets its typeclass execute the command.
        raw_string - raw command input coming from the command line.
        """
        # nick replacement - we require full-word matching.

        raw_string = utils.to_unicode(raw_string)

        raw_list = raw_string.split(None)
        raw_list = [" ".join(raw_list[: i + 1]) for i in range(len(raw_list)) if raw_list[: i + 1]]
        for nick in PlayerNick.objects.filter(db_obj=self, db_type__in=("inputline", "channel")):
            if nick.db_nick in raw_list:
                raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
                break
        if not sessid and _MULTISESSION_MODE in (0, 1):
            # in this case, we should either have only one sessid, or the sessid
            # should not matter (since the return goes to all of them we can just
            # use the first one as the source)
            sessid = self.get_all_sessions()[0].sessid
        return cmdhandler.cmdhandler(self.typeclass, raw_string, sessid=sessid)
Exemplo n.º 28
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this object. This method is a copy of the execute_
        cmd method on the session. This is never called normally, it's only
        used when wanting specifically to let an object be the caller of a
        command. It makes use of nicks of eventual connected players as well.

        Argument:
        raw_string (string) - raw command input
        sessid (int) - optional session id to return results to

        Returns Deferred - this is an asynchronous Twisted object that will
            not fire until the command has actually finished executing. To
            overload this one needs to attach callback functions to it, with
            addCallback(function). This function will be called with an
            eventual return value from the command execution.

            This return is not used at all by Evennia by default, but might
            be useful for coders intending to implement some sort of nested
            command structure.
        """
        # nick replacement - we require full-word matching.

        # do text encoding conversion
        raw_string = to_unicode(raw_string)

        raw_list = raw_string.split(None)
        raw_list = [" ".join(raw_list[:i + 1]) for i in range(len(raw_list))
                                                        if raw_list[:i + 1]]
        # fetch the nick data efficiently
        nicks = self.db_attributes.filter(db_category__in=("nick_inputline", "nick_channel"))
        if self.has_player:
            # attach player nicks as well, but after the object-level nicks
            nicks = list(nicks) + list(self.player.db_attributes.filter(db_category__in=("nick_inputline", "nick_channel")))
        for nick in nicks:
            if nick.db_key in raw_list:
                raw_string = raw_string.replace(nick.db_key, nick.db_strvalue, 1)
                break
        return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, callertype="object", sessid=sessid)
Exemplo n.º 29
0
    def data_in(self, text=None, **kwargs):
        """
        Send User->Evennia. This will in effect
        execute a command string on the server.

        Especially handled keywords:

        oob - this should hold a dictionary of oob command calls from
              the oob-supporting protocol.
        """
        if text:
            # this is treated as a command input
            text = to_unicode(text)
            # handle the 'idle' command
            if text.strip() == IDLE_COMMAND:
                self.update_session_counters(idle=True)
                return
            if self.player:
                # nick replacement
                puppet = self.player.get_puppet(self.sessid)
                if puppet:
                    text = puppet.nicks.nickreplace(text, categories=("inputline", "channel"), include_player=True)
                else:
                    text = self.player.nicks.nickreplace(
                        text, categories=("inputline", "channels"), include_player=False
                    )
            cmdhandler(self, text, callertype="session", sessid=self.sessid)
            self.update_session_counters()
        if "oob" in kwargs:
            # handle oob instructions
            global _OOB_HANDLER
            if not _OOB_HANDLER:
                from src.server.oobhandler import OOB_HANDLER as _OOB_HANDLER
            oobstruct = self.sessionhandler.oobstruct_parser(kwargs.pop("oob", None))
            # print "session.data_in: oobstruct:",oobstruct
            for (funcname, args, kwargs) in oobstruct:
                if funcname:
                    _OOB_HANDLER.execute_cmd(self, funcname, *args, **kwargs)
Exemplo n.º 30
0
    def execute_cmd(self, raw_string, sessid=None):
        """
        Do something as this player. This method is never called normally,
        but only when the player object itself is supposed to execute the
        command. It takes player nicks into account, but not nicks of
        eventual puppets.

        raw_string - raw command input coming from the command line.
        """
        raw_string = utils.to_unicode(raw_string)
        raw_string = self.nicks.nickreplace(raw_string,
                          categories=("inputline", "channel"), include_player=False)
        if not sessid and _MULTISESSION_MODE in (0, 1):
            # in this case, we should either have only one sessid, or the sessid
            # should not matter (since the return goes to all of them we can
            # just use the first one as the source)
            try:
                sessid = self.get_all_sessions()[0].sessid
            except IndexError:
                # this can happen for bots
                sessid = None
        return cmdhandler.cmdhandler(self.typeclass, raw_string,
                                     callertype="player", sessid=sessid)
Exemplo n.º 31
0
    def __new__(cls, *args, **kwargs):
        """
        When creating a new ANSIString, you may use a custom parser that has
        the same attributes as the standard one, and you may declare the
        string to be handled as already decoded. It is important not to double
        decode strings, as escapes can only be respected once.
        """
        string = args[0]
        if not isinstance(string, basestring):
            string = to_str(string, force_string=True)
        parser = kwargs.get('parser', ANSI_PARSER)
        decoded = kwargs.get('decoded', False) or hasattr(
            string, '_raw_string')
        if not decoded:
            # Completely new ANSI String
            clean_string = to_unicode(
                parser.parse_ansi(string, strip_ansi=True))
            string = parser.parse_ansi(string)
        elif hasattr(string, '_clean_string'):
            # It's already an ANSIString
            clean_string = string._clean_string
            string = string._raw_string
        else:
            # It's a string that has been pre-ansi decoded.
            clean_string = parser.strip_raw_codes(string)

        if not isinstance(string, unicode):
            string = string.decode('utf-8')
        else:
            # Do this to prevent recursive ANSIStrings.
            string = unicode(string)
        ansi_string = super(ANSIString, cls).__new__(ANSIString,
                                                     to_str(clean_string),
                                                     "utf-8")
        ansi_string._raw_string = string
        ansi_string._clean_string = clean_string
        return ansi_string
Exemplo n.º 32
0
 def get_object_with_player(self, ostring, exact=True, candidates=None):
     """
     Search for an object based on its player's name or dbref.
     This search
     is sometimes initiated by appending a * to the beginning of
     the search criterion (e.g. in local_and_global_search).
     search_string:  (string) The name or dbref to search for.
     """
     ostring = to_unicode(ostring).lstrip('*')
     # simplest case - search by dbref
     dbref = self.dbref(ostring)
     if dbref:
         return dbref
     # not a dbref. Search by name.
     cand_restriction = candidates != None and Q(
         pk__in=[_GA(obj, "id")
                 for obj in make_iter(candidates) if obj]) or Q()
     if exact:
         return self.filter(cand_restriction
                            & Q(db_player__username__iexact=ostring))
     else:  # fuzzy matching
         ply_cands = self.filter(cand_restriction & Q(
             playerdb__username__istartswith=ostring)).values_list(
                 "db_key", flat=True)
         if candidates:
             index_matches = string_partial_matching(ply_cands,
                                                     ostring,
                                                     ret_index=True)
             return [
                 obj for ind, obj in enumerate(make_iter(candidates))
                 if ind in index_matches
             ]
         else:
             return string_partial_matching(ply_cands,
                                            ostring,
                                            ret_index=False)
Exemplo n.º 33
0
Custom manager for Objects.
"""
try: import cPickle as pickle
except ImportError: import pickle
from django.db.models import Q
from django.conf import settings
#from django.contrib.auth.models import User
from django.db.models.fields import exceptions
from src.typeclasses.managers import TypedObjectManager
from src.typeclasses.managers import returns_typeclass, returns_typeclass_list
from src.utils import utils
from src.utils.utils import to_unicode, make_iter, string_partial_matching, to_str

__all__ = ("ObjectManager",)
_GA = object.__getattribute__
_DUMPS = lambda inp: to_unicode(pickle.dumps(inp))

# Try to use a custom way to parse id-tagged multimatches.

_AT_MULTIMATCH_INPUT = utils.variable_from_module(*settings.SEARCH_AT_MULTIMATCH_INPUT.rsplit('.', 1))

class ObjectManager(TypedObjectManager):
    """
    This ObjectManager implementes methods for searching
    and manipulating Objects directly from the database.

    Evennia-specific search methods (will return Typeclasses or
    lists of Typeclasses, whereas Django-general methods will return
    Querysets or database objects).

    dbref (converter)
Exemplo n.º 34
0
def create_object(typeclass=None, key=None, location=None,
                  home=None, permissions=None, locks=None,
                  aliases=None, destination=None, report_to=None, nohome=False):
    """
    Create a new in-game object. Any game object is a combination
    of a database object that stores data persistently to
    the database, and a typeclass, which on-the-fly 'decorates'
    the database object into whataver different type of object
    it is supposed to be in the game.

    See src.objects.managers for methods to manipulate existing objects
    in the database. src.objects.objects holds the base typeclasses
    and src.objects.models hold the database model.

    report_to is an optional object for reporting errors to in string form.
              If report_to is not set, errors will be raised as en Exception
              containing the error message. If set, this method will return
              None upon errors.
    nohome - this allows the creation of objects without a default home location;
             this only used when creating default location itself or during unittests
    """
    global _Object, _ObjectDB
    if not _Object:
        from src.objects.objects import Object as _Object
    if not _ObjectDB:
        from src.objects.models import ObjectDB as _ObjectDB

    # input validation

    if not typeclass:
        typeclass = settings.BASE_OBJECT_TYPECLASS
    elif isinstance(typeclass, _ObjectDB):
        # this is already an objectdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Object) or utils.inherits_from(typeclass, _Object):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path

    # handle eventual #dbref input
    location = handle_dbref(location, _ObjectDB)
    home = handle_dbref(home, _ObjectDB)
    destination = handle_dbref(destination, _ObjectDB)
    report_to = handle_dbref(report_to, _ObjectDB)

    # create new database object
    new_db_object = _ObjectDB()

    # assign the typeclass
    typeclass = utils.to_unicode(typeclass)
    new_db_object.typeclass_path = typeclass

    # the name/key is often set later in the typeclass. This
    # is set here as a failsafe.
    if key:
        new_db_object.key = key
    else:
        new_db_object.key = "#%i" % new_db_object.dbid

    # this will either load the typeclass or the default one
    new_object = new_db_object.typeclass

    if not _GA(new_object, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        SharedMemoryModel.delete(new_db_object)
        if report_to:
            _GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_object.key, typeclass,
                                                                 _GA(new_db_object, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_object, "typeclass_last_errmsg"))

    # from now on we can use the typeclass object
    # as if it was the database object.

    new_object.destination = destination

    # call the hook method. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.
    new_object.basetype_setup()  # setup the basics of Exits, Characters etc.
    new_object.at_object_creation()

    # custom-given perms/locks overwrite hooks
    if permissions:
        new_object.permissions.add(permissions)
    if locks:
        new_object.locks.add(locks)
    if aliases:
        new_object.aliases.add(aliases)

    if home:
        new_object.home = home
    else:
        # we shouldn't need to handle dbref here (home handler should fix it), but some have
        # reported issues here (issue 446).
        try:
            new_object.home = handle_dbref(settings.DEFAULT_HOME, _ObjectDB) if not nohome else None
        except _ObjectDB.DoesNotExist:
            raise _ObjectDB.DoesNotExist("settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed." %
                                         settings.DEFAULT_HOME)

    # perform a move_to in order to display eventual messages.
    if location:
        new_object.move_to(location, quiet=True)
    else:
        # rooms would have location=None.
        new_object.location = None

    # post-hook setup (mainly used by Exits)
    new_object.basetype_posthook_setup()

    new_object.save()
    return new_object
Exemplo n.º 35
0
def create_player(key, email, password,
                  typeclass=None,
                  is_superuser=False,
                  locks=None, permissions=None,
                  report_to=None):

    """
    This creates a new player.

    key - the player's name. This should be unique.
    email - email on valid [email protected] form.
    password - password in cleartext
    is_superuser - wether or not this player is to be a superuser
    locks - lockstring
    permission - list of permissions
    report_to - an object with a msg() method to report errors to. If
                not given, errors will be logged.

    Will return the Player-typeclass or None/raise Exception if the
    Typeclass given failed to load.

    Concerning is_superuser:
     Usually only the server admin should need to be superuser, all
     other access levels can be handled with more fine-grained
     permissions or groups. A superuser bypasses all lock checking
     operations and is thus not suitable for play-testing the game.

    """
    global _PlayerDB, _Player
    if not _PlayerDB:
        from src.players.models import PlayerDB as _PlayerDB
    if not _Player:
        from src.players.player import Player as _Player

    if not email:
        email = "*****@*****.**"
    if _PlayerDB.objects.filter(username__iexact=key):
        raise ValueError("A Player with the name '%s' already exists." % key)

    # this handles a given dbref-relocate to a player.
    report_to = handle_dbref(report_to, _PlayerDB)

    try:

        # create the correct Player object
        if is_superuser:
            new_db_player = _PlayerDB.objects.create_superuser(key, email, password)
        else:
            new_db_player = _PlayerDB.objects.create_user(key, email, password)

        if not typeclass:
            typeclass = settings.BASE_PLAYER_TYPECLASS
        elif isinstance(typeclass, _PlayerDB):
            # this is an PlayerDB instance, extract its typeclass path
            typeclass = typeclass.typeclass.path
        elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player):
            # this is Player object typeclass, extract its path
            typeclass = typeclass.path

        # assign the typeclass
        typeclass = utils.to_unicode(typeclass)
        new_db_player.typeclass_path = typeclass

        # this will either load the typeclass or the default one
        new_player = new_db_player.typeclass

        if not _GA(new_db_player, "is_typeclass")(typeclass, exact=True):
            # this will fail if we gave a typeclass as input
            # and it still gave us a default
            SharedMemoryModel.delete(new_db_player)
            if report_to:
                _GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_player.key, typeclass,
                                                                  _GA(new_db_player, "typeclass_last_errmsg")))
                return None
            else:
                raise Exception(_GA(new_db_player, "typeclass_last_errmsg"))

        new_player.basetype_setup()  # setup the basic locks and cmdset
        # call hook method (may override default permissions)
        new_player.at_player_creation()

        # custom given arguments potentially overrides the hook
        if permissions:
            new_player.permissions.add(permissions)
        elif not new_player.permissions:
            new_player.permissions.add(settings.PERMISSION_PLAYER_DEFAULT)
        if locks:
            new_player.locks.add(locks)
        return new_player

    except Exception:
        # a failure in creating the player; we try to clean
        # up as much as we can
        logger.log_trace()
        try:
            new_player.delete()
        except Exception:
            pass
        try:
            del new_player
        except Exception:
            pass
        raise
Exemplo n.º 36
0
def create_script(typeclass, key=None, obj=None, player=None, locks=None,
                  interval=None, start_delay=None, repeats=None,
                  persistent=None, autostart=True, report_to=None):
    """
    Create a new script. All scripts are a combination
    of a database object that communicates with the
    database, and an typeclass that 'decorates' the
    database object into being different types of scripts.
    It's behaviour is similar to the game objects except
    scripts has a time component and are more limited in
    scope.

    Argument 'typeclass' can be either an actual
    typeclass object or a python path to such an object.
    Only set key here if you want a unique name for this
    particular script (set it in config to give
    same key to all scripts of the same type). Set obj
    to tie this script to a particular object.

    See src.scripts.manager for methods to manipulate existing
    scripts in the database.

    report_to is an obtional object to receive error messages.
              If report_to is not set, an Exception with the
              error will be raised. If set, this method will
              return None upon errors.
    """
    global _Script, _ScriptDB
    if not _Script:
        from src.scripts.scripts import Script as _Script
    if not _ScriptDB:
        from src.scripts.models import ScriptDB as _ScriptDB

    if not typeclass:
        typeclass = settings.BASE_SCRIPT_TYPECLASS
    elif isinstance(typeclass, _ScriptDB):
        # this is already an scriptdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Script) or utils.inherits_from(typeclass, _Script):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path

    # create new database script
    new_db_script = _ScriptDB()

    # assign the typeclass
    typeclass = utils.to_unicode(typeclass)
    new_db_script.typeclass_path = typeclass

    # the name/key is often set later in the typeclass. This
    # is set here as a failsafe.
    if key:
        new_db_script.key = key
    else:
        new_db_script.key = "#%i" % new_db_script.id

    # this will either load the typeclass or the default one
    new_script = new_db_script.typeclass

    if not _GA(new_db_script, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        SharedMemoryModel.delete(new_db_script)
        if report_to:
            _GA(report_to, "msg")("Error creating %s (%s): %s" % (new_db_script.key, typeclass,
                                                                 _GA(new_db_script, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_script, "typeclass_last_errmsg"))

    if obj:
        new_script.obj = obj
    if player:
        new_script.player = player

    # call the hook method. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.
    new_script.at_script_creation()

    # custom-given variables override the hook
    if key:
        new_script.key = key
    if locks:
        new_script.locks.add(locks)
    if interval is not None:
        new_script.interval = interval
    if start_delay is not None:
        new_script.start_delay = start_delay
    if repeats is not None:
        new_script.repeats = repeats
    if persistent is not None:
        new_script.persistent = persistent

    # a new created script should usually be started.
    if autostart:
        new_script.start()

    new_db_script.save()
    return new_script
Exemplo n.º 37
0
def cmdhandler(called_by,
               raw_string,
               _testing=False,
               callertype="session",
               sessid=None,
               **kwargs):
    """
    This is the main function to handle any string sent to the engine.

    called_by - object on which this was called from. This is either a Session, a Player or an Object.
    raw_string - the command string given on the command line
    _testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.
    callertype - this is one of "session", "player" or "object", in decending
                 order. So when the Session is the caller, it will merge its
                 own cmdset into cmdsets from both Player and eventual puppeted
                 Object (and cmdsets in its room etc). A Player will only
                 include its own cmdset and the Objects and so on. Merge order
                 is the same order, so that Object cmdsets are merged in last,
                 giving them precendence for same-name and same-prio commands.
    sessid - Relevant if callertype is "player" - the session id will help
             retrieve the correct cmdsets from puppeted objects.
    **kwargs - other keyword arguments will be assigned as named variables on the
               retrieved command object *before* it is executed. This is unuesed
               in default Evennia but may be used by code to set custom flags or
               special operating conditions for a command as it executes.

    Note that this function returns a deferred!
    """

    raw_string = to_unicode(raw_string, force_string=True)

    session, player, obj = None, None, None
    if callertype == "session":
        session = called_by
        player = session.player
        if player:
            obj = yield _GA(player.dbobj, "get_puppet")(session.sessid)
    elif callertype == "player":
        player = called_by
        if sessid:
            obj = yield _GA(player.dbobj, "get_puppet")(sessid)
    elif callertype == "object":
        obj = called_by
    else:
        raise RuntimeError("cmdhandler: callertype %s is not valid." %
                           callertype)

    # the caller will be the one to receive messages and excert its permissions.
    # we assign the caller with preference 'bottom up'
    caller = obj or player or session

    try:  # catch bugs in cmdhandler itself
        try:  # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller, session, player, obj,
                                                 callertype, sessid)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets
            unformatted_raw_string = raw_string
            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)

            # Deal with matches

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = _("There were multiple matches.")
                if syscmd:
                    # use custom CMD_MULTIMATCH
                    syscmd.matches = matches
                else:
                    # fall back to default error handling
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) == 1:
                # We have a unique command match. But it may still be invalid.
                match = matches[0]
                cmdname, args, cmd = match[0], match[1], match[2]

                # check if we allow this type of command
                if cmdset.no_channels and hasattr(
                        cmd, "is_channel") and cmd.is_channel:
                    matches = []
                if cmdset.no_exits and hasattr(cmd, "is_exit") and cmd.is_exit:
                    matches = []

            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    # use custom CMD_NOMATH command
                    sysarg = raw_string
                else:
                    # fallback to default error text
                    sysarg = _("Command '%s' is not available.") % raw_string
                    suggestions = string_suggestions(
                        raw_string,
                        cmdset.get_all_cmd_keys_and_aliases(caller),
                        cutoff=0.7,
                        maxnum=3)
                    if suggestions:
                        sysarg += _(
                            " Maybe you meant %s?") % utils.list_to_string(
                                suggestions, _('or'), addquote=True)
                    else:
                        sysarg += _(" Type \"help\" for help.")
                raise ExecSystemCommand(syscmd, sysarg)

            # Check if this is a Channel-cmd match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                cmd.sessid = session.sessid if session else None
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset
            cmd.sessid = session.sessid if session else sessid
            cmd.session = session
            cmd.player = player
            cmd.raw_string = unformatted_raw_string
            #cmd.obj  # set via on-object cmdset handler for each command,
            # since this may be different for every command when
            # merging multuple cmdsets

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj is automatically made available by the cmdhandler.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if _testing:
                # only return the command instance
                returnValue(cmd)

            # assign custom kwargs to found cmd object
            for key, val in kwargs.items():
                setattr(cmd, key, val)

            # pre-command hook
            abort = yield cmd.at_pre_cmd()
            if abort:
                # abort sequence
                returnValue(abort)

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None

            # Done! This returns a deferred. By default, Evennia does
            # not use this at all.
            returnValue(ret)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset
                syscmd.sessid = session.sessid if session else None
                syscmd.raw_string = unformatted_raw_string

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    yield syscmd.obj.scripts.validate()

                if _testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                yield syscmd.parse()
                yield syscmd.func()
            elif sysarg:
                # return system arg
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(_(string))
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(_(string))
            caller.msg(string % format_exc())
Exemplo n.º 38
0
def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sessid=None, **kwargs):
    """
    This is the main function to handle any string sent to the engine.

    called_by - object on which this was called from. This is either a Session, a Player or an Object.
    raw_string - the command string given on the command line
    _testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.
    callertype - this is one of "session", "player" or "object", in decending
                 order. So when the Session is the caller, it will merge its
                 own cmdset into cmdsets from both Player and eventual puppeted
                 Object (and cmdsets in its room etc). A Player will only
                 include its own cmdset and the Objects and so on. Merge order
                 is the same order, so that Object cmdsets are merged in last,
                 giving them precendence for same-name and same-prio commands.
    sessid - Relevant if callertype is "player" - the session id will help
             retrieve the correct cmdsets from puppeted objects.
    **kwargs - other keyword arguments will be assigned as named variables on the
               retrieved command object *before* it is executed. This is unuesed
               in default Evennia but may be used by code to set custom flags or
               special operating conditions for a command as it executes.

    Note that this function returns a deferred!
    """

    raw_string = to_unicode(raw_string, force_string=True)

    session, player, obj = None, None, None
    if callertype == "session":
        session = called_by
        player = session.player
        if player:
            obj = yield _GA(player.dbobj, "get_puppet")(session.sessid)
    elif callertype == "player":
        player = called_by
        if sessid:
            obj = yield _GA(player.dbobj, "get_puppet")(sessid)
    elif callertype == "object":
        obj = called_by
    else:
        raise RuntimeError("cmdhandler: callertype %s is not valid." % callertype)

    # the caller will be the one to receive messages and excert its permissions.
    # we assign the caller with preference 'bottom up'
    caller = obj or player or session

    try:  # catch bugs in cmdhandler itself
        try:  # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller, session, player, obj,
                                                  callertype, sessid)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets
            unformatted_raw_string = raw_string
            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)

            # Deal with matches

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = _("There were multiple matches.")
                if syscmd:
                    # use custom CMD_MULTIMATCH
                    syscmd.matches = matches
                else:
                    # fall back to default error handling
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) == 1:
                # We have a unique command match. But it may still be invalid.
                match = matches[0]
                cmdname, args, cmd = match[0], match[1], match[2]

                # check if we allow this type of command
                if cmdset.no_channels and hasattr(cmd, "is_channel") and cmd.is_channel:
                    matches = []
                if cmdset.no_exits and hasattr(cmd, "is_exit") and cmd.is_exit:
                    matches = []

            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    # use custom CMD_NOMATH command
                    sysarg = raw_string
                else:
                    # fallback to default error text
                    sysarg = _("Command '%s' is not available.") % raw_string
                    suggestions = string_suggestions(raw_string,
                                    cmdset.get_all_cmd_keys_and_aliases(caller),
                                    cutoff=0.7, maxnum=3)
                    if suggestions:
                        sysarg += _(" Maybe you meant %s?") % utils.list_to_string(suggestions, _('or'), addquote=True)
                    else:
                        sysarg += _(" Type \"help\" for help.")
                raise ExecSystemCommand(syscmd, sysarg)

            # Check if this is a Channel-cmd match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                cmd.sessid = session.sessid if session else None
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset
            cmd.sessid = session.sessid if session else sessid
            cmd.session = session
            cmd.player = player
            cmd.raw_string = unformatted_raw_string
            #cmd.obj  # set via on-object cmdset handler for each command,
                      # since this may be different for every command when
                      # merging multuple cmdsets

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj is automatically made available by the cmdhandler.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if _testing:
                # only return the command instance
                returnValue(cmd)

            # assign custom kwargs to found cmd object
            for key, val in kwargs.items():
                setattr(cmd, key, val)

            # pre-command hook
            abort = yield cmd.at_pre_cmd()
            if abort:
                # abort sequence
                returnValue(abort)

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None

            # Done! This returns a deferred. By default, Evennia does
            # not use this at all.
            returnValue(ret)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset
                syscmd.sessid = session.sessid if session else None
                syscmd.raw_string = unformatted_raw_string

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    yield syscmd.obj.scripts.validate()

                if _testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                yield syscmd.parse()
                yield syscmd.func()
            elif sysarg:
                # return system arg
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(_(string))
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(_(string))
            caller.msg(string % format_exc())
Exemplo n.º 39
0
def create_object(typeclass, key=None, location=None,
                  home=None, player=None, permissions=None, locks=None,
                  aliases=None, destination=None, report_to=None):
    """
    Create a new in-game object. Any game object is a combination
    of a database object that stores data persistently to
    the database, and a typeclass, which on-the-fly 'decorates'
    the database object into whataver different type of object
    it is supposed to be in the game.

    See src.objects.managers for methods to manipulate existing objects
    in the database. src.objects.objects holds the base typeclasses
    and src.objects.models hold the database model.

    report_to is an optional object for reporting errors to in string form.
              If report_to is not set, errors will be raised as en Exception
              containing the error message. If set, this method will return
              None upon errors.
    """
    global _Object, _ObjectDB
    if not _Object:
        from src.objects.objects import Object as _Object
    if not _ObjectDB:
        from src.objects.models import ObjectDB as _ObjectDB

    if not typeclass:
        typeclass = settings.BASE_OBJECT_TYPECLASS
    elif isinstance(typeclass, _ObjectDB):
        # this is already an objectdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Object) or utils.inherits_from(typeclass, _Object):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path

    # create new database object
    new_db_object = _ObjectDB()

    # assign the typeclass
    typeclass = utils.to_unicode(typeclass)
    new_db_object.typeclass_path = typeclass

    # the name/key is often set later in the typeclass. This
    # is set here as a failsafe.
    if key:
        new_db_object.key = key
    else:
        new_db_object.key = "#%i" % new_db_object.dbid

    # this will either load the typeclass or the default one
    new_object = new_db_object.typeclass

    if not _GA(new_object, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still gave us a default
        SharedMemoryModel.delete(new_db_object)
        if report_to:
            _GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_object.key, typeclass,
                                                                 _GA(new_db_object, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_object, "typeclass_last_errmsg"))

    # from now on we can use the typeclass object
    # as if it was the database object.

    if player:
        # link a player and the object together
        new_object.player = player
        player.obj = new_object

    new_object.destination = destination

    # call the hook method. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.
    new_object.basetype_setup() # setup the basics of Exits, Characters etc.
    new_object.at_object_creation()

    # custom-given perms/locks overwrite hooks
    if permissions:
        new_object.permissions = permissions
    if locks:
         new_object.locks.add(locks)
    if aliases:
        new_object.aliases = aliases

    # perform a move_to in order to display eventual messages.
    if home:
        new_object.home = home
    else:
        new_object.home =  settings.CHARACTER_DEFAULT_HOME


    if location:
         new_object.move_to(location, quiet=True)
    else:
        # rooms would have location=None.
        new_object.location = None

    # post-hook setup (mainly used by Exits)
    new_object.basetype_posthook_setup()

    new_object.save()
    return new_object
Exemplo n.º 40
0
def create_object(typeclass=None, key=None, location=None,
                  home=None, permissions=None, locks=None,
                  aliases=None, destination=None, report_to=None, nohome=False):
    """
    Create a new in-game object. Any game object is a combination
    of a database object that stores data persistently to
    the database, and a typeclass, which on-the-fly 'decorates'
    the database object into whataver different type of object
    it is supposed to be in the game.

    See src.objects.managers for methods to manipulate existing objects
    in the database. src.objects.objects holds the base typeclasses
    and src.objects.models hold the database model.

    report_to is an optional object for reporting errors to in string form.
              If report_to is not set, errors will be raised as en Exception
              containing the error message. If set, this method will return
              None upon errors.
    nohome - this allows the creation of objects without a default home location;
             this only used when creating the default location itself or during unittests
    """
    global _Object, _ObjectDB
    if not _Object:
        from src.objects.objects import Object as _Object
    if not _ObjectDB:
        from src.objects.models import ObjectDB as _ObjectDB

    # input validation

    if not typeclass:
        typeclass = settings.BASE_OBJECT_TYPECLASS
    elif isinstance(typeclass, _ObjectDB):
        # this is already an objectdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Object) or utils.inherits_from(typeclass, _Object):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path
    typeclass = utils.to_unicode(typeclass)

    # Setup input for the create command

    location = handle_dbref(location, _ObjectDB)
    destination = handle_dbref(destination, _ObjectDB)
    home = handle_dbref(home, _ObjectDB)
    if not home:
        try:
            home = handle_dbref(settings.DEFAULT_HOME, _ObjectDB) if not nohome else None
        except _ObjectDB.DoesNotExist:
            raise _ObjectDB.DoesNotExist("settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed." %
                                         settings.DEFAULT_HOME)

    # create new database object all in one go
    new_db_object = _ObjectDB(db_key=key, db_location=location,
                              db_destination=destination, db_home=home,
                              db_typeclass_path=typeclass)

    if not key:
        # the object should always have a key, so if not set we give a default
        new_db_object.key = "#%i" % new_db_object.dbid

    # this will either load the typeclass or the default one (will also save object)
    new_object = new_db_object.typeclass

    if not _GA(new_object, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        try:
            SharedMemoryModel.delete(new_db_object)
        except AssertionError:
            # this happens if object was never created
            pass
        if report_to:
            report_to = handle_dbref(report_to, _ObjectDB)
            _GA(report_to, "msg")("Error creating %s (%s).\n%s" % (new_db_object.key, typeclass,
                                                                 _GA(new_db_object, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_object, "typeclass_last_errmsg"))

    # from now on we can use the typeclass object
    # as if it was the database object.

    # call the hook methods. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.

    # note - this may override input keys, locations etc!
    new_object.basetype_setup()  # setup the basics of Exits, Characters etc.
    new_object.at_object_creation()

    # we want the input to override that set in the hooks, so
    # we re-apply those if needed
    if new_object.key != key:
        new_object.key = key
    if new_object.location != location:
        new_object.location = location
    if new_object.home != home:
        new_object.home = home
    if new_object.destination != destination:
        new_object.destination = destination

    # custom-given perms/locks do overwrite hooks
    if permissions:
        new_object.permissions.add(permissions)
    if locks:
        new_object.locks.add(locks)
    if aliases:
        new_object.aliases.add(aliases)

    # trigger relevant move_to hooks in order to display messages.
    if location:
        location.at_object_receive(new_object, None)
        new_object.at_after_move(None)

    # post-hook setup (mainly used by Exits)
    new_object.basetype_posthook_setup()

    return new_object
Exemplo n.º 41
0
 def __str__(self):
     "print table"
     return  to_unicode("\n".join([line for line in self._generate_lines()]))
Exemplo n.º 42
0
def create_object(typeclass=None,
                  key=None,
                  location=None,
                  home=None,
                  permissions=None,
                  locks=None,
                  aliases=None,
                  destination=None,
                  report_to=None,
                  nohome=False):
    """
    Create a new in-game object. Any game object is a combination
    of a database object that stores data persistently to
    the database, and a typeclass, which on-the-fly 'decorates'
    the database object into whataver different type of object
    it is supposed to be in the game.

    See src.objects.managers for methods to manipulate existing objects
    in the database. src.objects.objects holds the base typeclasses
    and src.objects.models hold the database model.

    report_to is an optional object for reporting errors to in string form.
              If report_to is not set, errors will be raised as en Exception
              containing the error message. If set, this method will return
              None upon errors.
    nohome - this allows the creation of objects without a default home location;
             this only used when creating the default location itself or during unittests
    """
    global _Object, _ObjectDB
    if not _Object:
        from src.objects.objects import Object as _Object
    if not _ObjectDB:
        from src.objects.models import ObjectDB as _ObjectDB

    # input validation

    if not typeclass:
        typeclass = settings.BASE_OBJECT_TYPECLASS
    elif isinstance(typeclass, _ObjectDB):
        # this is already an objectdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Object) or utils.inherits_from(
            typeclass, _Object):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path
    typeclass = utils.to_unicode(typeclass)

    # Setup input for the create command

    location = handle_dbref(location, _ObjectDB)
    destination = handle_dbref(destination, _ObjectDB)
    home = handle_dbref(home, _ObjectDB)
    if not home:
        try:
            home = handle_dbref(settings.DEFAULT_HOME,
                                _ObjectDB) if not nohome else None
        except _ObjectDB.DoesNotExist:
            raise _ObjectDB.DoesNotExist(
                "settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed."
                % settings.DEFAULT_HOME)

    # create new database object all in one go
    new_db_object = _ObjectDB(db_key=key,
                              db_location=location,
                              db_destination=destination,
                              db_home=home,
                              db_typeclass_path=typeclass)

    if not key:
        # the object should always have a key, so if not set we give a default
        new_db_object.key = "#%i" % new_db_object.dbid

    # this will either load the typeclass or the default one (will also save object)
    new_object = new_db_object.typeclass

    if not _GA(new_object, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        try:
            SharedMemoryModel.delete(new_db_object)
        except AssertionError:
            # this happens if object was never created
            pass
        if report_to:
            report_to = handle_dbref(report_to, _ObjectDB)
            _GA(report_to,
                "msg")("Error creating %s (%s).\n%s" %
                       (new_db_object.key, typeclass,
                        _GA(new_db_object, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_object, "typeclass_last_errmsg"))

    # from now on we can use the typeclass object
    # as if it was the database object.

    # call the hook methods. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.

    # note - this may override input keys, locations etc!
    new_object.basetype_setup()  # setup the basics of Exits, Characters etc.
    new_object.at_object_creation()

    # we want the input to override that set in the hooks, so
    # we re-apply those if needed
    if new_object.key != key:
        new_object.key = key
    if new_object.location != location:
        new_object.location = location
    if new_object.home != home:
        new_object.home = home
    if new_object.destination != destination:
        new_object.destination = destination

    # custom-given perms/locks do overwrite hooks
    if permissions:
        new_object.permissions.add(permissions)
    if locks:
        new_object.locks.add(locks)
    if aliases:
        new_object.aliases.add(aliases)

    # trigger relevant move_to hooks in order to display messages.
    if location:
        new_object.at_object_receive(new_object, None)
        new_object.at_after_move(new_object)

    # post-hook setup (mainly used by Exits)
    new_object.basetype_posthook_setup()

    return new_object
Exemplo n.º 43
0
def create_player(key,
                  email,
                  password,
                  typeclass=None,
                  is_superuser=False,
                  locks=None,
                  permissions=None,
                  report_to=None):
    """
    This creates a new player.

    key - the player's name. This should be unique.
    email - email on valid [email protected] form.
    password - password in cleartext
    is_superuser - wether or not this player is to be a superuser
    locks - lockstring
    permission - list of permissions
    report_to - an object with a msg() method to report errors to. If
                not given, errors will be logged.

    Will return the Player-typeclass or None/raise Exception if the
    Typeclass given failed to load.

    Concerning is_superuser:
     Usually only the server admin should need to be superuser, all
     other access levels can be handled with more fine-grained
     permissions or groups. A superuser bypasses all lock checking
     operations and is thus not suitable for play-testing the game.

    """
    global _PlayerDB, _Player
    if not _PlayerDB:
        from src.players.models import PlayerDB as _PlayerDB
    if not _Player:
        from src.players.player import Player as _Player

    if not email:
        email = "*****@*****.**"
    if _PlayerDB.objects.filter(username__iexact=key):
        raise ValueError("A Player with the name '%s' already exists." % key)

    # this handles a given dbref-relocate to a player.
    report_to = handle_dbref(report_to, _PlayerDB)

    try:

        # create the correct Player object
        if is_superuser:
            new_db_player = _PlayerDB.objects.create_superuser(
                key, email, password)
        else:
            new_db_player = _PlayerDB.objects.create_user(key, email, password)

        if not typeclass:
            typeclass = settings.BASE_PLAYER_TYPECLASS
        elif isinstance(typeclass, _PlayerDB):
            # this is an PlayerDB instance, extract its typeclass path
            typeclass = typeclass.typeclass.path
        elif isinstance(typeclass, _Player) or utils.inherits_from(
                typeclass, _Player):
            # this is Player object typeclass, extract its path
            typeclass = typeclass.path

        # assign the typeclass
        typeclass = utils.to_unicode(typeclass)
        new_db_player.typeclass_path = typeclass

        # this will either load the typeclass or the default one
        new_player = new_db_player.typeclass

        if not _GA(new_db_player, "is_typeclass")(typeclass, exact=True):
            # this will fail if we gave a typeclass as input
            # and it still gave us a default
            SharedMemoryModel.delete(new_db_player)
            if report_to:
                _GA(report_to,
                    "msg")("Error creating %s (%s):\n%s" %
                           (new_db_player.key, typeclass,
                            _GA(new_db_player, "typeclass_last_errmsg")))
                return None
            else:
                raise Exception(_GA(new_db_player, "typeclass_last_errmsg"))

        new_player.basetype_setup()  # setup the basic locks and cmdset
        # call hook method (may override default permissions)
        new_player.at_player_creation()

        # custom given arguments potentially overrides the hook
        if permissions:
            new_player.permissions.add(permissions)
        elif not new_player.permissions:
            new_player.permissions.add(settings.PERMISSION_PLAYER_DEFAULT)
        if locks:
            new_player.locks.add(locks)
        return new_player

    except Exception:
        # a failure in creating the player; we try to clean
        # up as much as we can
        logger.log_trace()
        try:
            new_player.delete()
        except Exception:
            pass
        try:
            del new_player
        except Exception:
            pass
        raise
Exemplo n.º 44
0
def create_script(typeclass,
                  key=None,
                  obj=None,
                  player=None,
                  locks=None,
                  interval=None,
                  start_delay=None,
                  repeats=None,
                  persistent=None,
                  autostart=True,
                  report_to=None):
    """
    Create a new script. All scripts are a combination
    of a database object that communicates with the
    database, and an typeclass that 'decorates' the
    database object into being different types of scripts.
    It's behaviour is similar to the game objects except
    scripts has a time component and are more limited in
    scope.

    Argument 'typeclass' can be either an actual
    typeclass object or a python path to such an object.
    Only set key here if you want a unique name for this
    particular script (set it in config to give
    same key to all scripts of the same type). Set obj
    to tie this script to a particular object.

    See src.scripts.manager for methods to manipulate existing
    scripts in the database.

    report_to is an obtional object to receive error messages.
              If report_to is not set, an Exception with the
              error will be raised. If set, this method will
              return None upon errors.
    """
    global _Script, _ScriptDB
    if not _Script:
        from src.scripts.scripts import Script as _Script
    if not _ScriptDB:
        from src.scripts.models import ScriptDB as _ScriptDB

    if not typeclass:
        typeclass = settings.BASE_SCRIPT_TYPECLASS
    elif isinstance(typeclass, _ScriptDB):
        # this is already an scriptdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Script) or utils.inherits_from(
            typeclass, _Script):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path

    # create new database script
    new_db_script = _ScriptDB()

    # assign the typeclass
    typeclass = utils.to_unicode(typeclass)
    new_db_script.typeclass_path = typeclass

    # the name/key is often set later in the typeclass. This
    # is set here as a failsafe.
    if key:
        new_db_script.key = key
    else:
        new_db_script.key = "#%i" % new_db_script.id

    # this will either load the typeclass or the default one
    new_script = new_db_script.typeclass

    if not _GA(new_db_script, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        SharedMemoryModel.delete(new_db_script)
        if report_to:
            _GA(report_to,
                "msg")("Error creating %s (%s): %s" %
                       (new_db_script.key, typeclass,
                        _GA(new_db_script, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_script, "typeclass_last_errmsg"))

    if obj:
        new_script.obj = obj
    if player:
        new_script.player = player

    # call the hook method. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.
    new_script.at_script_creation()

    # custom-given variables override the hook
    if key:
        new_script.key = key
    if locks:
        new_script.locks.add(locks)
    if interval is not None:
        new_script.interval = interval
    if start_delay is not None:
        new_script.start_delay = start_delay
    if repeats is not None:
        new_script.repeats = repeats
    if persistent is not None:
        new_script.persistent = persistent

    # a new created script should usually be started.
    if autostart:
        new_script.start()

    new_db_script.save()
    return new_script
Exemplo n.º 45
0
def _to_ansi(obj):
    "convert to ANSIString"
    if hasattr(obj, "__iter__"):
        return [_to_ansi(o) for o in obj]
    else:
        return ANSIString(to_unicode(obj))
Exemplo n.º 46
0
def _to_ansi(obj):
    "convert to ANSIString"
    if hasattr(obj, "__iter__"):
        return [_to_ansi(o) for o in obj]
    else:
        return ANSIString(to_unicode(obj))
Exemplo n.º 47
0
def create_object(typeclass=None,
                  key=None,
                  location=None,
                  home=None,
                  permissions=None,
                  locks=None,
                  aliases=None,
                  destination=None,
                  report_to=None,
                  nohome=False):
    """
    Create a new in-game object. Any game object is a combination
    of a database object that stores data persistently to
    the database, and a typeclass, which on-the-fly 'decorates'
    the database object into whataver different type of object
    it is supposed to be in the game.

    See src.objects.managers for methods to manipulate existing objects
    in the database. src.objects.objects holds the base typeclasses
    and src.objects.models hold the database model.

    report_to is an optional object for reporting errors to in string form.
              If report_to is not set, errors will be raised as en Exception
              containing the error message. If set, this method will return
              None upon errors.
    nohome - this allows the creation of objects without a default home location;
             this only used when creating default location itself or during unittests
    """
    global _Object, _ObjectDB
    if not _Object:
        from src.objects.objects import Object as _Object
    if not _ObjectDB:
        from src.objects.models import ObjectDB as _ObjectDB

    # input validation

    if not typeclass:
        typeclass = settings.BASE_OBJECT_TYPECLASS
    elif isinstance(typeclass, _ObjectDB):
        # this is already an objectdb instance, extract its typeclass
        typeclass = typeclass.typeclass.path
    elif isinstance(typeclass, _Object) or utils.inherits_from(
            typeclass, _Object):
        # this is already an object typeclass, extract its path
        typeclass = typeclass.path

    # handle eventual #dbref input
    location = handle_dbref(location, _ObjectDB)
    home = handle_dbref(home, _ObjectDB)
    destination = handle_dbref(destination, _ObjectDB)
    report_to = handle_dbref(report_to, _ObjectDB)

    # create new database object
    new_db_object = _ObjectDB()

    # assign the typeclass
    typeclass = utils.to_unicode(typeclass)
    new_db_object.typeclass_path = typeclass

    # the name/key is often set later in the typeclass. This
    # is set here as a failsafe.
    if key:
        new_db_object.key = key
    else:
        new_db_object.key = "#%i" % new_db_object.dbid

    # this will either load the typeclass or the default one
    new_object = new_db_object.typeclass

    if not _GA(new_object, "is_typeclass")(typeclass, exact=True):
        # this will fail if we gave a typeclass as input and it still
        # gave us a default
        SharedMemoryModel.delete(new_db_object)
        if report_to:
            _GA(report_to,
                "msg")("Error creating %s (%s):\n%s" %
                       (new_db_object.key, typeclass,
                        _GA(new_db_object, "typeclass_last_errmsg")))
            return None
        else:
            raise Exception(_GA(new_db_object, "typeclass_last_errmsg"))

    # from now on we can use the typeclass object
    # as if it was the database object.

    new_object.destination = destination

    # call the hook method. This is where all at_creation
    # customization happens as the typeclass stores custom
    # things on its database object.
    new_object.basetype_setup()  # setup the basics of Exits, Characters etc.
    new_object.at_object_creation()

    # custom-given perms/locks overwrite hooks
    if permissions:
        new_object.permissions.add(permissions)
    if locks:
        new_object.locks.add(locks)
    if aliases:
        new_object.aliases.add(aliases)

    if home:
        new_object.home = home
    else:
        # we shouldn't need to handle dbref here (home handler should fix it), but some have
        # reported issues here (issue 446).
        try:
            new_object.home = handle_dbref(settings.DEFAULT_HOME,
                                           _ObjectDB) if not nohome else None
        except _ObjectDB.DoesNotExist:
            raise _ObjectDB.DoesNotExist(
                "settings.DEFAULT_HOME (= '%s') does not exist, or the setting is malformed."
                % settings.DEFAULT_HOME)

    # perform a move_to in order to display eventual messages.
    if location:
        new_object.move_to(location, quiet=True)
    else:
        # rooms would have location=None.
        new_object.location = None

    # post-hook setup (mainly used by Exits)
    new_object.basetype_posthook_setup()

    new_object.save()
    return new_object
Exemplo n.º 48
0
def create_player(name, email, password,
                  user=None,
                  typeclass=None,
                  is_superuser=False,
                  locks=None, permissions=None,
                  create_character=True, character_typeclass=None,
                  character_location=None, character_home=None,
                  player_dbobj=None, report_to=None):


    """
    This creates a new player, handling the creation of the User
    object and its associated Player object.

    If player_dbobj is given, this player object is used instead of
    creating a new one. This is called by the admin interface since it
    needs to create the player object in order to relate it automatically
    to the user.

    If create_character is
    True, a game player object with the same name as the User/Player will
    also be created. Its typeclass and base properties can also be given.

    Returns the new game character, or the Player obj if no
    character is created.  For more info about the typeclass argument,
    see create_objects() above.

    Note: if user is supplied, it will NOT be modified (args name, email,
    passw and is_superuser will be ignored). Change those properties
    directly on the User instead.

    If no permissions are given (None), the default permission group
    as defined in settings.PERMISSION_PLAYER_DEFAULT will be
    assigned. If permissions are given, no automatic assignment will
    occur.

    Concerning is_superuser:
     A superuser should have access to everything
     in the game and on the server/web interface. The very first user
     created in the database is always a superuser (that's using
     django's own creation, not this one).
     Usually only the server admin should need to be superuser, all
     other access levels can be handled with more fine-grained
     permissions or groups.
     Since superuser overrules all permissions, we don't
     set any in this case.

    """
    # The system should already have checked so the name/email
    # isn't already registered, and that the password is ok before
    # getting here.
    global _PlayerDB, _Player
    if not _PlayerDB:
        from src.players.models import PlayerDB as _PlayerDB
    if not _Player:
        from src.players.player import Player as _Player

    if not email:
        email = "*****@*****.**"
    if user:
        new_user = user
        email = user.email
    else:
        if is_superuser:
            new_user = User.objects.create_superuser(name, email, password)
        else:
            new_user = User.objects.create_user(name, email, password)
    try:
        if not typeclass:
            typeclass = settings.BASE_PLAYER_TYPECLASS
        elif isinstance(typeclass, _PlayerDB):
            # this is already an objectdb instance, extract its typeclass
            typeclass = typeclass.typeclass.path
        elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player):
            # this is already an object typeclass, extract its path
            typeclass = typeclass.path
        if player_dbobj:
            try:
                _GA(player_dbobj, "dbobj")
                new_db_player = player_dbobj.dbobj
            except AttributeError:
                new_db_player = player_dbobj
            # use the typeclass from this object
            typeclass = new_db_player.typeclass_path
        else:
            new_db_player = _PlayerDB(db_key=name, user=new_user)
            new_db_player.save()
            # assign the typeclass
            typeclass = utils.to_unicode(typeclass)
            new_db_player.typeclass_path = typeclass

        # this will either load the typeclass or the default one
        new_player = new_db_player.typeclass

        if not _GA(new_db_player, "is_typeclass")(typeclass, exact=True):
            # this will fail if we gave a typeclass as input and it still gave us a default
            SharedMemoryModel.delete(new_db_player)
            if report_to:
                _GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_player.key, typeclass,
                                                                  _GA(new_db_player, "typeclass_last_errmsg")))
                return None
            else:
                raise Exception(_GA(new_db_player, "typeclass_last_errmsg"))

        new_player.basetype_setup() # setup the basic locks and cmdset
        # call hook method (may override default permissions)
        new_player.at_player_creation()

        # custom given arguments potentially overrides the hook
        if permissions:
            new_player.permissions = permissions
        elif not new_player.permissions:
            new_player.permissions = settings.PERMISSION_PLAYER_DEFAULT

        if locks:
            new_player.locks.add(locks)

        # create *in-game* 'player' object
        if create_character:
            if not character_typeclass:
                character_typeclass = settings.BASE_CHARACTER_TYPECLASS
            # creating the object automatically links the player
            # and object together by player.obj <-> obj.player
            new_character = create_object(character_typeclass, key=name,
                                          location=character_location, home=character_location,
                                          permissions=permissions,
                                          player=new_player, report_to=report_to)
            return new_character
        return new_player
    except Exception, e:
        # a failure in creating the character
        if not user:
            # in there was a failure we clean up everything we can
            logger.log_trace()
            try:
                new_user.delete()
            except Exception:
                pass
            try:
                new_player.delete()
            except Exception:
                pass
            try:
                del new_character
            except Exception:
                pass
        raise e