Although I don’t actually feel like writing a blog post (I’d rather work on the project instead), there are a few reasons why I convinced myself of doing it anyway. First of all, it has already been 2 weeks since my last post and I kinda promised myself to keep this thing updated. A second reason is that some people requested more implementation details, mostly concerning the server-side and the needed connection for that. And last but not least : the mid-term evaluation is coming up! With this post I can present the mentors with a nice overview of my work so that they can easily let me pass ;).
So what did I achieve? Most of my time was spend on an asynchronous networking layer. Now for those of you who don’t know what that could possible be, I’ll explain the difference between the two options. With my first draft of the layer, which was thus synchronous, the game would be blocked during a server request until a reply has been received. With asynchrony the application just keeps running while a separate thread takes care of the incoming requests. This has the extra advantage of being able to show progress widgets and cancelling options.
Developing a working solution of this, is actually not that hard at all. The difficulty lies more in making an API that’s easy to use for not only myself, but for every developer that needs access to the server. This resulted in an iterative process where I had to rethink the design 3 to 4 times before reaching a nice level of usability. The fact that thread safeness had to be kept in mind, didn’t exactly make everything go smooth. The result consists of a priority queue to which different types of requests can be added; the XML request will probably be used most frequently. When adhering to my XML reply standard, the manager will automatically parse the result and check for success. The initiator of the request can then obtain extra info from the answer and he can even extend the request to define the callback which will be automatically called after a response has been received.
In my proposal I stated that I wouldn’t need to extend the GUI engine to obtain my desired lay-out, unfortunately I keep discovering bugs and hacked-in functionality that doesn’t translate to what I want to use it for. The most time consuming task here was making a basically new list-widget, that is furthermore backwards-compatible with the old list widget as it was already widely used. Now why did I had to renew it? Well the old widget didn’t fully support columns. The header did, but the content did not. With a tab hack though, the content could support up to 2 columns if they where left-aligned. Of course this doesn’t suffice for my server-selection screen and thus I improved it to fix the alignment and allow more columns. I present you with a screenshot of the temporary server selection interface above.
Other changes to the GUI engine include being able to change the color of text while already on the screen, a callback to the current screen when a dialog(pop-up window) is closed and a way to intercept closing attempts of such a dialog. I also had to do some more complex work on the ribbon widget (a row of icon buttons as used in almost every menu screen). For my project I need to be able to change the actions a user is allowed to do, depending on his state and rights. For instance when someone is signed in, he’ll have the option to sign out. This is a separate icon button and thus I needed to provide a mechanism to show and hide buttons. This is not so evident, as the lay-out has to be recalculated on every change as well as the order in which buttons get selected on key navigation.
Automatically signing in : an interesting feature which I had marked as optional, but got implemented anyway because of it’s helpfulness in testing the registered-user-only features. So yeah, a checkbox got added to the login dialog to remember your session. I’m not going to put another screenshot of that in here, as it already had 2 appearances on my blog. Nevertheless you can just check out my branch and see for yourself ;).
As requested I’ll now go into some database stuff. I was planning on doing this quite extended together with a diagram of the relations, but this post is already getting quite long. The first adjustment I did, was replacing the database engine with InnoDB, everywhere MyISAM was used. This allows me to use foreign keys as constraints and has some other advantages (but also disadvantages) like row-level locking instead of table-level locking, that I won’t go further into. The foreign keys allow me to do checks on database level. A field in one table, gets linked to a field in another table by value. With these properly set, I can’t for instance let people join non-existent servers or let a user that doesn’t exist be host of a server. Another cool use is that when a key gets deleted in a table, it can delete everything that is related to it. For example when deleting a server, every connection with that server is also deleted.
The session table has as engine MEMORY, which basically means it is never saved to disk. It’s faster, but all data is lost when TuxFamily’s server decides to shut down. Which is not that bad, as users will just be signed out.
No harm done.