Friday, March 29, 2013

Server Work

I haven't posted much in the last week or two.  I have been making progress, but largely I've been integrating the game client and simulation engine with the server system I'd written last year.  So, nothing glamorous, just a lot of 'oops!, I shouldn't have done it that way' sort of restructuring going on.

There are som interesting bits.  The simulation engine references XNA in order to use the various types (vectors, matrices, quaternions, etc,) as well as being able to load models.  Per triangle hit detection is one of the requirements, so I definitely have to have the model data and account for animation movement on the server.  So I figured I'd just reference and use XNA there, though definitely not actually running via the Game class of course.

I quickly realized that there was a serious problem.  Loading a model with XNA not only loads the data in the model file, it loads the textures and puts the model's vertices and indices in VertexBuffers and IndexBuffers as well.  Texture2Ds, VertexBuffers and IndexBuffers live on the video card.  There's definitely no guarantee that whatever machine the server is running on would have a DX9 video card; likely they'll be virtual anyway.  Plus it's just a waste.

Unfortunately there's no way to modify that loading behavior.  I considered looking up the format of the XNB files (the binary format XNA compiles resources to) and reading them directly, but then I realized that MonoGame does that already.  MonoGame is an open-source implementation of XNA.  It isn't entirely complete yet, so I can't use it on the front end, but for the server it should be entirely enough.

Even better, since it is open source, I was able to go into the ContentManager class and add some hacky code that allows to you instantiate a ContentManager and load a model without loading any shared resources (i.e. those that would reside on the video card).  Exactly what I needed!

There were some sticky problems with integrating this, however.  Since the SimulationEngine project was referenced from both the client and server, and both XNA and Monogame reside in the Microsoft.XNA.Framework namespace.... yeah, it really blew up at first.

Initially I wrote some interface code that did a bunch of casting and conversion between the two, but that was just ugly.  In the end I refactored the base SimulationEngine, making two additional projects, SimulationEngineClient and SimulationEngineServer.  Both these projects actually link to the files in SiimulationEngine, making them exact duplicates (though each overrides a few files).  Then SimulationEngineClient links to XNA, SimulationEngineServer links to Monogame.  Since they reside in the same namespace, nothing need change.  Boom, problem solved.

Anyway, each of these is inherited by RogueMoonSimulationEngineClient and RogueMoonSimulationEngineServer, which implement Rogue Moon game specific logic.

It is a bit twisty, but the code is pretty clean, and so far it hasn't presented too many problems, now that I have this all worked out.  It took me a while to get here, though!


No comments:

Post a Comment