The Twilight Sun

Archive for March, 2010

Aspect (plugin infrastructure)

by Jonathan on Mar.23, 2010, under Aspect

This is still entirely conceptual at the moment, so don’t get too excited. ;) Also, if you’re not too into technical stuff, you might want to read only the first paragraph.

I’m planning on making Aspect extensible to a certain extent. Users will be able to create plugins written in Lua, run on the server in a highly sandboxed environment, with a specialized API so the plugins can do useful stuff. One such API will probably be a widget interface, to create and manage HTML widgets on the browser side. This means you could create plugins that manage a visual set of stat gauges, or show a visual map, etc etc. in a similar vein to MUSHclient and Mudlet.

Now, plugins will be run on the server. This is because (a) I don’t think you can run Javascript sandboxed very easily, (b) it makes it much harder to communicate between the plugins and Aspect and the MUD, and (c) Lua is just so much nicer to script this kind of stuff with. For speed and manageability, I’ve also decided that all plugins will share the same Lua interpreter space. You have to be careful with security in all cases here, because third-party scripts will be running on the Aspect server. You don’t want arbitrary plugins to share player info, or clash with eachother in other ways.

Obviously I have to only give scripts access to utilities I want them to have access to. But what if the plugin goes into an infinite loop, or just takes too much time to execute? In the best case, it will lag everyone else connected to Aspect. That’s clearly not a good thing!

There is functionality in Lua to set a “hook” which can be called automatically every so often. Theoretically, I can use this to halt execution, go do other stuff, then come back to the plugins. But we also want some way to keep plugins completely separate, and we don’t want any one plugin to hog all the time so no other plugin gets a chance. It’s a bit of a sticky situation.

First of all, we can isolate each plugin by starting each one in a coroutine, and setting the coroutine functions environment to its own special table. Coroutines are like threads, but they’re cooperative rather than preemptive. That is to say, a coroutine has to say “Okay, I’m going to take a break now” or “Hey, you, do some work” explicitly in order for another coroutine to begin. And changing the environment keeps the plugins from sharing any state.

Now we’re down to one more problem (or at least the last major one for now). I mentioned before that I don’t want any one plugin to hog all the time. I also mentioned hook functions. It just so happens that you can set a hook function separately for each coroutine. If we could yield from that hook, it would be almost like preemptive threads. And while you can’t yield from a hook set with debug.sethook (in Lua), you can from a hook set with lua_sethook (in C). So I just have to figure out how to write C-based hook functions to yield every so often.

So that’s a rather verbose explanation of how I want to implement plugins. Well, it’s 2am and I needed to talk. :P Tl;dr summary: every plugin will be a completely isolated Lua coroutine that shares execution time with other plugins. Plugins will be able to do a lot of interesting things, like create and manage visual widgets on the user’s browser, like status bars and maps and stuff, and could even augment/replace the default output window and input bar. It’ll be extremely extensible.

Now if only I could figure out how lua_yield works.
~Jonathan

1 Comment :, more...

Project Aspect

by Jonathan on Mar.18, 2010, under MUDs

I’ve been working on a new personal project lately, which I call Aspect. It’ll a web-based MUD client, but without Java or Flash. (A bit like PHudBase, actually, but built differently.) I haven’t done much with it yet, but I’ve got a local webserver running using the Python-based Tornado server. Tornado is great because it’s built specifically for handling AJAX long polling, which is what I use to communicate between Aspect and the browser. I’ve never used Python before, so it’s an interesting experience.

I’m planning on making the client extremely customizable by way of plugins, drawing from my ongoing experiences with MUSHclient. I’m also taking philosophical inspiration from Mibbit, which seems to work similarly (though the focus is completely different). With some MUDs, though, there’s a bit of an issue. Many MUDs disallow multiplaying, which is often tracked through the user’s IP address. But all users playing through Aspect will appear to connect from the same IP address; namely, the IP of Aspect itself. This is something I’ll have to work out eventually, but I have some ideas.

More to come eventually. I’d like to keep most of the details under wraps for now, and there are a lot of details.
~Jonathan

7 Comments :, more...

MUSHclient, cont.

by Jonathan on Mar.07, 2010, under Uncategorized

So… Lately, I’ve been playing around a lot with MUSHclient’s source code. It’s pretty interesting to see how a program I’ve used for a long time actually functions (even though he uses the Whitesmiths indentation style, which I cannot abide. I’ve always been a fan of the Allman style, myself). I’ve actually made a few relatively minor contributions, which I’m pretty happy about. :) I also contributed (and I suppose maintain?) a pair of Visual Studio 2005 solution and project files, and helped ease the compilation process under it. Nick uses VC6, which is really old these days, but it’s what he used when he first started, and he’s not exactly willing to shell out hundreds of dollars to update. (I can’t honestly blame him.)

At any rate, there was a discussion about a new protocol Nick had scratched out as a hidden-data-transfer medium for MUDs, similar to ATCP and ZMP. It came about that JSON was a perfect fit for the protocol’s semantics, so I modified MUSHclient to add a scripted interface to a previously-created JSON library (called json-c). I’m really happy with how it turned out. I mean, I only wrote the glue between Lua and the library, but it was pretty interesting designing the glue nonetheless. The interface hasn’t been officially added to MUSHclient (yet?), but it’s in my GitHub fork of MUSHclient. (You can find my additions here, if you’re into that sort of thing)

Here’s an example of the interface in action:

chunk = json.encode{1, 2, 3, {foo = "bar", baz = {10, 20, 30}}}
print(chunk.to_json())

Output: [ 1, 2, 3, { "foo": "bar", "baz": [ 10, 20, 30 ] } ]

Admittedly, that’s pretty boring. The glue code is more interesting, but the end result is still useful. In my (admittedly very brief and minor) tests, json.decode():to_lua() was faster by 2ms than loadstring()(), which was a little surprising. JSON also has the advantage of being rather well supported by many languages, at least indirectly. The protocol specification Nick originally proposed used Lua itself as the data format, which worked but brought along some odd issues like defining or calling functions within the data. I rewrote a Lua protocol snippet as JSON and compared the two, and they were nearly identical, so there’s really not much to lose by using JSON instead.

With that pretty much done, now I’m working on converting MUSHclient’s help files from .hlp to the .chm format. Is it a lot of work? You bet. But at some point, somebody has to do it… But I’m using an sqlite3 database, Lua, and ltp to autogenerate the files, so at least it’s entertaining.

~Jonathan

2 Comments :, , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...