]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
added SV_PointContents
[xonotic/darkplaces.git] / sv_main.c
index a80badc1a132030f8e9bd60b38f302d39304b67f..74fd70ba600a0c7890d3ca64926085a1901763e7 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -28,8 +28,8 @@ static cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "1"}; // tend
 static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
 static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
 
-server_t               sv;
-server_static_t        svs;
+server_t sv;
+server_static_t svs;
 
 static char localmodels[MAX_MODELS][5];                        // inline model names for precache
 
@@ -59,7 +59,6 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_idealpitchscale);
        Cvar_RegisterVariable (&sv_aim);
        Cvar_RegisterVariable (&sv_nostep);
-       Cvar_RegisterVariable (&sv_predict);
        Cvar_RegisterVariable (&sv_deltacompress);
        Cvar_RegisterVariable (&sv_cullentities_pvs);
        Cvar_RegisterVariable (&sv_cullentities_portal);
@@ -164,13 +163,9 @@ Larger attenuations will drop off.  (max 4 attenuation)
 
 ==================
 */
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
-    float attenuation)
+void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
 {
-    int         sound_num;
-    int field_mask;
-    int                        i;
-       int                     ent;
+       int sound_num, field_mask, i, ent;
 
        if (volume < 0 || volume > 255)
                Host_Error ("SV_StartSound: volume = %i", volume);
@@ -185,16 +180,15 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
                return;
 
 // find precache number for sound
-    for (sound_num=1 ; sound_num<MAX_SOUNDS
-        && sv.sound_precache[sound_num] ; sound_num++)
-        if (!strcmp(sample, sv.sound_precache[sound_num]))
-            break;
+       for (sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
+               if (!strcmp(sample, sv.sound_precache[sound_num]))
+                       break;
 
-    if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
-    {
-        Con_Printf ("SV_StartSound: %s not precached\n", sample);
-        return;
-    }
+       if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
+       {
+               Con_Printf ("SV_StartSound: %s not precached\n", sample);
+               return;
+       }
 
        ent = NUM_FOR_EDICT(entity);
 
@@ -251,6 +245,9 @@ void SV_SendServerinfo (client_t *client)
        char                    **s;
        char                    message[128];
 
+       // edicts get reallocated on level changes, so we need to update it here
+       client->edict = EDICT_NUM((client - svs.clients) + 1);
+
        // LordHavoc: clear entityframe tracking
        client->entityframenumber = 0;
        EntityFrame_ClearDatabase(&client->entitydatabase);
@@ -316,9 +313,10 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection)
        memset (client, 0, sizeof(*client));
        client->netconnection = netconnection;
 
-       Con_DPrintf ("Client %s connected\n", client->netconnection->address);
+       Con_DPrintf("Client %s connected\n", client->netconnection->address);
 
-       strcpy (client->name, "unconnected");
+       strcpy(client->name, "unconnected");
+       strcpy(client->old_name, "unconnected");
        client->active = true;
        client->spawned = false;
        client->edict = EDICT_NUM(clientnum+1);
@@ -334,10 +332,6 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection)
                PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
                for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
                        client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
-               // set up the edict a bit
-               ED_ClearEdict(client->edict);
-               client->edict->v->colormap = NUM_FOR_EDICT(client->edict);
-               client->edict->v->netname = PR_SetString(client->name);
        }
 
        SV_SendServerinfo (client);
@@ -391,7 +385,7 @@ void SV_AddToFatPVS (vec3_t org, mnode_t *node)
                {
                        if (node->contents != CONTENTS_SOLID)
                        {
-                               pvs = sv.worldmodel->LeafPVS(sv.worldmodel, (mleaf_t *)node);
+                               pvs = sv.worldmodel->brushq1.LeafPVS(sv.worldmodel, (mleaf_t *)node);
                                for (i=0 ; i<fatbytes ; i++)
                                        fatpvs[i] |= pvs[i];
                        }
@@ -422,9 +416,9 @@ given point.
 */
 qbyte *SV_FatPVS (vec3_t org)
 {
-       fatbytes = (sv.worldmodel->numleafs+31)>>3;
+       fatbytes = (sv.worldmodel->brushq1.numleafs+31)>>3;
        memset (fatpvs, 0, fatbytes);
-       SV_AddToFatPVS (org, sv.worldmodel->nodes);
+       SV_AddToFatPVS (org, sv.worldmodel->brushq1.nodes);
        return fatpvs;
 }
 
@@ -440,7 +434,7 @@ loc0:
                // leaf
                if (node->contents == CONTENTS_SOLID)
                        return false;
-               leafnum = (mleaf_t *)node - sv.worldmodel->leafs - 1;
+               leafnum = (mleaf_t *)node - sv.worldmodel->brushq1.leafs - 1;
                return pvs[leafnum >> 3] & (1 << (leafnum & 7));
        }
 
