Evennia - a Python-Based Mu* Server



  • I registered to reply to this thread after I noticed it because of how close it is to my experiences. About six months ago, I decided to start creating a new MUSH with my room mate. I've been MU*ing for a few years with a decent amount of soft code experience but no experience at all with Python while he had very little MU experience but a pretty heavy computer science background. We had a pretty big argument since he was horrified at softcode and didn't want to learn it, while I was extremely reluctant to try something I had no familiarity with at all, but we went with Evennia.

    I'm SO glad we did. While definitely a few features would have been faster to add as we stumbled, there's a good amount of features we're adding that would have been flat out impossible with softcode. Particularly on the web framework side. One nice thing is that since django is bundled into it, you can do a lot of stuff for web support rather than just use an external wikia. We're still working on this ourselves, but there's a lot of potential there to have a far more rich web experience than just wiki character sheets. When you think of how critical wikis are to most games, there's a large potential for eliminating tedious tasks players often complain about, like cleaning logs or updating things about their characters sheets that would be reflected on the web. Ultimately the game might wind up being closer to a web browser game than a true MU, but with how niche MU gaming is I think if anything Evennia will lower the bar to entry rather than raise it.


  • Coder

    @Griatch Then you're using NAWS the right way, since it's as reliable as ben carson telling the truth.


  • Coder

    @Apos said:

    I registered to reply to this thread after I noticed it because of how close it is to my experiences. About six months ago, I decided to start creating a new MUSH with my room mate. I've been MU*ing for a few years with a decent amount of soft code experience but no experience at all with Python while he had very little MU experience but a pretty heavy computer science background. We had a pretty big argument since he was horrified at softcode and didn't want to learn it, while I was extremely reluctant to try something I had no familiarity with at all, but we went with Evennia.
    I'm SO glad we did. While definitely a few features would have been faster to add as we stumbled, there's a good amount of features we're adding that would have been flat out impossible with softcode. Particularly on the web framework side. One nice thing is that since django is bundled into it, you can do a lot of stuff for web support rather than just use an external wikia. We're still working on this ourselves, but there's a lot of potential there to have a far more rich web experience than just wiki character sheets. When you think of how critical wikis are to most games, there's a large potential for eliminating tedious tasks players often complain about, like cleaning logs or updating things about their characters sheets that would be reflected on the web. Ultimately the game might wind up being closer to a web browser game than a true MU, but with how niche MU gaming is I think if anything Evennia will lower the bar to entry rather than raise it.

    I'm very glad to hear this! Django is very powerful, there's a lot to do there and I think people have only just scratched the surface on what you could integrate with your game that way. On the client side we hope to enhance our web capabilities further and make it even easier to expand in that regime. Do you have a website or blog somewhere with information about you game/progress so far - would love to read more about it!
    .
    Griatch


  • Coder

    @Thenomain, @WTFE, others

    I pushed a development branch of Evennia that implements nested inline-functions as discussed in the last few pages of this thread. If people want they can check out the implementation and test it.

    These use in-game structures of the form $funcname{arg,arg2,...} (thanks to @WTFE for some of the arguments around syntax!), where one can escape commas, inlinefuncs and } inside the arguments either with \ or by wrapping verbatim text strings in the Python triple string markers (""" or ''' , this means you can add inline-funcs in normal say-quotes without them getting escaped).

    New inline-funcs are added by the developer by use of a normal Python function on the form funcname(*args, **kwargs), where *args in Python means "any number of positional arguments" and **kwargs means "any number of named keywords". Here, *args (a tuple) will hold the arguments given to $funcname(arg, arg2, ...) in-game and **kwargs is left for Evennia to make relevant state-information (such as Session info) available to the function.

    The |-style color codes were also put into this branch as a test, as per issue #818. The existing {- style color codes and non-nested inlinefuncs are still functional during a transitional period.

    This is a development branch, so constructive feedback and testing is appreciated. :smiley:
    .
    Griatch


  • Coder

    Not much interest in trying out the development branch in the interim it seems. So at any rate, the nested form of inlinefunc is now merged. After some pondering, I went with parentheses for the inlinefunc form anyway, making the syntax

    $funcname(arg1, arg2, ...)

    Where any argument can itself be an inlinefunc call. Escaping ) and commas is done either by \) or \, or by escaping everything inside python triplet-quotes, like '''..''' or """...""".

    The functions to make available are simply Python functions in a module Evennia is told to contain inlinefunc-ready functions. Here is an example of the Python function behind an inlinefunc that "crops" a string if it is too wide:

    from evennia.utils import utils
    def crop(*args, **kwargs):
        "Call signature is $crop(text, width)"
        text, width = "", 78 # defaults, if args are missing
        nargs = len(args)
        if nargs > 0:
            text = args[0]
        if nargs > 1 and args[1].strip().isdigit():
            # only accepts digits as the width 
            width = int(args[1]) 
        return utils.crop(text, width=width)
    

    As seen, this basically only consiststs of argument validation and then a call to an utility function to perform the crop (this particular utility function will crop to a string that in the width includes a suffix [...] to show it was cropped). This will now be usable in-game, for example as

    say This is a $crop(very\, very long text, 12) that we have.

    which will output

    You say, "This is a very ve[...] that we have."

    The number of inlinefuncs available out of the box is limited at this point but there is also an inlinefunc $clr(startcode, text, endcode) for those prefering to use that form to declare colors as $clr(r, redtext) (if no endcode is given, the reset-color code will be inserted automatically). As part of the same branch merger were also the variant of ANSI-coloring using |r etc to mark color codes.

    Please report issues/bugs go to the Evennia issue tracker.

    Enjoy, you guys are after all the ones saying the nested functionality was needed. :)
    .
    Griatch


  • Coder

    Okay, so I'm looking at evennia again. Before, I'd mentioned that everything was strings and was told that that was indeed not the case once things got into the internals of evennia. I assume there is a misunderstanding, then, about what I mean. For example, the dice command.

    All of the returns are interpolated strings. So yes, I can out of band it and be like, msg(oob='you rolled a 2d6 for 10!'), and it would technically send the message back oob, but it's still a string. I don't have the dice rolled, or the user who rolled it or any of that automatically. All of that info is interpolated in the string response itself.

    This is what I mean by saying it is string-based. Does making it a json object (or dict) with worthwhile information mean rewriting all of these commands? Do I have to turn a front-end message like:

    {
      cmd: 'roll',
      args: [{ count: 2, sides: 6 }]
    }
    

    Into roll 2d6 before sending it to the back-end in order for it to be understood?

    Does the parser accept any structured oob as long as it has some key that allows it to pass args to a command?


  • Coder

    @Glitch

    On the road, so need to keep I brief. What you send in msg(oob=...) is not a string. It's an OOB-command call + arguments, sent as a tuple. The available oob-commands server-side is specified and registered with the oob handler as normal Python calls. This is then sent on to the protocol (telnet or json/websocket). In the case of the current webclient, the oob function name is generally associated with a js function in your client code, which is then called with the specified arguments.
    You are correct however that the default commands universally tends to use the text channel over the oob channel. This makes a lot of sense for telnet, where oob happens via subnegotiation; for the webclient it makes less sense and the text channel will soon (tm) be collated as just another oob instruction.
    .
    Griatch


  • Coder

    Just to be a pedant, @Glitch, they are Unicode objects, not string objects. There are some differences.