Monday, December 17, 2007

I hate coursework...

There's a small delay in finishing up all the Game handshaking and getting the initial scene up. I'm currently occupied with a load of coursework which I have to finish because I screwed over a bunch of courses last year and the year before.

Really stupid, but if I want to start my graduation by the end of the college year, I better get all these courses patched up. And because of that, I have less time to work on Dune.

But, I found out I also have to re-do Network Programming(Why I failed that course is still a complete mystery to me), so I'm going to attempt to convince the professor to allow me to submit the network code of Dune. Mainly because it's more cooler than writing lame ass chat server(Using UDP and RMI), but also because it gives him a really cool example to show during classes.

So, I need to finish 1 more assignment for data structures / algorithms(Write an AVL Tree), and then I can submit all the code. One down so to say.

Wednesday, December 12, 2007

I need to re-think my class structure a bit...

I was reviewing my network code in the train on my way home today, and I came to the conclusion that I should think it over a little bit before I start expanding the code.

At the moment, on both the hosting and the connecting side, I have either a Server or Client as Task. The task is placed into the TaskManager and therefor updated each frame. Both the Server and the Client implement various properties via an interface(INetworkConnection). This is the connection status, connected players, etc. This is fine.

However, I also need to receive information back FROM the Task, such as when a new client connects, or when the user interface needs to update information. For this, the INetworkConnection is insufficient, because I need various events which come either from the lobby or the game. Such as PlayerConnect, PlayerForfeit, etc. It's a really bad idea to go from lobby -> Server/Client -> LobbyState. Messages would be re-routed via the INetworkConnection, which would slow things down AND clutter the INetworkConnection interface with too much useless crap.

I intend to counter this by creating ILobby and IGame interfaces, which the LobbyServer/LobbyClient and GameServer/GameClient would implement. These interfaces could then contain the function specific things for the lobby/game(such as a joining player for the lobby, and a forfeiting player for the game).

Using this system would probably be more efficient in terms of code maintenance than cramming it all into 1 gigantic interface. It would also prevent the Server/Client task from having to add GameStates, which keeps the seperation of UI / Logic intact.

I should have some in-screen screenshots soon, altho I probably need at least till sunday to buffer up all the player interaction with the game and send these commands over the network to the server. I need to change quite some code in the PlayerInput.cs file(Which basically contains all the code related to interaction from player to game).

Friday, December 07, 2007

Background loading of assets

Before I wanted to start out with the actual networking part, I wanted a way to load the assets from disk in the background, and before the game was actually running. This to prevent slowdowns in the network simulation when a new building/unit was constructed and the asset had to be loaded from disk.

In order to do this, I wanted a nice front-end(A progressbar to display the loading progress) and a back-end: A background thread which did the loading and put each asset into the TextureManager.

I started out with the ProgressBar, as the asset pre-loader was half done. It just needed to be modified to be able to work in a thread.

The progressbar is just another Control for my game. It basically draws it's outline, and based on a Value it shows a nice (blue) bar. I initially had a problem with the outlines not showing up. But, this is related to the way how D3DSprite and D3DXLine render. I solved the issue by doing a Sprite.End() RenderLine Sprite.Begin(), but that cuts down on performance, so I need a better way. I reported it as a 'tweak' in mantis, so I don't forget about it.

Loading, please wait...

The background asset loader was also heavily modified. I initially wanted to try and run it while performing my normal gamestate functionality, but I found out it's way too slow for that. The change was that when I constructed the Preloader, it would parse the list of assets to load and store these, and then with a call to LoadNext() it would take the next asset from the list and load it. So, I shoved that into my BackgroundLoader class, and all was done. The BackgroundLoader is a thread that keeps running until all loading is done, and once it loads the next asset, it will increase a counter, so I can poll how many assets are done and then update the progress bar.

However, I was quite shocked when I tested out the background loading process. It's slow as hell! It took 94 seconds in debug build and 87 seconds in release build to load all 58 assets in just 2 colors. Image how long it'll take when you're playing with 6 friends...

