]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
cleaned up edict clearing when connecting or coming back from a level change, this...
[xonotic/darkplaces.git] / sv_main.c
index 99ece146d702b60561627539ef038c97461609aa..bb18539c231c804fc6bfe609aede060d15488ee5 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -209,19 +209,19 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
 
        if (volume < 0 || volume > 255)
        {
-               Con_Printf ("SV_StartSound: volume = %i", volume);
+               Con_Printf ("SV_StartSound: volume = %i\n", volume);
                return;
        }
 
        if (attenuation < 0 || attenuation > 4)
        {
-               Con_Printf ("SV_StartSound: attenuation = %f", attenuation);
+               Con_Printf ("SV_StartSound: attenuation = %f\n", attenuation);
                return;
        }
 
        if (channel < 0 || channel > 7)
        {
-               Con_Printf ("SV_StartSound: channel = %i", channel);
+               Con_Printf ("SV_StartSound: channel = %i\n", channel);
                return;
        }
 
@@ -291,26 +291,9 @@ void SV_SendServerinfo (client_t *client)
        // edicts get reallocated on level changes, so we need to update it here
        client->edict = PRVM_EDICT_NUM((client - svs.clients) + 1);
 
-       // if client is a botclient coming from a level change, we need to set up
-       // client info that normally requires networking
-       if (!client->netconnection)
-       {
-               // set up the edict
-                PRVM_ED_ClearEdict(client->edict);
-
-               // copy spawn parms out of the client_t
-               for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
-                       (&prog->globals.server->parm1)[i] = host_client->spawn_parms[i];
-
-               // call the spawn function
-               host_client->clientconnectcalled = true;
-               prog->globals.server->time = sv.time;
-               prog->globals.server->self = PRVM_EDICT_TO_PROG(client->edict);
-               PRVM_ExecuteProgram (prog->globals.server->ClientConnect, "QC function ClientConnect is missing");
-               PRVM_ExecuteProgram (prog->globals.server->PutClientInServer, "QC function PutClientInServer is missing");
-               host_client->spawned = true;
-               return;
-       }
+       // clear cached stuff that depends on the level
+       client->weaponmodel[0] = 0;
+       client->weaponmodelindex = 0;
 
        // LordHavoc: clear entityframe tracking
        client->latestframenum = 0;
@@ -423,6 +406,9 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection)
                        client->spawn_parms[i] = (&prog->globals.server->parm1)[i];
        }
 
+       // set up the entity for this client (including .colormap, .team, etc)
+       PRVM_ED_ClearEdict(client->edict);
+
        // don't call SendServerinfo for a fresh botclient because its fields have
        // not been set up by the qc yet
        if (client->netconnection)
@@ -463,7 +449,7 @@ crosses a waterline.
 */
 
 int sv_writeentitiestoclient_pvsbytes;
-qbyte sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
+unsigned char sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
 
 static int numsendentities;
 static entity_state_t sendentities[MAX_EDICTS];
