Network code update

Everything related to the code /
Tout ce qui touche au code
Post Reply
User avatar
EvanR
Posts: 46
Joined: Tue Oct 31, 2006 6:24 pm
Location: United States
Contact:

Network code update

Post by EvanR » Sat Nov 11, 2006 8:45 pm

Sorry I haven't been on the forum for a while, it's just that I didn't have anything good to say! However I have made some progress and there's some questions to answer and some questions to ask.

I wrote some classes to do all the network stuff. The important one is Network which is supposed to be used by the main program to do high level controlling of the network (hostgame, disconnect, connect to game, get game list, get incoming events for processing). The internal implementation of this uses a bunch of other classes including a Socket class. Socket is pretty much finished and totally works on ipv6/ipv4 without anyone even caring about it. Of course, you can restrict connections to one or the other.

The current plan that its going toward is there are four types of packets
chat (long strings with from whom and to whom info)
sync (unit number, timestamp, some floats)
order (unit number, timestamp, order, some floats)
event (miscellaneous messages like new players, team joinings etc)

like Cire said, the event notifications can be 'tokenized' so events are pretty small packets. sync and order might be relatively long if they
contain many floats, and chat is only long if the message is long.

My idea is that chat, event, and orders go over the tcp connection and syncs go over udp without reliability. If a unit doesnt sync due to lost packet, it will sync later. No problem. Orders are critical to the game and must be received exactly once. Instead of making a scheme to do this over udp, why not just use tcp? A single sync should be short enough to fit in one udp packet, ie, no fragmentation. Am i right?

Zuzuf asked about data compression. chat messages might be reduced a few bytes with a huffman code. But since chat messages wont happen very often I don't think its worth it. Events are likely to be a couple bytes big. The packets that contain floating point numbers are going to be numerous and often. The best way to reduce this traffic is to decide which floats dont require 32 bits of precision (rotation?), since the data we will be using in ta3d will have sufficiently random floating point representation its unlikely that we can consistently save a singnificant number of bytes (out of perhaps 9 floats * 4 bytes = 36 bytes) with some compression algorithm.

