In slightly happier news, I've made quite a lot of progress on a new Java-based project of mine, called Nucleus. It's a modular, event-based system that heavily utilizes reflection, and the idea is to use it for MUDs. [grin]
Nucleus - The extensible MUD kernel
The idea behind Nucleus is to implement low-level details like networking and timers, basically supplying basic features, while also allowing third-party modules to be loaded for extra functionality. Each module runs in its own thread, protected from the other threads except through certain core mechanisms, such as events. And speaking of events, each module is backed by an event queue in the core, which calls the module's Main() method after it's done with its current event.
If a module really wants to run independantly of events, it can create a separate thread (or threads), but the Nucleus won't care in particular. [smile]
One of the planned modules is an interop module, acting as a binding between Java and another scripting language. There will be one interop module for any given language, and you can plug any of them into the Nucleus to allow part of the application to run in another language such as Lua or Python. This is the planned route to implementing MUD logic. [grin]You could even write your own language and binding module; I know many MUDs use a proprietary language for their scripting needs.
The Events System
One of the bigger obstacles for me was defining an acceptable events system between modules. Obviously, no module can be expected to accept any kind of event argument. After many days of thought, and one night of particularly hard thought, I came up with a pretty easy solution. There are three kinds of events in the Nucleus: Broadcasts, Events, and Requests.
Broadcasts are sent to every module. To allow this, I just create a Broadcast type in the core. Simple, because every module will have access to the core packages anyways. This could be used quite easily for input to a debug-logger module, which takes any broadcast it hears and writes it to a file. No module would be required to make any changes to accommodate the logger.
Events are sent from one module to another. This implies that the source module has prior knowledge about the second. This also restricts the kinds of events that can be sent: only ones the target module knows about. It's relatively simple from there to suggest that the target module define events it will accept, and have the source module import those events. The only part that's in the dark about the events themselves is the core, and it will solve this by looking for a @NucleusEvent annotation in module packages, reflectively loading their definitions as Class objects and storing them per-module.
Requests are much the same as Events, except that the target module is expected to return a value. Simply marking a named method with a @NucleusRequestable annotation is enough to trigger the core to load the proper definitions.
I want to put some code up here at some point, but right now I'm still working on actually implementing this system. [grin]