@@ -555,17 +549,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                }
 
                VectorCopy(ent->v->angles, angles);
-               if (DotProduct(ent->v->velocity, ent->v->velocity) >= 1.0f)
-               {
-                       VectorMA(ent->v->origin, host_client->latency, ent->v->velocity, origin);
-                       // LordHavoc: trace predicted movement to avoid putting things in walls
-                       trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, origin, MOVE_NORMAL, ent);
-                       VectorCopy(trace.endpos, origin);
-               }
-               else
-               {
-                       VectorCopy(ent->v->origin, origin);
-               }
+               VectorCopy(ent->v->origin, origin);
 
                // ent has survived every check so far, check if it is visible
                if (ent != clent && ((bits & U_VIEWMODEL) == 0))
@@ -600,7 +584,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        totalentities++;
 
                        // if not touching a visible leaf
-                       if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes))
+                       if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->brushq1.nodes))
                        {
                                culled_pvs++;
                                continue;
@@ -621,7 +605,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
                                testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
 
-                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
+                               if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
+                                       sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, testeye, vec3_origin, vec3_origin, testorigin);
+                               else
+                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
 
                                if (trace.fraction == 1)
                                        client->visibletime[e] = realtime + 1;
@@ -632,7 +619,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                        testorigin[1] = bound(entmins[1], testeye[1], entmaxs[1]);
                                        testorigin[2] = bound(entmins[2], testeye[2], entmaxs[2]);
 
-                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
+                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
+                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, testeye, vec3_origin, vec3_origin, testorigin);
+                                       else
+                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
 
                                        if (trace.fraction == 1)
                                                client->visibletime[e] = realtime + 1;
@@ -937,17 +927,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                }
 
                VectorCopy(ent->v->angles, angles);
-               if (DotProduct(ent->v->velocity, ent->v->velocity) >= 1.0f && host_client->latency >= 0.01f)
-               {
-                       VectorMA(ent->v->origin, host_client->latency, ent->v->velocity, origin);
-                       // LordHavoc: trace predicted movement to avoid putting things in walls
-                       trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, origin, MOVE_NORMAL, ent);
-                       VectorCopy(trace.endpos, origin);
-               }
-               else
-               {
-                       VectorCopy(ent->v->origin, origin);
-               }
+               VectorCopy(ent->v->origin, origin);
 
                // ent has survived every check so far, check if it is visible
                // always send embedded brush models, they don't generate much traffic
@@ -989,7 +969,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        totalentities++;
 
                        // if not touching a visible leaf