Which brings me to my next topic, what exactly are we sending? For a sync we need the units position, velocity and orientation (its behavior isn't critical as there will be orders packetes). Seems like position is just two floats, because its Z is either the same as the ground or at the standard aircraft flight level. Orientation for ground units is like one float right? Aircraft? Velocity for ground units is two floats since you can determine missing information from the ground's gradient. Aircraft?
For unit orders, it seems that we require floats at least sometimes. A move/build order takes two floats: the destination to move/build. Firing takes either two floats or an integer which is the unit to shoot at.

Which brings me to the next topic, shooting individual bullets seems to be slightly random and also could be very high frequency. We shouldn't send an order for each bullet fired, just the attack order. This helps with the very high frequency. We can avoid sending random bullet velocities by making sure that all players have syncronized random number generators. But I can image this failing when 1 more bullet is fired on one machine than another and everything goes wrong....

Which brings up the topic of catastrophic game split. Since no one is authoritative about the state of the game, we might run into a situation where a unit is dead in one game and still alive in another. (due to latency player1 fires and kills player2's unit before player2 knows it and player2 fires 'illegally' possibly killing a third unit who should not have died). Two solutions to this problem i can think of are: 1 periodically check for this kind of inconsistency and kill the 'ghost' unit on all games even if he 'should have lived' or 2 keep some kind of semi authoritative game state on the host computer and refer to him for the 'true' state of the unit's health, living/death status. Number 2 seems to be the more complicated.
Ideas?

And now a question. It seems reasonable to try and reduce network traffic by not sending sync or orders about units behind the fog of war. However the game might have fog of war off, so we sometimes must send all the information about everything to everyone. Perhaps we just shouldn't worry about such an optimization?

About AI, if all players even ai players are represented as network players (even in a single player game) then the same machinery that runs a network game will automatically work for a single player game with AI. Then the AI players are just written to have an idea of what the game looks like and send the orders (and syncs?) to the players game. This also allows us to have a dedicated AI server which uses extreme amounts of CPU to do strategy that would slow you down if it were running on the same machine as you. Any thoughts?

Another thing, does anyone want to look at my code? Should it be uploaded to the CVS? There is definitely some stuff to change regarding size of types, windows compatability, etc. Since I am working on it alone I feel like I might be doing something totally wrong.

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

Post by zuzuf » Sat Nov 11, 2006 10:45 pm

for position, I agree, 2 floats should be enough
for speed, 2 floats too (in fact speed is 2D for planes too because the Y coordinate is managed separately.
orientation is one float but an unsigned short int will be enough

the random number generator is heavily used by particles effects like explosions and above all huge explosions (atomic weapons) which produce a lots of particles. It's easy to synchronize the random number generator (just synchronize the position in the random array) but you will have to do it often because lots of things use it. Worse, we will need to synchronize weapons trajectories (what if a commander avoid a nuclear rocket on a computer and not on the others ??)

I prefer your first solution, if you can check all the units every 10 sec., that should be enough.

Your idea is interesting. We can avoid sending data which won't be displayed, but not everything hidden by the fog of war because, a unit can shoot something hidden!!

As far as AI is concerned, AI players are local players, and I would prefer to synchronize all the local players in one pass (not one by local player), I think this would prevent wasting some bandwidth and the engine can very well run in dedicated mode: you just have to omit the local human player.

I think you should put your code on CVS, this way everyone can test it, report bugs or comments.
=>;-D Penguin Powered

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

Post by EvanR » Sun Nov 12, 2006 12:01 am

Ok I have never seriously used CVS before, I know it can get annoying to rename files. Perhaps we should agree on what the names of the files should be before i upload. After that, what do I type to make new modules?

proposed names for new modules
Socket.cpp
Socket.h
TA3DSock.cpp
TA3DSock.h
SuperQueue.cpp
SuperQueue.h
Thread.h
Network.cpp
Network.h

and you only need to include Network.h in the main game.


By the way, I am having some trouble on devC++ for windows. It seems that the winsock include files that come with it are not as full featured as described at MSDN. In particular the new sockets api isn't totally complete. After some fiddling with those headers I got an ipv6 prog to compile and run on windows, so I know the support is out there. Hopefully Cire, who presumably has MS visual studio, will be able to test my sockets code on windows.

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

Post by zuzuf » Sun Nov 12, 2006 9:22 am

These names are OK. Now to make new modules, you must edit the src/Makefile.am, there is the list of files to compile, just add one line per new module (.cpp & .h) and global headers at the end of the list (like matrix.h, vector.h,ta3dbase.h).

Then you need to go to TA3D's root dir and type:
aclocal
autoconf
automake -a -c
in order to refresh things, now when you type make the new modules will build.

to upload this to CVS,
(from a working copy of the CVS repository)
cd to src/ and type:
cvs add Socket.cpp
and do this for each new file
then cd to TA3D's root dir and type:
cvs commit
then type some comments (for example "network modules")
and wait until it's done
=>;-D Penguin Powered

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

Post by Cire » Sun Nov 12, 2006 5:07 pm

Well only thing I need to say is that NOTHING criticle should go accross TCP, keep in mind TCP requires ACK packet replies, and if not received after a period of time will resend the packet again and again untill ACK is recived, This in many cases can be seconds! A few seconds in a RTS Game is very very very very bad especially if its sending it often, imagine each tick having to wait 2 or 3 or more seconds, when its normally over in 500 ms or something like that.

Hate to say it but keep TCP to chat and events, since they are not criticle to gameplay. Now to me each player will have a playerlist/ai player list ect in a list, eahc player will have a list of units and what not local to each player. If I change the orders of some of my units, flag it as dirty, which will go out over next tick to be updated to other players.

Get rid of most randomization that are 'criticle', and come up with algorthisims that are depandant so when they occur they will be the same on all platforms.

Now zuff brought up a key point, and that is that FPO's preformed on my cpu may not work out exactly the same on another cpu, so work here needs to be worked out.

I think if u reserved FPO's to some scale, like say 6 decimal places, you might be all right, I would also check out other big engines such as quake for ways in which they handle FPO's and what not from one to another cpu, ect.. You could also at connect time or for that matter 'at first install time or run time', run a routine that would say generate 50 floats from a set of fixed FPO calculations and when users connect to each other, attemtp to match these to each other, if thier are issues this is when your gona find out. It won't do you much good to see that thire are issues but at the very min i'tll help in debugging, and show you how much scale you can play with, for all you know cpus could be out at about 6 decimal places, or 12 its hard to say.

These are just a few suggestions, hope they help.

++Cire.

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

Post by zuzuf » Sun Nov 12, 2006 5:26 pm

it's even worse than a CPU problem, it also depends on how you use the CPU. For example using the FPU or SSE will ive different result since precision may vary (I think FPU can give you up to 80bits :x )
=>;-D Penguin Powered

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

Post by EvanR » Sun Nov 12, 2006 7:28 pm

single precision floats have 23 bits of significand. That translates to under 7 significant figures in decimal representation. That is we can only count on numbers like 1.234567 and 123.4567. This is how computers should work on floats as long as they have ieee754 standard. As far as I know thats everyone with an x86 based machine. On what computers are you worried about non standard floating point?

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

Post by EvanR » Tue Nov 14, 2006 6:40 am

So I am trying to compile my code as part of the main project that I downloaded latest CVS. The problem I am having is what to call my platform dependent #define directive and how to tell automake and friends that we need to define that. Currently I'm using the words #define TA3D_PLATFORM_LINUX to denote linux-only implementation. How do I get a -DTA3D_PLATFORM_LINUX into the build process? I can add this to the makefile manually, but I'd like to know the right way.

After that works I may want to go ahead and check in the new modules, but do I not need a special password and login instructions?

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

Post by Cire » Tue Nov 14, 2006 5:39 pm

For now just add #define TA3D_PLATFORM_LINUX to the top of your code, in upcoming sorce release it should be defined in a file called TA3D_Platform.h

Ideally when a user is building a version for himself, they will edit this file and define or undefine whatever platform they want, so you do not need to make any adjustements

To test your builds for now as I said just define it at the top of your code, or better yet create a file named TA3D_Platform.h and place it in that, that way you will not require any changes.

++Cire.

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 17, 2006 10:20 pm

to build with TA3D_PLATFORM_LINUX, just run configure like this:
./configure {what ever you want} -DTA3D_PLATFORM_LINUX

but there is no need to set this at build time since ALLEGRO can identify the platform for us with ALLEGRO_LINUX, ALLEGRO_WINDOWS, etc...
=>;-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 18, 2006 12:57 am

Ahhh that is good thanks. I will be submitting my code shortly. It can be used to connect two games together (assuming no bugs), but until a couple of policy decisions are made no data will be sent between games. We still have to decide who will connect to whom and send what data.

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

Post by zuzuf » Sat Nov 18, 2006 11:46 am

I added Cire's stdafx.h and stdafx.cpp to my working copy, with a few modifications like platform autodetection (all is in allegro/platform/alplatf.h) so we don't need -DTA3D_PLATFORM_LINUX anymore
=>;-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 18, 2006 3:19 pm

Ok I added the network modules. In the current state it probably won't compile on linux until the platform specific directives are fixed (they still have #ifdef TA3D_PLATFORM_XXX). After that is changed (to #ifdef ALLEGRO_XXX ?), it probably won't compile on windows due to some missing functionality in the sockets (the errors like E_WOULDBLOCK). Since I haven't built it on windows successfully I haven't tested the win32 thread stuff either. My problem is that the winsock2 header files that come with DevC++ don't have complete support for gai_strerror(). This function is in the documentation on MSDN so it should work on visual c++. The Socket class reports its own errors with printf, but that can easily be changed to use the rest of the projects error handling. Also the integer types in ta3dsock are the ones in sys/types.h on linux, that needs to use the types from the rest of the project.

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

Post by zuzuf » Sat Nov 18, 2006 4:21 pm

On windows, I didn't try, but on linux it builds with a few modifications I uploaded to CVS. I am starting a battle_room to test this
=>;-D Penguin Powered

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Sat Dec 02, 2006 4:17 pm

How the progress with multiplayer support is going? Zuzuf, you wrote about begining of battle_room testing... Does it works nice? :roll:

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

Post by Cire » Sun Dec 03, 2006 12:26 am

networking as is does not compile under windows, it includes several files that don't exists in windows. I really havn't had time to look at it in detail as i'am still working on getting the brunt of the code to compile under windows.

++Cire.

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

Post by EvanR » Tue Dec 12, 2006 8:46 pm

Sorry I've been so busy with real life. I have finals this week and its all crazy. I promise I'll get back into the ta3d groove next week!

User avatar
Balthazar
Moderator
Posts: 2055
Joined: Wed Nov 01, 2006 4:31 pm
Location: Russian Federation
Contact:

Post by Balthazar » Tue Dec 12, 2006 9:16 pm

Take your time, but try not too long, we need you :D

Post Reply

Who is online

Users browsing this forum: No registered users and 30 guests