{
int i;
int bits;
+ int impulse;
sizebuf_t buf;
unsigned char data[128];
static double lastsendtime = 0;
#define MOVEAVERAGING 0
#if MOVEAVERAGING
- static float forwardmove, sidemove, upmove, total; // accumulation
-#else
- float forwardmove, sidemove, upmove;
+ static float accumforwardmove = 0, accumsidemove = 0, accumupmove = 0, accumtotal = 0; // accumulation
#endif
+ float forwardmove, sidemove, upmove;
+
+ // if playing a demo, do nothing
+ if (!cls.netcon)
+ return;
#if MOVEAVERAGING
// accumulate changes between messages
- forwardmove += cl.cmd.forwardmove;
- sidemove += cl.cmd.sidemove;
- upmove += cl.cmd.upmove;
- total++;
+ accumforwardmove += cl.cmd.forwardmove;
+ accumsidemove += cl.cmd.sidemove;
+ accumupmove += cl.cmd.upmove;
+ accumtotal++;
#endif
- if (cl_movement.integer)
+ if (cl_movement.integer && cls.signon == SIGNONS)
{
if (!cl.movement_needupdate)
return;
cl.movement_needupdate = false;
- cl.movement = cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.intermission;
+ cl.movement = cl.stats[STAT_HEALTH] > 0 && !cl.intermission;
}
else
{
}
#if MOVEAVERAGING
// average the accumulated changes
- total = 1.0f / total;
- forwardmove *= total;
- sidemove *= total;
- upmove *= total;
- total = 0;
+ accumtotal = 1.0f / accumtotal;
+ forwardmove = accumforwardmove * accumtotal;
+ sidemove = accumsidemove * accumtotal;
+ upmove = accumupmove * accumtotal;
+ accumforwardmove = 0;
+ accumsidemove = 0;
+ accumupmove = 0;
+ accumtotal = 0;
#else
// use the latest values
forwardmove = cl.cmd.forwardmove;
if (cl.cmd.cursor_screen[1] <= -1) bits |= 32;
if (cl.cmd.cursor_screen[1] >= 1) bits |= 64;
+ impulse = in_impulse;
+ in_impulse = 0;
+
csqc_buttons = bits;
- // always dump the first two messages, because they may contain leftover inputs from the last level
- if (++cl.movemessages >= 2)
+ if (cls.signon == SIGNONS)
{
- // send the movement message
- // PROTOCOL_QUAKE clc_move = 16 bytes total
- // PROTOCOL_QUAKEDP clc_move = 16 bytes total
- // PROTOCOL_NEHAHRAMOVIE clc_move = 16 bytes total
- // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
- // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
- // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
- // PROTOCOL_DARKPLACES7 clc_move = 56 bytes total
- if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
- {
- // 5 bytes
- MSG_WriteByte (&buf, clc_move);
- MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
- // 3 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle8i (&buf, cl.viewangles[i]);
- // 6 bytes
- MSG_WriteCoord16i (&buf, forwardmove);
- MSG_WriteCoord16i (&buf, sidemove);
- MSG_WriteCoord16i (&buf, upmove);
- // 2 bytes
- MSG_WriteByte (&buf, bits);
- MSG_WriteByte (&buf, in_impulse);
- }
- else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
- {
- // 5 bytes
- MSG_WriteByte (&buf, clc_move);
- MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
- // 12 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle32f (&buf, cl.viewangles[i]);
- // 6 bytes
- MSG_WriteCoord16i (&buf, forwardmove);
- MSG_WriteCoord16i (&buf, sidemove);
- MSG_WriteCoord16i (&buf, upmove);
- // 2 bytes
- MSG_WriteByte (&buf, bits);
- MSG_WriteByte (&buf, in_impulse);
- }
- else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+ // always dump the first two messages, because they may contain leftover inputs from the last level
+ if (++cl.movemessages >= 2)
{
- // 5 bytes
- MSG_WriteByte (&buf, clc_move);
- MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
- // 6 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle16i (&buf, cl.viewangles[i]);
- // 6 bytes
- MSG_WriteCoord16i (&buf, forwardmove);
- MSG_WriteCoord16i (&buf, sidemove);
- MSG_WriteCoord16i (&buf, upmove);
- // 2 bytes
- MSG_WriteByte (&buf, bits);
- MSG_WriteByte (&buf, in_impulse);
- }
- else
- {
- // 5 bytes
- MSG_WriteByte (&buf, clc_move);
- if (cl.protocol != PROTOCOL_DARKPLACES6)
+ // send the movement message
+ // PROTOCOL_QUAKE clc_move = 16 bytes total
+ // PROTOCOL_QUAKEDP clc_move = 16 bytes total
+ // PROTOCOL_NEHAHRAMOVIE clc_move = 16 bytes total
+ // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
+ // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
+ // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
+ // PROTOCOL_DARKPLACES7 clc_move = 56 bytes total
+ if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 3 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle8i (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, impulse);
+ }
+ else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 12 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle32f (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, impulse);
+ }
+ else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 6 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle16i (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, impulse);
+ }
+ else
{
- if (cl_movement.integer)
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ if (cl.protocol != PROTOCOL_DARKPLACES6)
{
- cl.movesequence++;
- MSG_WriteLong (&buf, cl.movesequence);
+ if (cl_movement.integer)
+ {
+ cl.movesequence++;
+ MSG_WriteLong (&buf, cl.movesequence);
+ }
+ else
+ MSG_WriteLong (&buf, 0);
}
- else
- MSG_WriteLong (&buf, 0);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 6 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle16i (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 5 bytes
+ MSG_WriteLong (&buf, bits);
+ MSG_WriteByte (&buf, impulse);
+ // PRYDON_CLIENTCURSOR
+ // 30 bytes
+ MSG_WriteShort (&buf, cl.cmd.cursor_screen[0] * 32767.0f);
+ MSG_WriteShort (&buf, cl.cmd.cursor_screen[1] * 32767.0f);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_start[0]);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_start[1]);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_start[2]);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_impact[0]);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_impact[1]);
+ MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]);
+ MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber);
}
- MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
- // 6 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle16i (&buf, cl.viewangles[i]);
- // 6 bytes
- MSG_WriteCoord16i (&buf, forwardmove);
- MSG_WriteCoord16i (&buf, sidemove);
- MSG_WriteCoord16i (&buf, upmove);
- // 5 bytes
- MSG_WriteLong (&buf, bits);
- MSG_WriteByte (&buf, in_impulse);
- // PRYDON_CLIENTCURSOR
- // 30 bytes
- MSG_WriteShort (&buf, cl.cmd.cursor_screen[0] * 32767.0f);
- MSG_WriteShort (&buf, cl.cmd.cursor_screen[1] * 32767.0f);
- MSG_WriteFloat (&buf, cl.cmd.cursor_start[0]);
- MSG_WriteFloat (&buf, cl.cmd.cursor_start[1]);
- MSG_WriteFloat (&buf, cl.cmd.cursor_start[2]);
- MSG_WriteFloat (&buf, cl.cmd.cursor_impact[0]);
- MSG_WriteFloat (&buf, cl.cmd.cursor_impact[1]);
- MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]);
- MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber);
- }
- }
-#if MOVEAVERAGING
- forwardmove = sidemove = upmove = 0;
-#endif
- in_impulse = 0;
+ // FIXME: bits & 16 is +button5, Nexuiz specific
+ CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0);
+ }
- // ack the last few frame numbers
- // (redundent to improve handling of client->server packet loss)
- // for LATESTFRAMENUMS == 3 case this is 15 bytes
- for (i = 0;i < LATESTFRAMENUMS;i++)
- {
- if (cl.latestframenums[i] > 0)
+ // ack the last few frame numbers
+ // (redundent to improve handling of client->server packet loss)
+ // for LATESTFRAMENUMS == 3 case this is 15 bytes
+ for (i = 0;i < LATESTFRAMENUMS;i++)
{
- if (developer_networkentities.integer >= 1)
- Con_Printf("send clc_ackframe %i\n", cl.latestframenums[i]);
- MSG_WriteByte(&buf, clc_ackframe);
- MSG_WriteLong(&buf, cl.latestframenums[i]);
+ if (cl.latestframenums[i] > 0)
+ {
+ if (developer_networkentities.integer >= 1)
+ Con_Printf("send clc_ackframe %i\n", cl.latestframenums[i]);
+ MSG_WriteByte(&buf, clc_ackframe);
+ MSG_WriteLong(&buf, cl.latestframenums[i]);
+ }
}
- }
- // PROTOCOL_DARKPLACES6 = 67 bytes per packet
- // PROTOCOL_DARKPLACES7 = 71 bytes per packet
-
- // deliver the message
- if (cls.demoplayback)
- return;
- // nothing to send
- if (!buf.cursize)
- return;
- if (cls.signon != SIGNONS)
- return;
+ // PROTOCOL_DARKPLACES6 = 67 bytes per packet
+ // PROTOCOL_DARKPLACES7 = 71 bytes per packet
+ }
- // FIXME: bits & 16 is +button5, Nexuiz specific
- CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0);
+ // send the reliable message (forwarded commands) if there is one
+ NetConn_SendUnreliableMessage(cls.netcon, &buf);
- if (NetConn_SendUnreliableMessage(cls.netcon, &buf) == -1)
+ if (cls.netcon->message.overflowed)
{
Con_Print("CL_SendMove: lost server connection\n");
CL_Disconnect();
int CL_ReadFromServer(void)
{
CL_ReadDemoMessage();
- CL_SendCmd();
+ CL_SendMove();
r_refdef.time = cl.time;
r_refdef.extraupdate = !r_speeds.integer;
return 0;
}
-/*
-=================
-CL_SendCmd
-=================
-*/
-void CL_UpdatePrydonCursor(void);
-void CL_SendCmd(void)
-{
- // send the reliable message (forwarded commands) if there is one
- if (cls.netcon && cls.netcon->message.cursize && NetConn_CanSendMessage(cls.netcon))
- {
- if (developer.integer)
- {
- Con_Print("CL_SendCmd: sending reliable message:\n");
- SZ_HexDumpToConsole(&cls.netcon->message);
- }
- if (NetConn_SendReliableMessage(cls.netcon, &cls.netcon->message) == -1)
- Host_Error("CL_WriteToServer: lost server connection");
- SZ_Clear(&cls.netcon->message);
- }
-
- // send a move periodically
- CL_SendMove();
-}
-
// LordHavoc: pausedemo command
static void CL_PauseDemo_f (void)
{
sizebuf_t old;
// no need if server is local and definitely not if this is a demo
- if (sv.active || cls.demoplayback)
+ if (sv.active || !cls.netcon)
return;
// read messages from server, should just be nops
extern kbutton_t in_speed;
void CL_InitInput (void);
-void CL_SendCmd (void);
void CL_SendMove (void);
void CL_ValidateState(entity_state_t *s);
Con_Print("changelevel <levelname> : continue game on a new level\n");
return;
}
- // HACKHACKHACK
- if (!sv.active) {
- Host_Map_f();
- return;
- }
if (cls.demoplayback)
{
Con_Print("Only the server may changelevel\n");
return;
}
+ // HACKHACKHACK
+ if (!sv.active) {
+ Host_Map_f();
+ return;
+ }
if (cmd_source != src_command)
return;
Con_Print("restart : restart current level\n");
return;
}
- if (!sv.active || cls.demoplayback)
+ if (!sv.active)
{
Con_Print("Only the server may restart\n");
return;
MSG_WriteByte (&host_client->netconnection->message, svc_signonnum);
MSG_WriteByte (&host_client->netconnection->message, 2);
}
- host_client->sendsignon = true;
// reset the name change timer because the client will send name soon
host_client->nametime = 0;
MSG_WriteByte (&host_client->netconnection->message, svc_signonnum);
MSG_WriteByte (&host_client->netconnection->message, 3);
-
- host_client->sendsignon = true;
}
/*
return NetConn_Write(mysocket, string, (int)strlen(string), peeraddress);
}
-int NetConn_SendReliableMessage(netconn_t *conn, sizebuf_t *data)
-{
- unsigned int packetLen;
- unsigned int dataLen;
- unsigned int eom;
- unsigned int *header;
-
-//#ifdef DEBUG
- if (data->cursize == 0)
- {
- Con_Printf ("Datagram_SendMessage: zero length message\n");
- return -1;
- }
-
- if (data->cursize > (int)sizeof(conn->sendMessage))
- {
- Con_Printf ("Datagram_SendMessage: message too big (%u > %u)\n", data->cursize, sizeof(conn->sendMessage));
- return -1;
- }
-
- if (conn->canSend == false)
- {
- Con_Printf ("SendMessage: called with canSend == false\n");
- return -1;
- }
-//#endif
-
- memcpy(conn->sendMessage, data->data, data->cursize);
- conn->sendMessageLength = data->cursize;
-
- if (conn->sendMessageLength <= MAX_PACKETFRAGMENT)
- {
- dataLen = conn->sendMessageLength;
- eom = NETFLAG_EOM;
- }
- else
- {
- dataLen = MAX_PACKETFRAGMENT;
- eom = 0;
- }
-
- packetLen = NET_HEADERSIZE + dataLen;
-
- header = (unsigned int *)sendbuffer;
- header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
- header[1] = BigLong(conn->sendSequence);
- memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
-
- conn->sendSequence++;
- conn->canSend = false;
-
- if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) != (int)packetLen)
- return -1;
-
- conn->lastSendTime = realtime;
- packetsSent++;
- reliableMessagesSent++;
- return 1;
-}
-
-static void NetConn_SendMessageNext(netconn_t *conn)
+int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data)
{
unsigned int packetLen;
unsigned int dataLen;
unsigned int eom;
unsigned int *header;
- if (conn->sendMessageLength && !conn->canSend && conn->sendNext)
+ // if a reliable message fragment has been lost, send it again
+ if (!conn->canSend && conn->sendMessageLength && (realtime - conn->lastSendTime) > 1.0)
{
if (conn->sendMessageLength <= MAX_PACKETFRAGMENT)
{
header = (unsigned int *)sendbuffer;
header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
- header[1] = BigLong(conn->sendSequence);
+ header[1] = BigLong(conn->sendSequence - 1);
memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
- conn->sendSequence++;
- conn->sendNext = false;
+ if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) == (int)packetLen)
+ {
+ conn->lastSendTime = realtime;
+ packetsReSent++;
+ }
+ }
- if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) != (int)packetLen)
- return;
+ // if we have a new reliable message to send, do so
+ if (conn->canSend && conn->message.cursize)
+ {
+ if (conn->message.cursize > (int)sizeof(conn->sendMessage))
+ {
+ Con_Printf("NetConn_SendUnreliableMessage: reliable message too big (%u > %u)\n", conn->message.cursize, sizeof(conn->sendMessage));
+ conn->message.overflowed = true;
+ return -1;
+ }
- conn->lastSendTime = realtime;
- packetsSent++;
- }
-}
+ if (developer_networking.integer && conn == cls.netcon)
+ {
+ Con_Print("client sending reliable message to server:\n");
+ SZ_HexDumpToConsole(&conn->message);
+ }
-static void NetConn_ReSendMessage(netconn_t *conn)
-{
- unsigned int packetLen;
- unsigned int dataLen;
- unsigned int eom;
- unsigned int *header;
+ memcpy(conn->sendMessage, conn->message.data, conn->message.cursize);
+ conn->sendMessageLength = conn->message.cursize;
+ SZ_Clear(&conn->message);
- if (conn->sendMessageLength && !conn->canSend && (realtime - conn->lastSendTime) > 1.0)
- {
if (conn->sendMessageLength <= MAX_PACKETFRAGMENT)
{
dataLen = conn->sendMessageLength;
header = (unsigned int *)sendbuffer;
header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
- header[1] = BigLong(conn->sendSequence - 1);
+ header[1] = BigLong(conn->sendSequence);
memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
- conn->sendNext = false;
+ conn->sendSequence++;
+ conn->canSend = false;
- if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) != (int)packetLen)
- return;
+ NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress);
conn->lastSendTime = realtime;
- packetsReSent++;
+ packetsSent++;
+ reliableMessagesSent++;
}
-}
-
-qboolean NetConn_CanSendMessage(netconn_t *conn)
-{
- return conn->canSend;
-}
-
-int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data)
-{
- int packetLen;
- unsigned int *header;
-
- packetLen = NET_HEADERSIZE + data->cursize;
-//#ifdef DEBUG
- if (data->cursize == 0)
+ // if we have an unreliable message to send, do so
+ if (data->cursize)
{
- Con_Printf ("Datagram_SendUnreliableMessage: zero length message\n");
- return -1;
- }
+ packetLen = NET_HEADERSIZE + data->cursize;
- if (packetLen > (int)sizeof(sendbuffer))
- {
- Con_Printf ("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize);
- return -1;
- }
-//#endif
+ if (packetLen > (int)sizeof(sendbuffer))
+ {
+ Con_Printf("NetConn_SendUnreliableMessage: message too big %u\n", data->cursize);
+ return -1;
+ }
- header = (unsigned int *)sendbuffer;
- header[0] = BigLong(packetLen | NETFLAG_UNRELIABLE);
- header[1] = BigLong(conn->unreliableSendSequence);
- memcpy(sendbuffer + NET_HEADERSIZE, data->data, data->cursize);
+ header = (unsigned int *)sendbuffer;
+ header[0] = BigLong(packetLen | NETFLAG_UNRELIABLE);
+ header[1] = BigLong(conn->unreliableSendSequence);
+ memcpy(sendbuffer + NET_HEADERSIZE, data->data, data->cursize);
- conn->unreliableSendSequence++;
+ conn->unreliableSendSequence++;
- if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) != (int)packetLen)
- return -1;
+ NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress);
- packetsSent++;
- unreliableMessagesSent++;
- return 1;
+ packetsSent++;
+ unreliableMessagesSent++;
+ }
+ return 0;
}
void NetConn_CloseClientPorts(void)
}
}
-int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int length)
+static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int length)
{
unsigned int count;
unsigned int flags;
Con_DPrint("ack sequencing error\n");
conn->lastMessageTime = realtime;
conn->timeout = realtime + net_messagetimeout.value;
- conn->sendMessageLength -= MAX_PACKETFRAGMENT;
- if (conn->sendMessageLength > 0)
+ if (conn->sendMessageLength > MAX_PACKETFRAGMENT)
{
+ unsigned int packetLen;
+ unsigned int dataLen;
+ unsigned int eom;
+ unsigned int *header;
+
+ conn->sendMessageLength -= MAX_PACKETFRAGMENT;
memcpy(conn->sendMessage, conn->sendMessage+MAX_PACKETFRAGMENT, conn->sendMessageLength);
- conn->sendNext = true;
- NetConn_SendMessageNext(conn);
+
+ if (conn->sendMessageLength <= MAX_PACKETFRAGMENT)
+ {
+ dataLen = conn->sendMessageLength;
+ eom = NETFLAG_EOM;
+ }
+ else
+ {
+ dataLen = MAX_PACKETFRAGMENT;
+ eom = 0;
+ }
+
+ packetLen = NET_HEADERSIZE + dataLen;
+
+ header = (unsigned int *)sendbuffer;
+ header[0] = BigLong(packetLen | (NETFLAG_DATA | eom));
+ header[1] = BigLong(conn->sendSequence);
+ memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen);
+
+ conn->sendSequence++;
+
+ if (NetConn_Write(conn->mysocket, (void *)&sendbuffer, packetLen, &conn->peeraddress) == (int)packetLen)
+ {
+ conn->lastSendTime = realtime;
+ packetsSent++;
+ }
}
else
{
return false;
}
-int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
+static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
{
int ret, c, control;
const char *s;
{
int i, length;
lhnetaddress_t peeraddress;
- netconn_t *conn;
NetConn_UpdateSockets();
if (cls.connect_trying && cls.connect_nextsendtime < realtime)
{
NetConn_Write(cls.connect_mysocket, net_message.data, net_message.cursize, &cls.connect_address);
SZ_Clear(&net_message);
}
- for (i = 0;i < cl_numsockets;i++) {
- while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0) {
+ for (i = 0;i < cl_numsockets;i++)
+ while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0)
NetConn_ClientParsePacket(cl_sockets[i], readbuffer, length, &peeraddress);
- }
- }
NetConn_QueryQueueFrame();
if (cls.netcon && realtime > cls.netcon->timeout)
{
CL_Disconnect();
Host_ShutdownServer ();
}
- for (conn = netconn_list;conn;conn = conn->next)
- NetConn_ReSendMessage(conn);
}
#define MAX_CHALLENGES 128
}
extern void SV_SendServerinfo (client_t *client);
-int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
+static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress)
{
int i, ret, clientnum, best;
double besttime;
{
int i, length;
lhnetaddress_t peeraddress;
- netconn_t *conn;
NetConn_UpdateSockets();
for (i = 0;i < sv_numsockets;i++)
while (sv_sockets[i] && (length = NetConn_Read(sv_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0)
SV_DropClient(false);
}
}
- for (conn = netconn_list;conn;conn = conn->next)
- NetConn_ReSendMessage(conn);
}
void NetConn_QueryMasters(void)
double lastSendTime;
qboolean canSend;
- qboolean sendNext;
// writing buffer to send to peer as the next reliable message
// can be added to at any time, copied into sendMessage buffer when it is
extern cvar_t cl_netlocalping;
-int NetConn_SendReliableMessage(netconn_t *conn, sizebuf_t *data);
-//void NetConn_SendMessageNext(netconn_t *conn);
-//void NetConn_ReSendMessage(netconn_t *conn);
-qboolean NetConn_CanSendMessage(netconn_t *conn);
int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data);
void NetConn_CloseClientPorts(void);
void NetConn_OpenClientPorts(void);
void NetConn_Close(netconn_t *conn);
void NetConn_Listen(qboolean state);
int NetConn_IsLocalGame(void);
-//int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int length);
-//int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress);
-//int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *data, int length, lhnetaddress_t *peeraddress);
void NetConn_ClientFrame(void);
void NetConn_ServerFrame(void);
void NetConn_QueryMasters(void);
qboolean clientconnectcalled;
// false = don't send datagrams
qboolean spawned;
- // only valid before spawned
- qboolean sendsignon;
// requested rate in bytes per second
int rate;
// realtime this client connected
double connecttime;
- // reliable messages must be sent periodically
- double last_message;
+ // keepalive messages must be sent periodically during signon
+ double keepalivetime;
// communications handle
netconn_t *netconnection;
MSG_WriteByte (&client->netconnection->message, svc_signonnum);
MSG_WriteByte (&client->netconnection->message, 1);
- client->sendsignon = true;
client->spawned = false; // need prespawn, spawn, etc
}
=======================
*/
static unsigned char sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
-qboolean SV_SendClientDatagram (client_t *client)
+void SV_SendClientDatagram (client_t *client)
{
int rate, maxrate, maxsize, maxsize2;
sizebuf_t msg;
msg.maxsize = maxsize;
msg.cursize = 0;
- MSG_WriteByte (&msg, svc_time);
- MSG_WriteFloat (&msg, sv.time);
-
- // add the client specific data to the datagram
- SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
- VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
- SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
-
- // expand packet size to allow effects to go over the rate limit
- // (dropping them is FAR too ugly)
- msg.maxsize = maxsize2;
-
- // copy the server datagram if there is space
- // FIXME: put in delayed queue of effects to send
- if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
- SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
-
-// send the datagram
- if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
+ if (host_client->spawned)
{
- SV_DropClient (true);// if the message couldn't send, kick off
- return false;
+ MSG_WriteByte (&msg, svc_time);
+ MSG_WriteFloat (&msg, sv.time);
+
+ // add the client specific data to the datagram
+ SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
+ VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
+ SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
+
+ // expand packet size to allow effects to go over the rate limit
+ // (dropping them is FAR too ugly)
+ msg.maxsize = maxsize2;
+
+ // copy the server datagram if there is space
+ // FIXME: put in delayed queue of effects to send
+ if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
+ SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
+ }
+ else if (realtime > client->keepalivetime)
+ {
+ // the player isn't totally in the game yet
+ // send small keepalive messages if too much time has passed
+ client->keepalivetime = realtime + 5;
+ MSG_WriteChar (&msg, svc_nop);
}
- return true;
+// send the datagram
+ NetConn_SendUnreliableMessage (client->netconnection, &msg);
}
/*
}
-/*
-=======================
-SV_SendNop
-
-Send a nop message without trashing or sending the accumulated client
-message buffer
-=======================
-*/
-void SV_SendNop (client_t *client)
-{
- sizebuf_t msg;
- unsigned char buf[4];
-
- msg.data = buf;
- msg.maxsize = sizeof(buf);
- msg.cursize = 0;
-
- MSG_WriteChar (&msg, svc_nop);
-
- if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
- SV_DropClient (true); // if the message couldn't send, kick off
- client->last_message = realtime;
-}
-
/*
=======================
SV_SendClientMessages
continue;
}
- if (host_client->spawned)
- {
- if (!prepared)
- {
- prepared = true;
- // only prepare entities once per frame
- SV_PrepareEntitiesForSending();
- }
- if (!SV_SendClientDatagram (host_client))
- continue;
- }
- else
- {
- // the player isn't totally in the game yet
- // send small keepalive messages if too much time has passed
- // send a full message when the next signon stage has been requested
- // some other message data (name changes, etc) may accumulate
- // between signon stages
- if (!host_client->sendsignon)
- {
- if (realtime - host_client->last_message > 5)
- SV_SendNop (host_client);
- continue; // don't send out non-signon messages
- }
- }
-
- if (host_client->netconnection->message.cursize)
+ if (!prepared)
{
- if (!NetConn_CanSendMessage (host_client->netconnection))
- continue;
-
- if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->netconnection->message) == -1)
- SV_DropClient (true); // if the message couldn't send, kick off
- SZ_Clear (&host_client->netconnection->message);
- host_client->last_message = realtime;
- host_client->sendsignon = false;
+ prepared = true;
+ // only prepare entities once per frame
+ SV_PrepareEntitiesForSending();
}
+ SV_SendClientDatagram (host_client);
}
// clear muzzle flashes