Beautiful weekend here in Atlanta, Georgia, USA. Sunny, no clouds, and up to I believe 80 degrees (26 Celsius) this weekend. Naturally, I spent most of it indoors. Part of Friday evening and Sunday I spent creating this application just to see if I could do it. It pings the gaming servers for Dungeon & Dragons Online every minute, a massively multiplayer online roleplaying game. It solves 3 extremely niche problems:
- You need to have the DDO game installed on your computer to get server status updates. This is a web application (or a executable widget); no installation necessary.
- You need to login before you can see them. Using this app, you just visit whereever this app is hosted or double-click the executable on your desktop.
- You need to have 51 megs to spare. This app takes 11 (less in a browser).
Why You Should Care
Like I said; extremely niche. That wasn’t the point, however. The goal was to set a challenge for myself, and learn in the process. A nice side-effect is some code I feel others can learn from.
- This is a pefect example of how to over-architect an application. This is a widget, not even an application, so the need for an Application Framework such as ARP was definately not needed and major overkill.
- Same code, 2 different runtime environments: Desktop and Web.
- Using a business delegate to handle all the “crap” involved with getting the business rules working.
- Using a business delegate to handle the security context. (Not sure if this was a good idea yet or not).
- How to get the new version of mProjector to handle Flash Player 8 filters plus transparency.
Digital Thorns in My Side
There were 2 things that really bothered me during and after development. The first, which I already mentioned, was allowing the business delegate to handle the security context. Basically, Flash Player running as a projector is not bound by the Flash Player security sandbox. When the Flash Player is not running in an executable, it is. The way I know is by checking for the existence of mProjector API’s. They are baked in when the mProjector exe file is made; stuck on global as static level objects with methods I reckon. If they aren’t there, you aren’t running in an mProjector created exe file, and thus are probably running as a SWF file, usually on the web in a web browser.
While I agree that the business delegate is the correct place to handle coverting the XML received from the server into a usable ActionScript class value object, I don’t necessarely agree it is the best place to handle security context. I DO agree that it certainly the easiest. Since he’s already making asyncronous calls to the server for specific data, why not just put it there? :: shrugs :: For me, the jury is out on that one.
The second was how I’ve allowed Commands to call a callback function. To me, you’re code that is calling a command usually wants:
- something to happen
- to know when it’s done
- to get the data from the operation if any
Getting something to happen is easy; that’s what Commands do. Chunks of code usually responsible for getting or modifiying data, whether that be from local classes, firing other Views to do things, or making server calls via a business delegate (if applicable).
To know when it’s done is accomplished by my CommandRegistry; you can specify a callback function that the Command calls when it’s completed. This is called whenever the Command feels like it. This could be immediately, or after the business delegate has returned a result or fault… or never if you so choose; it is optional after all.
That last part, however, has got me stumped; mainly because I haven’t really thought through how to solve it. How does your result function “know” what it is getting back? It doesn’t, and that sucks. ResultEvent has a property called “result”. This property is not cast on purpose; this allows anythng to be passed into a ResultEvent. That way, if you talk to PHP, Java, Perl, Ruby, ColdFusion, or who the heck ever, you can throw that result into a ResultEvent, and you’re business delegate will get it and know where to look for it. But it’s the business delegate’s job, if your Command decides to use one, to massage and/or convert that into something usable and pass it back to the Command to handle. The Command can then easily pass this back to the result function.
The problem is, how does the instance invoking the Command know what the Command returns? Cairngorm users would argue, “A Command doesn’t ‘return’ anything; merely sets data on the ModelLocator, and bindings fire, and everyone’s informed and happy.” Uh…ok… so do we now declare that all Commands return true or false in their result functions? That certainly brings some order and understanding here, but greatly limits the functionality that result handlers provide. Remember this is Flash, we don’t have bindings like Flex does. There are some binding classes, sure, but they aren’t implemented as thoroughly nor as transparently as they are in Flex. Thus, it’s typically easier to get a result function and handle View updates manually. To me, this is justified since Flash projects aren’t as large in scope so this is more realistic a scenario anyway. Besides, making other datatypes act like Array’s do via DataProvider where changing an array via the DataProvider API methods dispatches a modelChanged event isn’t that diffucult to do.
So yeah, you could do boolean return values, but that is limiting. How about Event objects like ActionScript 3 does? Flex Builder 2 will actually give you compile error if the event type your event handler defines is the incorrect type. So, if you register for a MouseEvent, but define this in your event handler function:
function onPressed ( event : KeyEvent )
Flex Builder 2 will throw a compiler error.
However, you don’t register for Command events, you fire them off, and register a callback. I’m finding it hard to find some strongly typed way of “knowing” what a Command returns in it’s result function.
Anyway, I really had fun over-doing this widget and having it work in 2 runtime contexts (desktop vs. web) and 2 security contexts (desktop vs. web). It uses my modified version of ARP. Hopefully you can learn something from the code!
*** Warning: Currently, the web app utlizes a PHP proxy script on my server to get around Flash Player’s security sandbox. My suggestion is to host the PHP script on your own server, assuming you deem it secure enough, or some other proxy, and point your ddo_server_status_config.xml config file to have the proxy point to your server. I have no problem with you using mine (if you do nothing or don’t know what I’m talking about, it does by default), but if mine goes down (meaning they ban my server’s IP or my host bitches about bandwidth), then you’ll be forced to use your own, someone elses, or the exe instead. ***
To utilize the exe, just double-click the “DDOServerStatus.exe”.
If you wish to host the DDO Server Status app on your own site, simply do the following:
- upload the “DDOServerStatus.swf” to your site
- upload the “ddo_server_status_config.xml” next to the SWF
- put this HTML code in your webpage, ensuring the 2 paths to the SWF are correct:
<embed src="DDOServerStatus.swf" quality="high" bgcolor="#ffffff" width="136" height="330" name="DDOServerStatus" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>