Slowpoke is slow :(

So yea, background loading is in, except it's terribly slow. In fact, it's so slow, it's unusable to develop the network play with, because having to wait ~1.5 minute before being able to test something out is too much for me.

For the coming tests(The actual network gameplay), I'll be testing with a reduced preload set, just a handfull of units / buildings.

Tuesday, December 04, 2007

A peak into Dune's protocol

I'm currently happily coding away at the Lobby for the game. Most of the code is in now, with the exception of colors / factions / map. I'll add in which map will be loaded soon to the host as a command line switch (dune -host 2 -name Host -map mp_test.map). I also added in most of the code for the LobbyClient. When connecting to the server, it will display a nice "Connecting..." text and when handshaking between client/server has been completed, it will show the same text as the lobby(ie, n out of m connected players).

Now, let's dive into the messaging system:

I decided to cut up the system into small, manageable components. This means there's a Server, LobbyServer and GameServer. The Server object manages the connections and routes the messages to the sub-system. The responsibility of the LobbyServer / GameServer should be obvious.

Because I wanted to seperate out the systems, the first byte in a message is the 'targeted' sub-system. The 2nd byte is the message and the 3rd and beyond bytes are message specific:
1 byte 1 byte n bytes
[Sub-System] [Message] [Message Specific Data]

There are no fields in my messages which specify the length of data. Because Lidgren handles all the low-level stuff, it will wrap my data into UDP packets, and reading data back is as simple as msg.ReadString() / msg.ReadByte(). No need to check for correct length, or if all the data is valid: Lidgren does that terrible work for me.

The pro of my system, is that I don't get insanely long switch statements to handle all the messages. This is how my 'main' message pump looks on the server:


It's quite simple, and adding new sub-systems is a matter of seconds.

The ProcessMessage() then reads the next byte in the message, which contains the message, which is used to pass it to the correct handler. That looks like this:


How each message is composed isn't really that important. I can give you the exact details, but it sounds more boring than interesting.

Monday, December 03, 2007

We get signal!

Hmmm, I think I used this title before… Not sure. And who cares anyway? It’s Sunday evening 22:45 now, almost time to get some shut eye before heading off to work.

Before diving into my bed, I’ll write up some nice post on my progress on the Dune Networking Components, and post it when my internet connection is back up again.

At the moment, I can connect clients to the in-game lobby. It will accept their connection, and once it receives a handshake, it will return their player ID, and a list of all connected players. This needs to be expanded with a faction and a color, but that isn’t in yet.

This is how the Lobby looks like server side:

Looks pretty sweet eh(I think I broke my FPS counter… There is no way in hell that runs at 35 FPS)? Well, it’s far from done, but I’ll get to that later on. This is what the basic lobby still needs:

  • Handling of disconnects
  • Player colors
  • Player factions
There are more things required for the lobby, such as map selection, game options(Starting credits, starting units, how do we handle starting points(fixed / random), spice blooms, etc.). But for the sake of simplicity, I don't add those in. It would only complicate things while I want to get basic networking up and running.

Don’t get me started on the client side… That one just connects and sends the handshake. Nothing else yet. That's next up.

For the networking library I’m using the Lidgren Network Library. It’s pretty awesome if you’re working in .NET. It’s extremely easy to use and does all sorts of things for you, such as internal clock synch, message re-sending, etc. Speaking of which, I should see if there's a new version out the library. The version I'm using is a few months old.

No technical details to explain to you guys yet, so you have to wait a bit longer. The cool technical details come when I start working on synchronizing the simulations.

Let's get connected!

It’s been a good month(!!!) since I did a update on the devlog. So I figured I’d give you guys a new update on how things are going. The updates are going in a bit weird way this time, because I made an oopsie with my internet bill(I accidently forgot to pay a month, and they put a nice “Please pay us and you get internet access again kthx” banner whenever I browse to any website.

That’s the annoyance with all the moving around, you miss a bill and then they shut you off. However, they put a filter on my line at Friday afternoon 18:30, 30 minutes after closing their billing department. If they did it an hour earlier, I’d fix them up the bill immediately and there wouldn’t have been a problem.

But, this is good news for Dune. As I can’t waste my time on the internet, I decided to start coding up the network components for Dune.

Design

As opposed to earlier posts, I decided to actually go with a Client / Server setup instead of a star setup. The P2P star is difficult to set up and I couldn’t figure out a way to be 100% be sure all clients would have the correct amount of data to make sure they don’t go out of synch.

Downside in my current approach is that the host will have to have at least n times as much bandwidth as regular players, where n is the amount of players – 1. But, in a time of broadband, I doubt that’ll be a problem.

I still intend to go with the turn-based approach: Each set of commands is send 1 (or 2) turns ahead of the current one. Turns are executed at a determined interval(for instance, 200ms) on authority of the server. So, when turn 1 is running, and the server knows all the clients have received the commands required to execute turn 2, it’ll send a StartTurn 2. However, this will mean, that if 1 client has a roundtrip time above the turn-length, the game will start to lag at some point. In order to prevent this, I intend to add some form for heuristic to automatically adapt the turn-time based on client pings. However, this won’t do magic, because if pings are above 300 ~ 400ms, turns will take too long and players will notice lag between commanding a unit and actually executing it.

Implementation

At the moment, I’m implementing the basic server / client code. The server runs as a Task in the game, as it needs to be updated at least once per frame. Next to it the client runs its normal simulation at the moment.

I’m still doubting if I give the server its own simulation: That would mean the hosting player would run the game twice: Its own copy, and a server copy. On slow machines, this would mean it would lag(Or to be more precise, run at low FPS).

However, I could hand the Server task a reference to the client simulation and use that as a base. It could generate checksums of that and request checksums from other clients to compare and kick out-of-synch players. But, that’s too far ahead.

I intend to write the code that hosts a basic lobby and let’s other clients connect. No graphical goodness tho, just basic command line stuff like:
dune2.exe –host 2 –name or dune2.exe –join -name

Once a client can connect to the server I can add the code to start a game and just show the same scenario on both game instances. I think that’s a challenge on its own already.