
The QuakeWorld connection process:
---------------------------------

servercount
Each time a server changes maps, it will bump the servercount variable.  The signon
messages sent from the client to the server will include a servercount, and if the
server detects that it has changed levels while the client is in the process of
connecting, the client connection process will be restarted.

svc_skinlist

MAX_SIGNON_BUFFERS...

+attack;wait  : this both does the attack and prints a chat?

put frag counts in userinfo as *frags?

no forward to server commands unless active?

changelevel / reconnect confusion

syncing the fixangle over the reliable channel with the first update
	option to put the update in the reliable message?


--------------
A "connect <server>" command is executed on the client.

CL_Connect_f() disconnects from the current server if connected, 
sets the current server to the new value, and sends the first connection packet.

The connection packet will be resent by CL_CheckForResend() every two seconds until the server connects.

A connection packet is an out of band packet containing "connect <userinfo>" with userinfo quoted.

--------------

The server receives the OOB message in SVC_DirectConnect()

It can respond with an OOB client print of "banned" or "server is full" if the client
cannot enter the game.

If the client can get in, the server will initialize a new client_t structure with a
netchan_t, and respond with an OOB message containing S2C_CONNECTION.  Further
communication will be through sequenced netchan_t messages instead of OOB messages.

The client_t->state is set to cs_connected

--------------

if S2C_CONNECTION packet is dropped, the connect message will be resent after two
seconds and the server will recognize the address and reuse the allocated client_t FIXME:bug?)			

When the client receives the S2C_CONNECTION, it initializes cls.netchan and sends
a "new" string command over the netchan to the server.

cls.state is set to ca_connected	FIXME: change to cs_connected?

--------------

The "new" usercommand on the server is issued by the client every time they enter a level,
which is why none of the information is sent in the initial S2C_CONNECTION message. 

"new" sends over 

Before the client can begin playing in the server, the following information must be sent:

gamedir
svc_serverinfo
	PROTOCOL_VERSION
	servercount		// for detecting when the server
	gamedir			// for deciding the add-on directory (qw, ctf, etc)
	playernumber	// the client will allways be in this slot
	the qc string of world.message	// usually the level's full verbose name
cdtrack
fullserverinfo

when received, the client changes state to ca_onserver.  When the client receives
all the information needed to render a frame, the state will be changed to ca_active

.....

svc_soundlist

.....

svc_modellist

.....

prespawn passes the contents of the sv.signon_buffers, which hold
static entity spawning, static sound spawning, and all the entity baselines
FIXME: don't need to pass all baselines, uninitialized probs?

.....

"spawn" sends all dynamically changing state (fullclient updates, lightmaps, frags)
and ma

FIXME: 32 clients could be up to 16k in updates, which overflows the 8k packet size

FIXME: there is an updating hole between the sending of spawn data and the client
being notified 


"begin"

Actually spawns the client into the world as a visible entity.

The client_t->state is set to cs_spawned, so normal datagram updates begin

-----------------------

When the first valid packetentities_t arrives at the client, cls.state is set
to ca_active, and rendering can begin.

FIXME: make sure player and packets are both valid


movecmd_t	movecmd;


input from 

packet sender
	wake up on alarms or input signal
	if on input signal, set skipnextalrm
	else
		if skipnextalarm
			skipnextalarm = false;
			continue;
	lock packet
	get current movecmd
	send message
	unlock packet

packet receiver
	wake up only on packet arrival
	identify the packet source
	calculate exact latency
	save the packet off




	// cause timer messages to be issued
	SetTimer (mainwindow, 1, 50, NULL);

	// cause packet received messages to be issued
	WSAAsyncSelect ( net_socket, mainwindow, WM_USER, FD_READ );	

	if (!GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg);
		DispatchMessage (&msg);
		while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (!GetMessage (&msg, NULL, 0, 0))
				break;
			TranslateMessage (&msg);
   			DispatchMessage (&msg);
		}
		PrepareToBlock ();
	}

