Multiplayer draft document

Everything related to the code /
Tout ce qui touche au code
Post Reply
User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Multiplayer draft document

Post by Cire » Thu Nov 02, 2006 4:03 am

This is a early draft document that outlines multplayer support and concrens. It is just a draft and is open to suggestions and comments.

Introduction:
The goal or goals of this document is mainly to outline and establish some rules and regulations that will govern multi-player within TA3D. It is by no means complete and defantly not concret. It is my goal to attempt to outline what we will need to do to the engine, and perhaps discuess some techiniques for handling just that.

The Engine:
Though I havn't looked at the engine source code in over a month or more, and i'am only going on what I can recall from memory, the engine is going to require some heavy modificaitons to allow for multi-player support.

Currently and please forgive me if i'am wrong, a player is stored in a globaly chunk of differnet variables. We will need to modify this to instead be stuck within a structure, or better yet a class, and then apply this player to an 'array' or class array or a group of players. Even the AI player should be encompassed within this array. It will make for much easier handling within the engine when we can pull from the array and handle each player on a whole.

What I mean by this is that our code will look and behave alot more smoothly when we can handle a player(s) that is easy to find and lookup within an array or group rather then the local player and ai player and remote player. For the most part we should let the engine 'assume' that all players are local and handle them as such. It will be the part of the multi-player support that will seperate difference, and ai handlers that will handle ai player actions and so on.

We also need to have the engine at startup preform perhaps some 'tests' that should produce some numbers that are meaninful. What I mean by this is have the engine do some guess work on how many units we might be able to handle. This will come in handy later in multi-player we we are looking around for servers that will help increase game preformance by sharing loads.

The engine itself should perhaps step back and take a tick approach, it would be key to implementing good multi-player support and allow the game to stay completly in sync, since a 'tick' wouln't occur till everyone was ready for it.

Multi-player support:
The first step in mulit-player support would perhaps be adding our lobby that the user would be dumped into. Here we would pretty much just show the list of options for hosting our game, selecting the map for example, disabiling units, resource settings and more. I am going to strongly suggest that we use a tcp/ip protocal for this and only this as well as in game chat, since ack's shouln't hold up game at all on chat it should be ok for this and only this. We might also wana add features for downloading maps that we might not have as well as units that we don't have providing they are 'used'. Of course the user receiving the map/units should be asked first to make sure they want to accpet the file(s), and we could set this up so that multiple users with the same file would send different chunks to the player for ultimate download speed of said file. This is just a thought.

Now i'am going to use the term 'server' loosly, since I believe that we should write this serverless. Now assume for a moment that we have 4 people who want to game together. we will call these users 'user a', 'user b', 'user c' and of course 'user d'. User a, hosts the game, now user b,c,d could connect to user a to join that game, but I think its better if we allow say user b to join with user a and user c could join to user b, and user d could join to user a, b or c. So in essence 1 starts hosting the game, and others join into the host, at that point any other joiners could join to any other user who is in the game.

Why? This would allow intelligent match makers to set the host as the best choice to host the game, and pair up users to join in with thier best connection status. Of course once the user enters the lobby he or she would then open a tcp/ip connection to the group of users. So we would require 1 listening port and one out going port in tcp/ip for each and every user in our game.

Why? suppose our host drops to user b, its always nice that he could stay in the game if hes still got connections to c,d. or suppose he dropps totally, its always nice that b,c,d could do some 'rehost' calulcations and the game continue.

so our tcp/ip connection would serve as nothing more then a way to pass starting data back and forth, as well as game chat. Of course we probably want to do some decent handshaking to ensure the reliatability of connections and what not, after all we don't want no spoofing done here now do we. :)

In Game Mulit-Player support:
I'am going to stop here till I have had time to further study the engine and examine exactly what composes up units, maps and so on. One thing I need to look at is if we are using traditional floating points 32 bits (4 bytes), where we might get away with using 16 bits. if we can reduce this in most place in game accuracy on fpu math might be enhanced as well as reducing what we need to send accross piplines.

We should be looking at using UDP protocal to handle most of our in game packets, and will probably want to number these and keep track of say the last few we received from each player so that if some are dropped we can re-quest' them again.

