Potential Players:
Island Forge is now in Open Beta. Play FREE during Beta!

Monsters Kill Themselves

Island Forge No Comments »
Logic mistakes can be fun. Today I saw a dragon effectively chasing its own tail, attacking itself ... to death. Exploring the rest of the island, I found only dead creatures, who presumably suffered the same self-inflicted fate. Unfortunately, this will be corrected before anyone else gets to see the carnage.

2011 Week 1: Performance

Developer's Cave, Island Forge No Comments »
This week, I was distracted by my Internet connection failing regularly. A few hours on the phone and a couple cable modems later, I think I'm stable once again. None of this affects the test server, which has been running smoothly, even though it's (meager) memory is nearly fully allocated. Lately I've been focused on server and network performance. I've already significantly reduced bandwidth requirements for the server. Memory allocation needs some tuning, as many content objects can't be entirely deallocated at runtime yet. I'm just wrapping up another change, which will improve network performance, as well as lessen the overall burden on the client. I won't get into client-specific (e.g., graphic rendering) performance in earnest until I've addressed the remaining server memory allocation issues (next week).

Thread Monitoring with java.lang.management

Developer's Cave, Island Forge No Comments »
I recently delved into the java.lang.management package, in order to measure thread activity in my Potential RPG server application. Tools like VisualVM offer real-time probing, but I also like to have my applications produce their own statistical results. In this case, I'm logging CPU time (and a bunch of other stats) from my server application, which I use to produce performance charts (using the JFreeChart library). In java.lang.management, OperatingSystemMXBean reports the CPU time of your application process. The ThreadMXBean class reports the CPU time of each active thread. CPU time measures time spent being executed by the CPU. Contrast this with wallclock time, which may include time when your process is swapped out for other work. In addition, you can query user time, which is the portion of CPU time spent executing your application, as opposed to performing system time events such as disk I/O. Java tip: How to get CPU, system, and user time for benchmarking is an excellent article on using these classes. In particular, notice that ThreadMXBean does not report on threads that have died. To avoid missing thread activity, it is important to poll for thread activity at some granularity. I'm trying a 500ms polling rate, but my initial results imply that the thread I'm using to do this polling is using a significant percentage of the overall CPU time. Any thread activity missed by the polling granularity can be reported by subtracting the sum of sampled thread time from the total process CPU time. By increasing the polling rate, you can catch more short-lived threads, at the expense of more overall CPU time spent polling. In some cases, I'm using a thread pool (Executors.newCachedThreadPool()). By default, each thread will have a unique name, but this is not a requirement. By passing in a custom thread factory, I can name all threads that perform a similar service the same. In my thread polling routine, I add the CPU time of each thread by name. This way, even if several threads are actively performing some task, the CPU time is reported for the group. By monitoring my thread activity, I've found which parts of my application are working the hardest. I've also identified a few rogue threads (probably quick-and-dirty cases in which I extend Thread itself), which need to be wrangled. These might account for the CPU time not being captured by my polling. Overall, these thread monitoring results give me a good idea where to improve performance.

Java Click Count: Windows vs Linux

Developer's Cave, Island Forge No Comments »
Mouse events from Java Swing report the click count. When mouse events are generated within some click threshold (which should be an operating system setting), the click count increases. One common problem is processing single- versus double-clicks. Java does not hold back the single-click event (click count of 1) even when a double-click (click count of 2) may be forthcoming. This is for good reason: As well designed of a programming language that it is, Java cannot see the future. There are techniques (documented elsewhere) for dealing with this aspect of mouse processing in Java. The impetus for this article is mouse event inconsistencies between platforms. Particularly, click counts seem to be reported differently for different events on different platforms. Read the rest of this entry »

Usability, Performance, Scalability

Developer's Cave, Island Forge No Comments »
As of this month, I have transitioned from adding gameplay features into improving usability, performance, and scalability. Usability includes improving the game's user interface, as well as streamlining client behavior and server operation. For instance, the in-world shops and character inventory have been given a face lift. More technical issues include client network behavior and server configurability. Performance testing measures CPU and RAM utilization on the client and server, client-server network requirements, server database/disk read/write, and graphic processing capability of the client. Performance tuning will allow the client to run smoother and reduce server-side bandwidth, CPU, and RAM requirements. Scalability is related to performance, dealing specifically with the capability of the client, server, and network to handle increasing numbers of players (and therefore islands, creatures, battles, items, etc.).

Using JTextArea in a JList

Developer's Cave 6 Comments »
JTextArea is a convenient Swing component to use when word-wrapping is needed. To display a list of multi-line messages, for example, the obvious solution is to use a JTextArea as the ListCellRenderer Component for a JList (within a JScrollPane). However, you will soon find that the text often does not end up word-wrapped as expected. After reading post after post of mystic incantations, none of which actually seem to fully work, I present my solution for using a JTextArea in a JList: Don't. Read the rest of this entry »

Swing Model-View-Controller

Developer's Cave No Comments »
It's old news that Java's Swing GUI toolkit follows a deficient Model-View-Controller (MVC) architecture. In most cases, Swing fuses together the notion of the View and Controller, but offers a separate Model. At least, that's what the naming convention implies. For example, JComboBox should be a View-Controller to a ComboBoxModel. This particular case failed me today. Read the rest of this entry »

BetaAlpha Progress

Island Forge No Comments »
It has been nearly 2 entire weeks with no updates for the BetaAlpha playtesters, giving you plenty of time to ramp up your characters... before I dash them to the aether once again. To let you know where I stand, I'm currently knee deep in (what is scheduled to be) the last major wave of gameplay integration. (This is a promising position, as I was neck deep about a week ago.) More specifically, the items and inventory are [redacted] ... on second thought, just wait and see. A BetaAlpha update is planned for later this week.

“Now... bring me that horizon.” -- Jack Sparrow

Comparable Max Function

Developer's Cave No Comments »
Here's a helpful method for returning the maximum of two Comparable objects. Do the Java APIs provide this somewhere?
/**
 * Return the <i>maximum</i> of the two arguments. If the arguments 
 * are <i>equal</i> (as defined by the Comparable contract), the
 * <i>left-hand-side</i> argument is returned.
 */
public static <T extends Comparable> T max(T lhs, T rhs)
{
    return rhs.compareTo(lhs) > 0 ? rhs : lhs;
}

Network Improvement

Island Forge No Comments »
Although my overarching guideline during this phase of development is to focus on gameplay and features, I decided it was necessary to revamp the network layer of the client-server platform. This was primarily a consolidation and cleanup effort, motivated by nagging session management issues, resulting from overly-complex code. I have not yet seen the SLOC drop, but I'm expecting it to be significant. The end result is a cleaner, simpler, more robust network layer. As a happy side effect, the streamlined threading model and byte management should theoretically improve overall efficiency. Alas, having not yet performed any detailed measurements on the previous network code, I will not know how much better the new routines are. Although technically significant, Playtesters shouldn't notice a thing (except for not being locked out of the server due to broken session logic). Then again, I could have introduced a whole host of new issues... Have at it! Update: The SLOC drop is in. Roughly a couple thousand lines of code less, and all the better for it.

"Fortune favors the bold." -Terence