Friday, July 28, 2006
I came home late last Wednesday night and, against my better judgment, logged into SL to put in some time on the Garage of DOOM. This was a mistake, at least from a practical RL standpoint, but I knew that going in. I was not a happy camper Thursday morning. And employers are seldom amused when you show up to meetings with keyboard-shaped sleep marks embedded in your cheek.
But, in terms of SL and the GoD, it was a very productive session. I love late nights like that, where all of the background processes that have been percolating in the back of my mind suddenly reach readout all at once. I live for those hours long domino trains of minor epiphanies. Okay, I don't live for them. But they're a hell of a lot of fun.
This particular little string of brainwaves started with the monster rezzing subsystem. As you may or may not remember (if you've had nothing better to do than read past weblog posts on this project), the monster distribution system is composed of a central server and a series of remote rezzers. The player's HUD calls out for a monster, the server hears it, and the player's key is sent to the rezzers. Then the rezzers are sent monsters to be rezzed and programmed with said player's key. The net result is some types of monsters come into existence knowing who they should pursue.
That's the way it used to work. Then a light bulb flickered on above my head, and I realized that a player has no way of telling if a monster was called by his HUD or by another player. And that's assuming it's a multi-player game to begin with. It doesn't matter at all if there's only one player on the field!
Each player's HUD calls for monsters every 6 seconds or so. Said call can result in one to three monsters, depending on how close the total monster count is to the maximum monster population built into the server. There is no outward sign to indicate whether Bob's HUD or Fred's HUD sent the call for a monster. All the players know is that more monsters have appeared. So why bother designating an initial target by remote? Just let the monsters who care about such things decide for themselves!
That chopped out a considerable amount of communications traffic and processing, and made the monster rezzing process a fair bit simpler. Bob's HUD calls for a monster. The monster server decides how many monsters to rez, and sends the monsters to randomly selected remote rezzers. The rezzer detects a change in inventory, and rezzes the monster that just arrived. Less pre-processing, fewer interim steps, and no extraneous hidden comm chatter required.
Once the monster is rezzed, it waits for the next roll call of active players to be sent out by the central server, then scans for appropriate targets. Then it goes after the nearest player. The only difference is that some monsters (such as Vampires, Rippers, and Wraiths) remember this first target selection, and goes after that player exclusively until one or the other is dead. Less decisive foes (Skeletons, Mummies, Zombies) continually check to see which player is closest. Either way, they function just fine without additional pre-programming from the central server.
This also sorted out one of the most maddening intermittent bugs in the game. For some reason I was never able to determine, an unknown transient coincidence of game events would sometimes cause the monster to hang while waiting for the initial programming mentioned above. Normally , the monster would come into play listening on a predetermined, random communications channel. If everything went well (something like 98% of the time) the rezzer would send the summoning player's key on this channel, and the monster would stop listening (thus removing a now-unnecessary llListen) and leap into action. (The channel had to be reselected each new rez, because multiple rezzers are in chat range of each other, and monsters could end up programmed by an adjacent message.) But, for some reason I was never able to fathom, every once in a while the monster missed this call-to-arms, or possibly shut down its programming channel prematurely, and just stand there staring at the walls. Not only did the bug make the monster a sitting duck, it tied up the rezzer (which checks for obstructions before rezzing) until the player got around to dispatching it. Not good.
Now, thought, the monster comes into play ready for action. It immediately starts scanning for nearby avatars, and checks their keys against the active player roll call list when it arrives (6 seconds between roll calls). And since the roll call list is continually updated, if said monster should for some reason miss the first one (lag effects, processing/setup required on initial rez), the worst thing that can happen is it stands still for a little longer before it starts stalking its prey. All in all, Wednesday's work was a major boon for the efficiency and stability of the game as a while.
And then, Thursday, I spent over an hour tracking down a stupid list processing bug in the high score server, before realizing that the entire subroutine I was debugging was more-or-less superfluous. Some days ya' got it, some days ya' don't.