I will now take a week to study the engine before i further enhace the document. Feedback is now welcome.

++Cire.

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Thu Nov 02, 2006 5:36 am

You said in the IRC meeting that we shouldn't think about ipv6. The preferred way to write socket code is with the new api which is protocol independent. I am writing a couple classes to make connecting and managing connections easy for ta3d. If you would like, please send me your 'strong' sockets code and I'll see how hard it would be to make it ipv6 compatable. It is true that ipv6 is currently very unpopular, but that is because no one wants to write software that supports it! The current rewards would be for ipv6 users to avoid NAT firewalls, but in the future your performance would be enhanced by ipv6 multicast etc. In either case, the game uses ipv4 automatically when ipv6 is unavailable or is deactivated in the options. That's why the new api is better. It is often the case that old programs with the old sockets are written so that updating it for ipv6 is really hard.

As I was discussing with zuzuf, network traffic would be best reduced by not sending change in position / change in speed or anything like that, but by only sending orders and shots fired. In this way each player computes the entire game himself and can determine if necessary whether the orders or shots are impossible (cheating). A periodic syncronization signal can correct for time drift and a timestamp on each order can partially correct for latency. But this is more complicated.

Did I understand all this correctly, you want to send position information about each unit over the network each time it changes? Floating point numbers??? And how do you plan on getting a computer to operate efficiently on 16 bit floating point numbers? Do you mean to use 16 bit integers instead?

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Thu Nov 02, 2006 10:48 am

first it's impossible to use 16bits to code correctly a position on the map. Maps are too big and we would lost too much precision. But speed can be coded on 16bits integers as well as heading (but not for computation, only for data transfer). Maybe 24bits can be enough for position since a position is packed in 2x16bits in TA's scripts.

Of course we can send orders and shots fired, but for units, we will need more precision because sometimes a unit takes random decisions (when it decides to attack an enemy, ...), and we will need to send from time to time position and speed.

As far as connections are concerned, your idea is interesting, this would allow the game to continue even is there is a small problem, but maybe we could just reconnect when a connection breaks??