-                       if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, lightmins, lightmaxs, sv.worldmodel->nodes))
+                       if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, lightmins, lightmaxs, sv.worldmodel->brushq1.nodes))
                        {
                                culled_pvs++;
                                continue;
@@ -1008,7 +988,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                testorigin[0] = (entmins[0] + entmaxs[0]) * 0.5f;
                                testorigin[1] = (entmins[1] + entmaxs[1]) * 0.5f;
                                testorigin[2] = (entmins[2] + entmaxs[2]) * 0.5f;
-                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
+                               if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
+                                       sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
+                               else
+                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
                                if (trace.fraction == 1)
                                        client->visibletime[e] = realtime + 1;
                                else
@@ -1017,7 +1000,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                        testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
                                        testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
                                        testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
-                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
+                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
+                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
+                                       else
+                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
                                        if (trace.fraction == 1)
                                                client->visibletime[e] = realtime + 1;
                                        else
@@ -1028,7 +1014,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                                        testorigin[0] = lhrandom(lightmins[0], lightmaxs[0]);
                                                        testorigin[1] = lhrandom(lightmins[1], lightmaxs[1]);
                                                        testorigin[2] = lhrandom(lightmins[2], lightmaxs[2]);
-                                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
+                                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
+                                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
+                                                       else
+                                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
                                                        if (trace.fraction == 1)
                                                                client->visibletime[e] = realtime + 1;
                                                        else
@@ -1378,59 +1367,63 @@ void SV_UpdateToReliableMessages (void)
 // check for changes to be sent over the reliable streams
        for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
        {
-               // update the host_client fields we care about according to the entity fields
-               sv_player = host_client->edict;
-               s = PR_GetString(sv_player->v->netname);
-               if (s != host_client->name)
-               {
-                       if (s == NULL)
-                               s = "";
-                       // point the string back at host_client->name to keep it safe
-                       strncpy(host_client->name, s, sizeof(host_client->name) - 1);
-                       sv_player->v->netname = PR_SetString(host_client->name);
-               }
-               if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors)) && host_client->colors != val->_float)
-                       host_client->colors = val->_float;
-               host_client->frags = sv_player->v->frags;
-               if (gamemode == GAME_NEHAHRA)
-                       if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)) && host_client->pmodel != val->_float)
-                               host_client->pmodel = val->_float;
-
-               // if the fields changed, send messages about the changes
-               if (strcmp(host_client->old_name, host_client->name))
+               // only update the client fields if they've spawned in
+               if (host_client->spawned)
                {
-                       strcpy(host_client->old_name, host_client->name);
-                       for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                       // update the host_client fields we care about according to the entity fields
+                       sv_player = host_client->edict;
+                       s = PR_GetString(sv_player->v->netname);
+                       if (s != host_client->name)
                        {
-                               if (!client->active || !client->spawned)
-                                       continue;
-                               MSG_WriteByte (&client->message, svc_updatename);
-                               MSG_WriteByte (&client->message, i);
-                               MSG_WriteString (&client->message, host_client->name);
+                               if (s == NULL)
+                                       s = "";
+                               // point the string back at host_client->name to keep it safe
+                               strncpy(host_client->name, s, sizeof(host_client->name) - 1);
+                               sv_player->v->netname = PR_SetString(host_client->name);
                        }
-               }
-               if (host_client->old_colors != host_client->colors)
-               {
-                       host_client->old_colors = host_client->colors;
-                       for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                       if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors)) && host_client->colors != val->_float)
+                               host_client->colors = val->_float;
+                       host_client->frags = sv_player->v->frags;
+                       if (gamemode == GAME_NEHAHRA)
+                               if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)) && host_client->pmodel != val->_float)
+                                       host_client->pmodel = val->_float;
+
+                       // if the fields changed, send messages about the changes
+                       if (strcmp(host_client->old_name, host_client->name))
                        {
-                               if (!client->active || !client->spawned)
-                                       continue;
-                               MSG_WriteByte (&client->message, svc_updatecolors);
-                               MSG_WriteByte (&client->message, i);
-                               MSG_WriteByte (&client->message, host_client->colors);
+                               strcpy(host_client->old_name, host_client->name);
+                               for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                               {
+                                       if (!client->active || !client->spawned)
+                                               continue;
+                                       MSG_WriteByte (&client->message, svc_updatename);
+                                       MSG_WriteByte (&client->message, i);
+                                       MSG_WriteString (&client->message, host_client->name);
+                               }
                        }