@@ -507,7 +493,7 @@ void SV_PrepareEntitiesForSending(void)
 
                flags = 0;
                i = (int)(PRVM_GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
-               glowsize = (qbyte)bound(0, i, 255);
+               glowsize = (unsigned char)bound(0, i, 255);
                if (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
                        flags |= RENDER_GLOWTRAIL;
 
@@ -519,8 +505,8 @@ void SV_PrepareEntitiesForSending(void)
                light[2] = (unsigned short)bound(0, f, 65535);
                f = PRVM_GETEDICTFIELDVALUE(ent, eval_light_lev)->_float;
                light[3] = (unsigned short)bound(0, f, 65535);
-               lightstyle = (qbyte)PRVM_GETEDICTFIELDVALUE(ent, eval_style)->_float;
-               lightpflags = (qbyte)PRVM_GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
+               lightstyle = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_style)->_float;
+               lightpflags = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
 
                if (gamemode == GAME_TENEBRAE)
                {
@@ -587,7 +573,7 @@ void SV_PrepareEntitiesForSending(void)
                cs.nodrawtoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
                cs.drawonlytoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
                cs.tagentity = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
-               cs.tagindex = (qbyte)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
+               cs.tagindex = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
                cs.glowsize = glowsize;
 
                // don't need to init cs.colormod because the defaultstate did that for us
@@ -607,14 +593,14 @@ void SV_PrepareEntitiesForSending(void)
                if (f)
                {
                        i = (int)f;
-                       cs.alpha = (qbyte)bound(0, i, 255);
+                       cs.alpha = (unsigned char)bound(0, i, 255);
                }
                // halflife
                f = (PRVM_GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
                if (f)
                {
                        i = (int)f;
-                       cs.alpha = (qbyte)bound(0, i, 255);
+                       cs.alpha = (unsigned char)bound(0, i, 255);
                }
 
                cs.scale = 16;
@@ -622,7 +608,7 @@ void SV_PrepareEntitiesForSending(void)
                if (f)
                {
                        i = (int)f;
-                       cs.scale = (qbyte)bound(0, i, 255);
+                       cs.scale = (unsigned char)bound(0, i, 255);
                }
 
                cs.glowcolor = 254;
@@ -656,20 +642,21 @@ void SV_PrepareEntitiesForSending(void)
                // specialvisibilityradius)
                if ((model = sv.models[modelindex]))
                {
+                       float scale = cs.scale * (1.0f / 16.0f);
                        if (cs.angles[0] || cs.angles[2]) // pitch and roll
                        {
-                               VectorAdd(cs.origin, model->rotatedmins, cullmins);
-                               VectorAdd(cs.origin, model->rotatedmaxs, cullmaxs);
+                               VectorMA(cs.origin, scale, model->rotatedmins, cullmins);
+                               VectorMA(cs.origin, scale, model->rotatedmaxs, cullmaxs);
                        }
                        else if (cs.angles[1])
                        {
-                               VectorAdd(cs.origin, model->yawmins, cullmins);
-                               VectorAdd(cs.origin, model->yawmaxs, cullmaxs);
+                               VectorMA(cs.origin, scale, model->yawmins, cullmins);
+                               VectorMA(cs.origin, scale, model->yawmaxs, cullmaxs);
                        }
                        else
                        {
-                               VectorAdd(cs.origin, model->normalmins, cullmins);
-                               VectorAdd(cs.origin, model->normalmaxs, cullmaxs);
+                               VectorMA(cs.origin, scale, model->normalmins, cullmins);
+                               VectorMA(cs.origin, scale, model->normalmaxs, cullmaxs);
                        }
                }
                else
@@ -927,7 +914,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        int             items;
        prvm_eval_t     *val;
        vec3_t  punchvector;
-       qbyte   viewzoom;
+       unsigned char   viewzoom;
        const char *s;
 
 //
@@ -1144,7 +1131,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
 SV_SendClientDatagram
 =======================
 */
-static qbyte sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
+static unsigned char sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
 qboolean SV_SendClientDatagram (client_t *client)
 {
        int rate, maxrate, maxsize, maxsize2;
@@ -1310,7 +1297,7 @@ message buffer
 void SV_SendNop (client_t *client)
 {
        sizebuf_t       msg;
-       qbyte           buf[4];
+       unsigned char           buf[4];
 
        msg.data = buf;
        msg.maxsize = sizeof(buf);
@@ -1592,7 +1579,7 @@ void SV_SendReconnect (void)
        MSG_WriteByte(&sv.reliable_datagram, svc_stufftext);
        MSG_WriteString(&sv.reliable_datagram, "reconnect\n");
 #else
-       qbyte data[128];
+       unsigned char data[128];
        sizebuf_t msg;
 
        msg.data = data;
@@ -1667,8 +1654,8 @@ void SV_IncreaseEdicts(void)
 
        for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
        {
-               ent->priv.vp = (qbyte*) prog->edictprivate + i * prog->edictprivate_size;
-               ent->fields.server = (void *)((qbyte *)prog->edictsfields + i * prog->edict_size);
+               ent->priv.vp = (unsigned char*) prog->edictprivate + i * prog->edictprivate_size;
+               ent->fields.server = (void *)((unsigned char *)prog->edictsfields + i * prog->edict_size);
                // link every entity except world
                if (!ent->priv.server->free)
                        SV_LinkEdict(ent, false);
@@ -1784,14 +1771,10 @@ void SV_SpawnServer (const char *server)
        /*for (i = 0;i < prog->max_edicts;i++)
        {
                ent = prog->edicts + i;
-               ent->priv.vp = (qbyte*) prog->edictprivate + i * prog->edictprivate_size;
-               ent->fields.server = (void *)((qbyte *)prog->edictsfields + i * prog->edict_size);
+               ent->priv.vp = (unsigned char*) prog->edictprivate + i * prog->edictprivate_size;
+               ent->fields.server = (void *)((unsigned char *)prog->edictsfields + i * prog->edict_size);
        }*/
 
-       // fix up client->edict pointers for returning clients right away...
-       for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
-               host_client->edict = PRVM_EDICT_NUM(i + 1);
-
        sv.datagram.maxsize = sizeof(sv.datagram_buf);
        sv.datagram.cursize = 0;
        sv.datagram.data = sv.datagram_buf;
@@ -1858,10 +1841,21 @@ void SV_SpawnServer (const char *server)
 // serverflags are for cross level information (sigils)
        prog->globals.server->serverflags = svs.serverflags;
 
+       // we need to reset the spawned flag on all connected clients here so that
+       // their thinks don't run during startup (before PutClientInServer)
+       // we also need to set up the client entities now
+       // and we need to set the ->edict pointers to point into the progs edicts
+       for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
+       {
+               host_client->spawned = false;
+               host_client->edict = PRVM_EDICT_NUM(i + 1);
+               PRVM_ED_ClearEdict(host_client->edict);
+       }
+
        // load replacement entity file if found
        entities = NULL;
        if (sv_entpatch.integer)
-               entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true);
+               entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true, NULL);
        if (entities)
        {
                Con_Printf("Loaded maps/%s.ent\n", sv.name);
@@ -1879,11 +1873,6 @@ void SV_SpawnServer (const char *server)
        sv.state = ss_active;
        prog->allowworldwrites = false;
 
-       // we need to reset the spawned flag on all connected clients here so that
-       // their thinks don't run during startup (before PutClientInServer)
-       for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
-               host_client->spawned = false;
-
 // run two frames to allow everything to settle
        for (i = 0;i < 2;i++)
        {
@@ -1897,11 +1886,32 @@ void SV_SpawnServer (const char *server)
        if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
                SV_CreateBaseline ();
 
-// send serverinfo to all connected clients
-       // (note this also handles botclients coming back from a level change)
+// send serverinfo to all connected clients, and set up botclients coming back from a level change
        for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
-               if (host_client->active)
+       {
+               if (!host_client->active)
+                       continue;
+               if (host_client->netconnection)
                        SV_SendServerinfo(host_client);
+               else
+               {
+                       int j;
+                       // if client is a botclient coming from a level change, we need to
+                       // set up client info that normally requires networking
+
+                       // copy spawn parms out of the client_t
+                       for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
+                               (&prog->globals.server->parm1)[j] = host_client->spawn_parms[j];
+
+                       // call the spawn function
+                       host_client->clientconnectcalled = true;
+                       prog->globals.server->time = sv.time;
+                       prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
+                       PRVM_ExecuteProgram (prog->globals.server->ClientConnect, "QC function ClientConnect is missing");
+                       PRVM_ExecuteProgram (prog->globals.server->PutClientInServer, "QC function PutClientInServer is missing");
+                       host_client->spawned = true;
+               }
+       }
 
        Con_DPrint("Server spawned.\n");
        NetConn_Heartbeat (2);
@@ -1962,9 +1972,9 @@ void SV_VM_CB_InitEdict(prvm_edict_t *e)
                        val->_float = svs.clients[num].colors;
                // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
                if( eval_playermodel )
-                       PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
+                       PRVM_GETEDICTFIELDVALUE(e, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
                if( eval_playerskin )
-                       PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
+                       PRVM_GETEDICTFIELDVALUE(e, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
        }
 }