I think the first thing players must do when entering in multiplayer mode is syncing game internal clock, so we can extrapolate received data when needed (we don't want to stop the game between ticks??)

one last thing, I would prefer ipv6 because it has interesting features and can fall back to ipv4 if needed.
=>;-D Penguin Powered

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Thu Nov 02, 2006 1:39 pm

Units decide randomly when to fire? I thought that in original TA units turn and fire immediately when in range and then fire again after a constant amount of time? When firing large numbers of bullets, they do seem randomly directed, but we can cut corners and have the 'random' directions more deterministic by carefully seeding our generators. It still seems too much to send position updates for moving units (no orders) since there might be a ton of aircraft circling some location. I still don't understand whether or not pathfinding will be a problem.

For the periodic resync of the position of units, we can avoid a huge burst of activity over the network by having the units each resync at various times during the resync period not all at once. This way you spread out the resync and you better use the connection (what if they are on 56k). Each unit could have a resync timer, and they are all out of phase so that they dont all resync at the same time. Just a thought!

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Thu Nov 02, 2006 3:03 pm

In fact each unit check the zone where it can find enemy units to fire at but it doesn't check all the zone only a random part of it. By doing like this I reduced the time needed to compute a frame, instead of taking 1 frame to check all the zone it takes a lot more frames but units aren't small and since check is done randomly you don't see the difference at all!!

Well pathfinding might be a problem because if synchronization isn't perfect the pathfinding functions might not return the same path for different players, because units might not be exactly at the same place, and with a round error it might be place a bit more on the left/right. The map object stores which units is on a map bloc, but a round error could cause a shift.
ex: 0.999999999999999999 = 1.0 or 0.99, if you take the integer part you get 1 or 0 depending on how it has been rounded.
=>;-D Penguin Powered

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Fri Nov 03, 2006 4:48 am

I have a question about the plan for low level network code. Will the socket communication be handled by one or more dedicated threads or will the game check sockets for incoming data once each game loop?

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Nov 03, 2006 9:21 am

I think using threads will achieve better performance and multi-core systems (we also should do that with physics when it will be finished)
=>;-D Penguin Powered

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Fri Nov 03, 2006 3:18 pm

Well I guess since EvenR wants to handle network layers thier really is no need for me to dable within this area, so with that I guess will pull back and leave you guys to the project.

I really only wanted to handle network layers and to provide an optional d3d interface as well as engine optmizations. I can submit engine optimizations to zuf rather then do this as part of the team.

So with that i'll leave yas in peace and keep peeking in from time to time to offer some advice if ya's want.

I strongly suggest that you do not use tcp for game data however, and look at udp, I know its unreliable but if you properly write it you should be able to tell when a packet was dropped. If you end up going with tcp your gona have a lagging game, remember that tcp guarenteed deliver will stop sending and 'wait' for ack packets. This can be measured in seconds, and the game will suffer horriably for it.

Best of luck guys.

++Cire.

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Fri Nov 03, 2006 4:35 pm

An individual unit's syncronization data should be pretty small enough so as to fit inside one udp packet (no fragmentation). We could use udp for that because it doesnt matter if we do unit syncro out of order and it doesn't matter if we miss a packet every once in a while. If we miss a packet he'll get syncronized a little later. To send orders or death certificates I think tcp would save some hassle though. For time syncronization I can imagine some stream of udp packets which we can use some kind of statistics analysis to estimate the difference in two players clocks.

User avatar
zuzuf
Administrateur - Site Admin
Posts: 3281
Joined: Mon Oct 30, 2006 8:49 pm
Location: Toulouse, France
Contact:

Post by zuzuf » Fri Nov 03, 2006 5:12 pm

Cire -> you do what you want, but I really think you could bring a lot to the project if you stay with us. But if you still send me patches, then for me you're still in the team.
=>;-D Penguin Powered

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Sat Nov 04, 2006 5:49 am

I know I can do ipv6 sockets stuff, but there is a lot of don't know. Cire seems to know something about how to put the actual communication calls into the engine. When the time comes for that two or more people working on it could really help.

User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Post by EvanR » Sat Nov 04, 2006 5:27 pm

There will be a thread for the player's tcp server socket, it will accept connections and envoke the stuff to add new players or spectators, right? But what about the rest of the sockets. Should there be one thread for each connection and for each udp socket? Or should we manage all remote sockets together in one thread with the FD_SET stuff. I'm just trying to understand the direction my code is going to go.

I have almost completed a class for low level sockets. It lets you use tcp/udp over ipv4/ipv6 fairly easily (you can make it auto decide on ipv4/ipv6, and of course ipv6 servers can accept connections on both protos). The next thing I will do is make a derived class which is tailored for use with ta3d, for example you can easily send our custom designed datatypes / packets without having to deal with creating the byte by byte representation first. Of course, I have no idea what our custom designed packets look like yet :)

User avatar
Cire
Moderator
Posts: 350
Joined: Tue Oct 31, 2006 5:59 pm
Location: Somewhere on Earth

Post by Cire » Sun Nov 05, 2006 3:19 am

Personally I would use 1 thread to handle the pool of connections/listening socket. Since your gona end up 'syncing' clocks and what not, any and all packets received can be sorted and handled in thier correct order.

Imho setting sockets into asyncorous mode with read/write/close/connect should do the trick. Then just create some event objects, for read process packets and push them onto a stack, sort the stack according to the packets clock time and process them in order during the engine process call.

Hope all this makes since, its getting late and kinda responding when i shouln't be, cause da mind is half dead. :)

Anyhow as I said previously I would use tcp to handle non criticle data, such as chat messages, marker events. Keep in mind that any non-criticle game messages shoudl also be 'tokenized'. This would help..A) reduce the amount of data sent, B) allow you to read resource specific local languages and display them in that. An example of a non-crictle game message might be a user teaming up with another user, or un-teaming, ect, rather then sending a message such as "joe blow has allied with jim bob" you would simply send out a packet with a header iding it as a token message, with some id header and arguments of the player numbers, and allow each computer to ocnstruct the message as they saw fit so if the user is german the message could be displayed in german and so on.

Anyhow enuff ramblings from me, hope it helps.

++Cire.

Post Reply

Who is online

Users browsing this forum: No registered users and 30 guests