From 9cc276c2e36a6fc6cfafd8a0fb6df85e2f644c07 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 11 Feb 2006 02:33:30 +0000 Subject: [PATCH] migrated cls.message and client->message buffers into netconn_t struct git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5960 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 35 +++++++++----------- cl_parse.c | 67 +++++++++++++++++++++----------------- client.h | 3 -- cmd.c | 8 ++--- common.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common.h | 2 ++ host.c | 33 ++++++++++++------- host_cmd.c | 86 ++++++++++++++++++++++++++---------------------- mvm_cmds.c | 4 +-- netconn.c | 3 ++ netconn.h | 10 ++++++ prvm_cmds.c | 7 ++-- server.h | 5 --- sv_main.c | 78 ++++++++++++++++++++------------------------ svvm_cmds.c | 26 +++++++++------ 15 files changed, 292 insertions(+), 169 deletions(-) diff --git a/cl_main.c b/cl_main.c index c39741bf..346ebdd4 100644 --- a/cl_main.c +++ b/cl_main.c @@ -146,8 +146,6 @@ void CL_ClearState(void) // reset the view zoom interpolation cl.mviewzoom[0] = cl.mviewzoom[1] = 1; - SZ_Clear (&cls.message); - cl_num_entities = 0; cl_num_csqcentities = 0; //[515]: csqc cl_num_static_entities = 0; @@ -302,14 +300,21 @@ void CL_Disconnect(void) CL_StopPlayback(); else if (cls.netcon) { + sizebuf_t buf; + unsigned char bufdata[8]; if (cls.demorecording) CL_Stop_f(); + // send clc_disconnect 3 times to improve chances of server receiving + // it (but it still fails sometimes) Con_DPrint("Sending clc_disconnect\n"); - SZ_Clear(&cls.message); - MSG_WriteByte(&cls.message, clc_disconnect); - NetConn_SendUnreliableMessage(cls.netcon, &cls.message); - SZ_Clear(&cls.message); + memset(&buf, 0, sizeof(buf)); + buf.data = bufdata; + buf.maxsize = sizeof(bufdata); + MSG_WriteByte(&buf, clc_disconnect); + NetConn_SendUnreliableMessage(cls.netcon, &buf); + NetConn_SendUnreliableMessage(cls.netcon, &buf); + NetConn_SendUnreliableMessage(cls.netcon, &buf); NetConn_Close(cls.netcon); cls.netcon = NULL; } @@ -1528,23 +1533,17 @@ CL_SendCmd void CL_UpdatePrydonCursor(void); void CL_SendCmd(void) { - if (cls.demoplayback) - { - SZ_Clear(&cls.message); - return; - } - // send the reliable message (forwarded commands) if there is one - if (cls.message.cursize && NetConn_CanSendMessage(cls.netcon)) + 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.message); + SZ_HexDumpToConsole(&cls.netcon->message); } - if (NetConn_SendReliableMessage(cls.netcon, &cls.message) == -1) + if (NetConn_SendReliableMessage(cls.netcon, &cls.netcon->message) == -1) Host_Error("CL_WriteToServer: lost server connection"); - SZ_Clear(&cls.message); + SZ_Clear(&cls.netcon->message); } } @@ -1636,10 +1635,6 @@ void CL_Init (void) r_refdef.maxdrawqueuesize = 256 * 1024; r_refdef.drawqueue = (unsigned char *)Mem_Alloc(cl_mempool, r_refdef.maxdrawqueuesize); - cls.message.data = cls.message_buf; - cls.message.maxsize = sizeof(cls.message_buf); - cls.message.cursize = 0; - CL_InitInput (); // diff --git a/cl_parse.c b/cl_parse.c index aa58c514..f1cc56c1 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -268,50 +268,57 @@ An svc_signonnum has been received, perform a client side setup */ static void CL_SignonReply (void) { - //char str[8192]; - -Con_DPrintf("CL_SignonReply: %i\n", cls.signon); + Con_DPrintf("CL_SignonReply: %i\n", cls.signon); switch (cls.signon) { case 1: - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, "prespawn"); + if (cls.netcon) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, "prespawn"); + } break; case 2: - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("name \"%s\"", cl_name.string)); + if (cls.netcon) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("name \"%s\"", cl_name.string)); - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("color %i %i", cl_color.integer >> 4, cl_color.integer & 15)); + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("color %i %i", cl_color.integer >> 4, cl_color.integer & 15)); - if (cl_pmodel.integer) - { - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("pmodel %i", cl_pmodel.integer)); - } - if (*cl_playermodel.string) - { - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("playermodel %s", cl_playermodel.string)); - } - if (*cl_playerskin.string) - { - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("playerskin %s", cl_playerskin.string)); - } + if (cl_pmodel.integer) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("pmodel %i", cl_pmodel.integer)); + } + if (*cl_playermodel.string) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("playermodel %s", cl_playermodel.string)); + } + if (*cl_playerskin.string) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("playerskin %s", cl_playerskin.string)); + } - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va("rate %i", cl_rate.integer)); + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, va("rate %i", cl_rate.integer)); - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, "spawn"); + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, "spawn"); + } break; case 3: - MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, "begin"); + if (cls.netcon) + { + MSG_WriteByte (&cls.netcon->message, clc_stringcmd); + MSG_WriteString (&cls.netcon->message, "begin"); + } break; case 4: diff --git a/client.h b/client.h index 8bc6575e..7efd028c 100644 --- a/client.h +++ b/client.h @@ -451,9 +451,6 @@ typedef struct client_static_s int signon; // network connection netconn_t *netcon; - // writing buffer to send to server - sizebuf_t message; - unsigned char message_buf[1024]; } client_static_t; diff --git a/cmd.c b/cmd.c index a9a685f4..bc09a50d 100644 --- a/cmd.c +++ b/cmd.c @@ -1028,14 +1028,14 @@ void Cmd_ForwardStringToServer (const char *s) return; } - if (cls.demoplayback) - return; // not really connected + if (!cls.netcon) + return; // LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my // attention, it has been eradicated from here, its only (former) use in // all of darkplaces. - MSG_WriteByte(&cls.message, clc_stringcmd); - SZ_Write(&cls.message, (const unsigned char *)s, (int)strlen(s) + 1); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); + SZ_Write(&cls.netcon->message, (const unsigned char *)s, (int)strlen(s) + 1); } /* diff --git a/common.c b/common.c index 80bd2a4c..8bc5a3d5 100644 --- a/common.c +++ b/common.c @@ -1254,6 +1254,100 @@ char *SearchInfostring(const char *infostring, const char *key) } } +void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength) +{ + int pos, j; + size_t keylength; + if (!key) + key = ""; + if (!value) + value = ""; + keylength = strlen(key); + if (valuelength < 1 || !value) + { + Con_Printf("InfoString_GetValue: no room in value\n"); + return; + } + value[0] = 0; + if (strchr(key, '\\')) + { + Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key); + return; + } + if (!key[0]) + { + Con_Printf("InfoString_GetValue: can not look up a key with no name\n"); + return; + } + while (buffer[pos] == '\\') + { + if (!memcmp(buffer + pos+1, key, keylength)) + { + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + pos++; + for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < (int)valuelength - 1;j++) + value[j] = buffer[pos+j]; + value[j] = 0; + return; + } + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + } + // if we reach this point the key was not found +} + +void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value) +{ + int pos, pos2; + size_t keylength; + if (!key) + key = ""; + if (!value) + value = ""; + keylength = strlen(key); + if (strchr(key, '\\') || strchr(value, '\\')) + { + Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \\ which is not possible to store in an infostring\n", key, value); + return; + } + if (!key[0]) + { + Con_Printf("InfoString_SetValue: can not set a key with no name\n"); + return; + } + while (buffer[pos] == '\\') + { + if (!memcmp(buffer + pos+1, key, keylength)) + break; + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + } + // if we found the key, find the end of it because we will be replacing it + pos2 = pos; + if (buffer[pos] == '\\') + { + for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos++); + for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos++); + } + if (bufferlength <= 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2)) + { + Con_Printf("InfoString_SetValue: no room for \"%s\" \"%s\" in infostring\n", key, value); + return; + } + if (value && value[0]) + { + // set the key/value and append the remaining text + char tempbuffer[4096]; + strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer)); + sprintf(buffer + pos, "\\%s\\%s%s", key, value, tempbuffer); + } + else + { + // just remove the key from the text + strcpy(buffer + pos, buffer + pos2); + } +} + //======================================================== // strlcat and strlcpy, from OpenBSD diff --git a/common.h b/common.h index ffbcc8c1..b1cba03c 100644 --- a/common.h +++ b/common.h @@ -281,6 +281,8 @@ void freedirectory(stringlist_t *list); char *SearchInfostring(const char *infostring, const char *key); +void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength); +void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value); // strlcat and strlcpy, from OpenBSD // Most (all?) BSDs already have them diff --git a/host.c b/host.c index 3d52666e..180bb66c 100644 --- a/host.c +++ b/host.c @@ -294,8 +294,11 @@ FIXME: make this just a stuffed echo? */ void SV_ClientPrint(const char *msg) { - MSG_WriteByte(&host_client->message, svc_print); - MSG_WriteString(&host_client->message, msg); + if (host_client->netconnection) + { + MSG_WriteByte(&host_client->netconnection->message, svc_print); + MSG_WriteString(&host_client->netconnection->message, msg); + } } /* @@ -332,10 +335,10 @@ void SV_BroadcastPrint(const char *msg) for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) { - if (client->spawned) + if (client->spawned && client->netconnection) { - MSG_WriteByte(&client->message, svc_print); - MSG_WriteString(&client->message, msg); + MSG_WriteByte(&client->netconnection->message, svc_print); + MSG_WriteString(&client->netconnection->message, msg); } } @@ -374,12 +377,15 @@ void Host_ClientCommands(const char *fmt, ...) va_list argptr; char string[MAX_INPUTLINE]; + if (!host_client->netconnection) + return; + va_start(argptr,fmt); dpvsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); - MSG_WriteByte(&host_client->message, svc_stufftext); - MSG_WriteString(&host_client->message, string); + MSG_WriteByte(&host_client->netconnection->message, svc_stufftext); + MSG_WriteString(&host_client->netconnection->message, string); } /* @@ -404,10 +410,15 @@ void SV_DropClient(qboolean crash) if (!crash) { // LordHavoc: no opportunity for resending, so use unreliable 3 times - MSG_WriteByte(&host_client->message, svc_disconnect); - NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); - NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); - NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); + unsigned char bufdata[8]; + sizebuf_t buf; + memset(&buf, 0, sizeof(buf)); + buf.data = bufdata; + buf.maxsize = sizeof(bufdata); + MSG_WriteByte(&buf, svc_disconnect); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf); + NetConn_SendUnreliableMessage(host_client->netconnection, &buf); } // break the net connection NetConn_Close(host_client->netconnection); diff --git a/host_cmd.c b/host_cmd.c index c14d7752..f047ac75 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -1274,9 +1274,12 @@ void Host_PreSpawn_f (void) return; } - SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize); - MSG_WriteByte (&host_client->message, svc_signonnum); - MSG_WriteByte (&host_client->message, 2); + if (host_client->netconnection) + { + SZ_Write (&host_client->netconnection->message, sv.signon.data, sv.signon.cursize); + 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 @@ -1313,8 +1316,9 @@ void Host_Spawn_f (void) host_client->nametime = 0; // LordHavoc: moved this above the QC calls at FrikaC's request - // send all current names, colors, and frag counts - SZ_Clear (&host_client->message); + // LordHavoc: commented this out + //if (host_client->netconnection) + // SZ_Clear (&host_client->netconnection->message); // run the entrance script if (sv.loadgame) @@ -1352,24 +1356,29 @@ void Host_Spawn_f (void) PRVM_ExecuteProgram (prog->globals.server->PutClientInServer, "QC function PutClientInServer is missing"); } + host_client->sendsignon = true; + + if (!host_client->netconnection) + return; // send time of update - MSG_WriteByte (&host_client->message, svc_time); - MSG_WriteFloat (&host_client->message, sv.time); + MSG_WriteByte (&host_client->netconnection->message, svc_time); + MSG_WriteFloat (&host_client->netconnection->message, sv.time); + // send all current names, colors, and frag counts for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) { if (!client->active) continue; - MSG_WriteByte (&host_client->message, svc_updatename); - MSG_WriteByte (&host_client->message, i); - MSG_WriteString (&host_client->message, client->name); - MSG_WriteByte (&host_client->message, svc_updatefrags); - MSG_WriteByte (&host_client->message, i); - MSG_WriteShort (&host_client->message, client->frags); - MSG_WriteByte (&host_client->message, svc_updatecolors); - MSG_WriteByte (&host_client->message, i); - MSG_WriteByte (&host_client->message, client->colors); + MSG_WriteByte (&host_client->netconnection->message, svc_updatename); + MSG_WriteByte (&host_client->netconnection->message, i); + MSG_WriteString (&host_client->netconnection->message, client->name); + MSG_WriteByte (&host_client->netconnection->message, svc_updatefrags); + MSG_WriteByte (&host_client->netconnection->message, i); + MSG_WriteShort (&host_client->netconnection->message, client->frags); + MSG_WriteByte (&host_client->netconnection->message, svc_updatecolors); + MSG_WriteByte (&host_client->netconnection->message, i); + MSG_WriteByte (&host_client->netconnection->message, client->colors); } // send all current light styles @@ -1377,44 +1386,43 @@ void Host_Spawn_f (void) { if (sv.lightstyles[i][0]) { - MSG_WriteByte (&host_client->message, svc_lightstyle); - MSG_WriteByte (&host_client->message, (char)i); - MSG_WriteString (&host_client->message, sv.lightstyles[i]); + MSG_WriteByte (&host_client->netconnection->message, svc_lightstyle); + MSG_WriteByte (&host_client->netconnection->message, (char)i); + MSG_WriteString (&host_client->netconnection->message, sv.lightstyles[i]); } } // send some stats - MSG_WriteByte (&host_client->message, svc_updatestat); - MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS); - MSG_WriteLong (&host_client->message, prog->globals.server->total_secrets); + MSG_WriteByte (&host_client->netconnection->message, svc_updatestat); + MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALSECRETS); + MSG_WriteLong (&host_client->netconnection->message, prog->globals.server->total_secrets); - MSG_WriteByte (&host_client->message, svc_updatestat); - MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS); - MSG_WriteLong (&host_client->message, prog->globals.server->total_monsters); + MSG_WriteByte (&host_client->netconnection->message, svc_updatestat); + MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALMONSTERS); + MSG_WriteLong (&host_client->netconnection->message, prog->globals.server->total_monsters); - MSG_WriteByte (&host_client->message, svc_updatestat); - MSG_WriteByte (&host_client->message, STAT_SECRETS); - MSG_WriteLong (&host_client->message, prog->globals.server->found_secrets); + MSG_WriteByte (&host_client->netconnection->message, svc_updatestat); + MSG_WriteByte (&host_client->netconnection->message, STAT_SECRETS); + MSG_WriteLong (&host_client->netconnection->message, prog->globals.server->found_secrets); - MSG_WriteByte (&host_client->message, svc_updatestat); - MSG_WriteByte (&host_client->message, STAT_MONSTERS); - MSG_WriteLong (&host_client->message, prog->globals.server->killed_monsters); + MSG_WriteByte (&host_client->netconnection->message, svc_updatestat); + MSG_WriteByte (&host_client->netconnection->message, STAT_MONSTERS); + MSG_WriteLong (&host_client->netconnection->message, prog->globals.server->killed_monsters); // send a fixangle // Never send a roll angle, because savegames can catch the server // in a state where it is expecting the client to correct the angle // and it won't happen if the game was just loaded, so you wind up // with a permanent head tilt - MSG_WriteByte (&host_client->message, svc_setangle); - MSG_WriteAngle (&host_client->message, host_client->edict->fields.server->angles[0], sv.protocol); - MSG_WriteAngle (&host_client->message, host_client->edict->fields.server->angles[1], sv.protocol); - MSG_WriteAngle (&host_client->message, 0, sv.protocol); + MSG_WriteByte (&host_client->netconnection->message, svc_setangle); + MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->angles[0], sv.protocol); + MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->angles[1], sv.protocol); + MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol); - SV_WriteClientdataToMessage (host_client, host_client->edict, &host_client->message, stats); + SV_WriteClientdataToMessage (host_client, host_client->edict, &host_client->netconnection->message, stats); - MSG_WriteByte (&host_client->message, svc_signonnum); - MSG_WriteByte (&host_client->message, 3); - host_client->sendsignon = true; + MSG_WriteByte (&host_client->netconnection->message, svc_signonnum); + MSG_WriteByte (&host_client->netconnection->message, 3); } /* diff --git a/mvm_cmds.c b/mvm_cmds.c index 92a227c1..b9bda855 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -714,10 +714,10 @@ sizebuf_t *VM_WriteDest (void) case MSG_ONE: destclient = (int) PRVM_G_FLOAT(OFS_PARM2); - if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active) + if (destclient < 0 || destclient >= svs.maxclients || !svs.clients[destclient].active || !svs.clients[destclient].netconnection) PRVM_ERROR("VM_clientcommand: %s: invalid client !", PRVM_NAME); - return &svs.clients[destclient].message; + return &svs.clients[destclient].netconnection->message; case MSG_ALL: return &sv.reliable_datagram; diff --git a/netconn.c b/netconn.c index baa77b62..2f50f4d1 100755 --- a/netconn.c +++ b/netconn.c @@ -740,6 +740,9 @@ netconn_t *NetConn_Open(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress) conn->peeraddress = *peeraddress; conn->canSend = true; conn->lastMessageTime = realtime; + conn->message.data = conn->messagedata; + conn->message.maxsize = sizeof(conn->messagedata); + conn->message.cursize = 0; // LordHavoc: (inspired by ProQuake) use a short connect timeout to // reduce effectiveness of connection request floods conn->timeout = realtime + net_connecttimeout.value; diff --git a/netconn.h b/netconn.h index 1597f892..61d6f57c 100755 --- a/netconn.h +++ b/netconn.h @@ -128,12 +128,22 @@ typedef struct netconn_s 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 + // possible to send a reliable message and then cleared + sizebuf_t message; + unsigned char messagedata[NET_MAXMESSAGE]; + + // reliable message that is currently sending + // (for building fragments) unsigned int ackSequence; unsigned int sendSequence; unsigned int unreliableSendSequence; int sendMessageLength; unsigned char sendMessage[NET_MAXMESSAGE]; + // reliable message that is currently being received + // (for putting together fragments) unsigned int receiveSequence; unsigned int unreliableReceiveSequence; int receiveMessageLength; diff --git a/prvm_cmds.c b/prvm_cmds.c index db63a141..85af22e2 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -219,9 +219,12 @@ void VM_sprint (void) } client = svs.clients + clientnum; + if (!client->netconnection) + return; + VM_VarString(1, string, sizeof(string)); - MSG_WriteChar(&client->message,svc_print); - MSG_WriteString(&client->message, string); + MSG_WriteChar(&client->netconnection->message,svc_print); + MSG_WriteString(&client->netconnection->message, string); } /* diff --git a/server.h b/server.h index 6db16c4d..58e13ac5 100644 --- a/server.h +++ b/server.h @@ -107,8 +107,6 @@ typedef struct client_s qboolean clientconnectcalled; // false = don't send datagrams qboolean spawned; - // has been told to go to another level - qboolean dropasap; // only valid before spawned qboolean sendsignon; @@ -130,9 +128,6 @@ typedef struct client_s // intended motion calced from cmd vec3_t wishdir; - // can be added to at any time, copied and clear once per frame - sizebuf_t message; - unsigned char msgbuf[NET_MAXMESSAGE]; // PRVM_EDICT_NUM(clientnum+1) prvm_edict_t *edict; diff --git a/sv_main.c b/sv_main.c index af1a39ea..39a9d48a 100644 --- a/sv_main.c +++ b/sv_main.c @@ -296,6 +296,8 @@ void SV_SendServerinfo (client_t *client) int i; char message[128]; + // we know that this client has a netconnection and thus is not a bot + // edicts get reallocated on level changes, so we need to update it here client->edict = PRVM_EDICT_NUM((client - svs.clients) + 1); @@ -323,52 +325,52 @@ void SV_SendServerinfo (client_t *client) client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool); } - SZ_Clear (&client->message); - MSG_WriteByte (&client->message, svc_print); + SZ_Clear (&client->netconnection->message); + MSG_WriteByte (&client->netconnection->message, svc_print); dpsnprintf (message, sizeof (message), "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, prog->filecrc); - MSG_WriteString (&client->message,message); + MSG_WriteString (&client->netconnection->message,message); - // LordHavoc: this does not work on dedicated servers, needs fixing. + // FIXME: LordHavoc: this does not work on dedicated servers, needs fixing. //[515]: init csprogs according to version of svprogs, check the crc, etc. if(csqc_loaded && (cls.state == ca_dedicated || PRVM_NUM_FOR_EDICT(client->edict) != 1)) { - MSG_WriteByte (&client->message, svc_stufftext); + MSG_WriteByte (&client->netconnection->message, svc_stufftext); if(SV_InitCmd) - MSG_WriteString (&client->message, va("csqc_progcrc %i;%s\n", csqc_progcrc.integer, SV_InitCmd)); + MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i;%s\n", csqc_progcrc.integer, SV_InitCmd)); else - MSG_WriteString (&client->message, va("csqc_progcrc %i\n", csqc_progcrc.integer)); + MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i\n", csqc_progcrc.integer)); } - MSG_WriteByte (&client->message, svc_serverinfo); - MSG_WriteLong (&client->message, Protocol_NumberForEnum(sv.protocol)); - MSG_WriteByte (&client->message, svs.maxclients); + MSG_WriteByte (&client->netconnection->message, svc_serverinfo); + MSG_WriteLong (&client->netconnection->message, Protocol_NumberForEnum(sv.protocol)); + MSG_WriteByte (&client->netconnection->message, svs.maxclients); if (!coop.integer && deathmatch.integer) - MSG_WriteByte (&client->message, GAME_DEATHMATCH); + MSG_WriteByte (&client->netconnection->message, GAME_DEATHMATCH); else - MSG_WriteByte (&client->message, GAME_COOP); + MSG_WriteByte (&client->netconnection->message, GAME_COOP); - MSG_WriteString (&client->message,PRVM_GetString(prog->edicts->fields.server->message)); + MSG_WriteString (&client->netconnection->message,PRVM_GetString(prog->edicts->fields.server->message)); for (i = 1;i < MAX_MODELS && sv.model_precache[i][0];i++) - MSG_WriteString (&client->message, sv.model_precache[i]); - MSG_WriteByte (&client->message, 0); + MSG_WriteString (&client->netconnection->message, sv.model_precache[i]); + MSG_WriteByte (&client->netconnection->message, 0); for (i = 1;i < MAX_SOUNDS && sv.sound_precache[i][0];i++) - MSG_WriteString (&client->message, sv.sound_precache[i]); - MSG_WriteByte (&client->message, 0); + MSG_WriteString (&client->netconnection->message, sv.sound_precache[i]); + MSG_WriteByte (&client->netconnection->message, 0); // send music - MSG_WriteByte (&client->message, svc_cdtrack); - MSG_WriteByte (&client->message, prog->edicts->fields.server->sounds); - MSG_WriteByte (&client->message, prog->edicts->fields.server->sounds); + MSG_WriteByte (&client->netconnection->message, svc_cdtrack); + MSG_WriteByte (&client->netconnection->message, prog->edicts->fields.server->sounds); + MSG_WriteByte (&client->netconnection->message, prog->edicts->fields.server->sounds); // set view - MSG_WriteByte (&client->message, svc_setview); - MSG_WriteShort (&client->message, PRVM_NUM_FOR_EDICT(client->edict)); + MSG_WriteByte (&client->netconnection->message, svc_setview); + MSG_WriteShort (&client->netconnection->message, PRVM_NUM_FOR_EDICT(client->edict)); - MSG_WriteByte (&client->message, svc_signonnum); - MSG_WriteByte (&client->message, 1); + MSG_WriteByte (&client->netconnection->message, svc_signonnum); + MSG_WriteByte (&client->netconnection->message, 1); client->sendsignon = true; client->spawned = false; // need prespawn, spawn, etc @@ -406,9 +408,7 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) strcpy(client->old_name, "unconnected"); client->spawned = false; client->edict = PRVM_EDICT_NUM(clientnum+1); - client->message.data = client->msgbuf; - client->message.maxsize = sizeof(client->msgbuf); - client->message.allowoverflow = true; // we can catch it + client->netconnection->message.allowoverflow = true; // we can catch it // updated by receiving "rate" command from client client->rate = NET_MINRATE; // no limits for local player @@ -1328,7 +1328,7 @@ void SV_UpdateToReliableMessages (void) for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++) if (client->netconnection) - SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); + SZ_Write (&client->netconnection->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); SZ_Clear (&sv.reliable_datagram); } @@ -1376,12 +1376,9 @@ void SV_SendClientMessages (void) if (!host_client->active) continue; if (!host_client->netconnection) - { - SZ_Clear(&host_client->message); continue; - } - if (host_client->message.overflowed) + if (host_client->netconnection->message.overflowed) { SV_DropClient (true); // if the message couldn't send, kick off continue; @@ -1413,21 +1410,16 @@ void SV_SendClientMessages (void) } } - if (host_client->message.cursize || host_client->dropasap) + if (host_client->netconnection->message.cursize) { if (!NetConn_CanSendMessage (host_client->netconnection)) continue; - if (host_client->dropasap) - SV_DropClient (false); // went to another level - else - { - if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1) - SV_DropClient (true); // if the message couldn't send, kick off - SZ_Clear (&host_client->message); - host_client->last_message = realtime; - host_client->sendsignon = false; - } + 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; } } diff --git a/svvm_cmds.c b/svvm_cmds.c index 110234b6..40d6c175 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -265,9 +265,12 @@ void PF_sprint (void) } client = svs.clients + entnum-1; + if (!client->netconnection) + return; + VM_VarString(1, string, sizeof(string)); - MSG_WriteChar(&client->message,svc_print); - MSG_WriteString(&client->message, string); + MSG_WriteChar(&client->netconnection->message,svc_print); + MSG_WriteString(&client->netconnection->message, string); } @@ -295,9 +298,12 @@ void PF_centerprint (void) } client = svs.clients + entnum-1; + if (!client->netconnection) + return; + VM_VarString(1, string, sizeof(string)); - MSG_WriteChar(&client->message,svc_centerprint); - MSG_WriteString(&client->message, string); + MSG_WriteChar(&client->netconnection->message,svc_centerprint); + MSG_WriteString(&client->netconnection->message, string); } /* @@ -869,11 +875,11 @@ void PF_lightstyle (void) for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++) { - if (client->active) + if (client->active && client->netconnection) { - MSG_WriteChar (&client->message, svc_lightstyle); - MSG_WriteChar (&client->message,style); - MSG_WriteString (&client->message, val); + MSG_WriteChar (&client->netconnection->message, svc_lightstyle); + MSG_WriteChar (&client->netconnection->message,style); + MSG_WriteString (&client->netconnection->message, val); } } } @@ -1126,13 +1132,13 @@ sizebuf_t *WriteDest (void) case MSG_ONE: ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity); entnum = PRVM_NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection) { Con_Printf ("WriteDest: tried to write to non-client\n"); return &sv.reliable_datagram; } else - return &svs.clients[entnum-1].message; + return &svs.clients[entnum-1].netconnection->message; default: Con_Printf ("WriteDest: bad destination\n"); -- 2.39.2