Twitter  YouTube  E-Mail  RSS
The One Man MMO Project
The story of a lone developer's quest to build an online world :: MMO programming, design, and industry commentary
The Evolution of a Feature
By Robert Basler on 2017-08-28 11:47:49
Homepage: email:one at onemanmmo dot com

Debugging finally started going a little faster this week. Iteration time - the time it takes to make a change and then test it - has been terrible with Nemesis mode. Typically, iteration time with Miranda is about a minute which isn't bad, but with the new server for Nemesis mode acting up, I was constantly having to shut down and restart everything which takes at least 10 minutes and really chews through a work day. As of Friday I can finally play several Nemesis matches in a row without having to restart everything.


The last thing I worked on this week was penalties for players who disconnect during a match. I thought it was interesting because it illustrates how even simple features sometimes have to evolve through a number of iterations before a workable solution is found.

Miranda is a little different from most multiplayer games because it allows players to log out and log back in without leaving a Nemesis match in-progress. If a player disconnects for too long though, the match ends and the player gets a penalty for quitting. The nice thing about this system is that if you have a temporary network problem that causes you to disconnect from the server, you can still re-join a match in progress and finish it.

There are four pieces involved in recording a penalty. The Session server keeps track of all the elements of a Nemesis match, the players, game rules and more. The Sim server runs the game simulation, moving the player's tanks around and figuring out damage from weapons. The Login server keeps track of who is logged in and who isn't. The final piece is the database which stores data for the other servers.

The first pass on penalties, I did the standard "find something similar, cut, paste and tweak" that programmers do when they have a lot of new code to write and they're just trying to get everything roughed in so they can start playing with it. I had the new Session server sent a message to the Sim server which then looked up the logged-in player and changed the stats to apply the penalty. This took about 15 minutes to code and fell apart the first time a player actually got a penalty.

When a player logs in, the Login server assigns them to a Sim server which then loads the stats for the force the player selects. When the player logs out, there's no longer a Sim server with those stats loaded to apply the penalty. Since for a disconnection penalty most of the time the player is offline when penalties are doled out, that is a problem.

To make things even more complicated, to reduce the load on the database, each Miranda server stores copies of the database data for fast access. As a result, the current data for everything in the game is usually stored on one server or another, not in the database. The tricky part then is that those stats are managed entirely by a Sim server, but there is more than one Sim server. If the Session server wants to update the penalty stats, it needs to be able to negotiate with a Sim server to make those changes. But remember I said that players are only assigned to a Sim server when they are logged in?

The second attempt I was going to have the Session server update the stats directly on the database if the player is offline, bypassing the Sim server entirely, but have the Sim server do the changes if the player is online. I worked on that approach for a few hours. It works fine if the player is offline because the Sim server will load the updated stats the next time the player logs in. And it works if the player is online. But what if the player is logging in or logging out while the messages are going back and forth between the servers or the database is being updated? Trying to manage all possible cases while avoiding penalties not being applied or being applied twice gets very messy.

The third attempt I was going to have a Login server update the player stats, and a Sim server update the force stats whether the player was logged in or not. That was only marginally better than the previous solution, still with lots of messy cases and complications. That attempt lasted about 30 minutes, then I realized I needed to get out of the office and maybe a simpler solution would come to me.

I went for a walk. On the way back to the office I figured it out. The solution is super-simple to implement and is guaranteed to never apply a penalty too many times, or too few.

When a player gets a penalty, the Session server writes the penalty info in a database table. Each time the Sim server loads a force, it checks the database to see if there are any player or force penalties that need to be applied, and if there are, it applies them then deletes them from the database table. The only issue is if a penalty comes in while the player is logged in. In that case the penalty won't be applied until the next time the player logs in. (I could have the Sim recheck periodically, but given how often players log in and out, I don't think the extra load is worth the improvement.) The implementation adds a small load on the database, but as far as correctness and simplicity, it's really good.

The final solution took about three hours to write, I'll be testing it out this morning.

New Comment

Cookie Warning

We were unable to retrieve our cookie from your web browser. If pressing F5 once to reload this page does not get rid of this message, please read this to learn more.

You will not be able to post until you resolve this problem.

Comment (You can use HTML, but please double-check web link URLs and HTML tags!)
Your Name
Homepage (optional, don't include http://)
Email (optional, but automatically spam protected so please do)
What is four plus three? (What's this?)

  Admin Log In

[Home] [Blog] [Video] [Shop] [Press Kit] [About]
Terms Of Use & Privacy Policy