-               }
-               if (host_client->old_frags != host_client->frags)
-               {
-                       host_client->old_frags = host_client->frags;
-                       for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                       if (host_client->old_colors != host_client->colors)
                        {
-                               if (!client->active || !client->spawned)
-                                       continue;
-                               MSG_WriteByte (&client->message, svc_updatefrags);
-                               MSG_WriteByte (&client->message, i);
-                               MSG_WriteShort (&client->message, host_client->frags);
+                               host_client->old_colors = host_client->colors;
+                               for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                               {
+                                       if (!client->active || !client->spawned)
+                                               continue;
+                                       MSG_WriteByte (&client->message, svc_updatecolors);
+                                       MSG_WriteByte (&client->message, i);
+                                       MSG_WriteByte (&client->message, host_client->colors);
+                               }
+                       }
+                       if (host_client->old_frags != host_client->frags)
+                       {
+                               host_client->old_frags = host_client->frags;
+                               for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
+                               {
+                                       if (!client->active || !client->spawned)
+                                               continue;
+                                       MSG_WriteByte (&client->message, svc_updatefrags);
+                                       MSG_WriteByte (&client->message, i);
+                                       MSG_WriteShort (&client->message, host_client->frags);
+                               }
                        }
                }
        }
@@ -1713,9 +1706,16 @@ void SV_IncreaseEdicts(void)
        void *oldedictsfields = sv.edictsfields;
        void *oldmoved_edicts = sv.moved_edicts;
 
+       if (sv.max_edicts >= MAX_EDICTS)
+               return;
+
        // links don't survive the transition, so unlink everything
-       for (i = 0;i < sv.max_edicts;i++)
-               SV_UnlinkEdict (sv.edicts + i);
+       for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
+       {
+               if (!ent->e->free)
+                       SV_UnlinkEdict(sv.edicts + i);
+               memset(&ent->e->areagrid, 0, sizeof(ent->e->areagrid));
+       }
        SV_ClearWorld();
 
        sv.max_edicts   = min(sv.max_edicts + 32, MAX_EDICTS);
@@ -1726,13 +1726,12 @@ void SV_IncreaseEdicts(void)
        memcpy(sv.edictsengineprivate, oldedictsengineprivate, oldmax_edicts * sizeof(edict_engineprivate_t));
        memcpy(sv.edictsfields, oldedictsfields, oldmax_edicts * pr_edict_size);
 
-       for (i = 0;i < sv.max_edicts;i++)
+       for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
        {
-               ent = sv.edicts + i;
                ent->e = sv.edictsengineprivate + i;
                ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
                // link every entity except world
-               if (i > 0)
+               if (!ent->e->free)
                        SV_LinkEdict(ent, false);
        }
 
@@ -1829,8 +1828,6 @@ void SV_SpawnServer (const char *server)
 
 // leave slots at start for clients only
        sv.num_edicts = svs.maxclients+1;
-       for (i=0 ; i<svs.maxclients ; i++)
-               svs.clients[i].edict = EDICT_NUM(i+1);
 
        sv.state = ss_loading;
        sv.paused = false;
@@ -1859,7 +1856,7 @@ void SV_SpawnServer (const char *server)
 
        sv.model_precache[0] = "";
        sv.model_precache[1] = sv.modelname;
-       for (i = 1;i < sv.worldmodel->numsubmodels;i++)
+       for (i = 1;i < sv.worldmodel->brushq1.numsubmodels;i++)
        {
                sv.model_precache[i+1] = localmodels[i];
                sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);
@@ -1876,7 +1873,7 @@ void SV_SpawnServer (const char *server)
        ent->v->solid = SOLID_BSP;
        ent->v->movetype = MOVETYPE_PUSH;
 
-       if (coop.integer)
+       if (coop.value)
                pr_global_struct->coop = coop.integer;
        else
                pr_global_struct->deathmatch = deathmatch.integer;
@@ -1897,7 +1894,7 @@ void SV_SpawnServer (const char *server)
                Mem_Free(entities);
        }
        else
-               ED_LoadFromFile (sv.worldmodel->entities);
+               ED_LoadFromFile (sv.worldmodel->brush.entities);
 
 
        // LordHavoc: clear world angles (to fix e3m3.bsp)
@@ -1909,10 +1906,11 @@ void SV_SpawnServer (const char *server)
        sv.state = ss_active;
 
 // run two frames to allow everything to settle
-       sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
-       SV_Physics ();
-       sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
-       SV_Physics ();
+       for (i = 0;i < 2;i++)
+       {
+               sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
+               SV_Physics ();
+       }
 
        Mod_PurgeUnused();