So ok,
weve seen the mess that is the Internet, and all the pitfalls,
what can we do about them as game developers?
Rats,
I knew someone was going to ask that. I thought I was done, Check
please. But noooo, more stuff to have to type up. Oh well.
The first
thing we should do is define the difference between client/server
type games and peer to peer games.
Peer to
peer involves two or more games talking to each other, each running
the game itself and only exchanging input data. This reduces network
traffic to a minimum, but brings several other problems to the
table, like coping with lost traffic. This is far more important
when more than one game is running, since contention occurs over
who is correct and who is not. Variance in game play can get very
sticky in these situations, as each game must stay synchronized
with the others. Additionally, each game must wait for the input
from the others before it can simulate the next frame remember
playing DOOM and it would lock up momentarily?
Client/Server
involves one machine running the game and dictating to all the
clients what the state of play is and what they should be displaying.
Effectively the clients become pretty much dumb terminals transmitting
the user input to the server, and letting it handle almost everything.
They draw the scene the server tells them to display, and play
the sounds the server tells them to play. Actually, it's not quite
as bad as this, as the server does on occasion tend to offload
functionality onto the client, but that's the basic idea.
What I'm
going to discuss has more to do with Client/Server type setups
than peer to peer since almost all online type games have some
degree of Client/Server architecture to them - every game has
to have one client that 'hosts' the game and is considered 'correct'
in the case of world event contention between peers. (Unless they
dont, in which case, youd just get an out of
synch error and quit.)
Ok, now
on to our problem list - The TCP/IP selection is a no brainer
- we don't have to discuss that anymore.
One down.
Packet
bloating. This one can be tricky. Obviously a max packet size
in the code is in order here to stop modem buffer overloading.
We here at Raven are actually implementing a floating max packet
size, for those people who are running over a local network, or
that have large bandwidth available to them. When you hit a packet
that breaks your buffer size, the secret is to split the data
into two smaller chunks - only send in the first packet what is
really necessary to be there that instant. Data like entity movements
and so on. Stuff like chat messages can wait till the next packet,
since no one is going to miss that being one packet late. Still,
tough decisions need to be made as to what's important and what
isn't, and sometimes this can make the game feel a little sluggish
and unresponsive. This is where the floating packet size can be
helpful, since it should remove that feeling from those with large
bandwidth or running local games. Not the best solution, but one
that's worth a try.
Other
stuff that's worth thinking about includes tokenizing text messages.
If your server is sending a lot of preset text messages, it makes
more sense to have these pre-loaded on the client, and just send
them a text string reference number rather than the whole string.
This reduces out message traffic considerably. The same trick
can be played with sending down filenames when the server asks
the client to load something. For instance you can break down
the file into path names, and then filenames. If you are asking
for a bunch of sound files to be loaded, then only send the path
once, and from then on, refer to the path as a token in the string.
For instance we'll ask the client to load
"sound/weapons/death.wav".
Once the client receives this string, it will store away the path
as a token, and the next time we want a sound, we send "%1pain.wav"
and the client knows by the %1 to go away and use that path it
got first time to load this sound. Little things, but they all
help.