]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
improved pr_fields command to list how many entities are using each entity field...
[xonotic/darkplaces.git] / sv_main.c
index 1ea395fa856b2753c70f149f4f43009bdafec679..0a5b5bdf8c500f8de57c1d204f52d538106b5d40 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -35,6 +35,9 @@ static mempool_t *sv_edicts_mempool = NULL;
 
 //============================================================================
 
+extern void SV_Phys_Init (void);
+extern void SV_World_Init (void);
+
 /*
 ===============
 SV_Init
@@ -61,6 +64,9 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_cullentities_trace);
        Cvar_RegisterVariable (&sv_cullentities_stats);
 
+       SV_Phys_Init();
+       SV_World_Init();
+
        for (i = 0;i < MAX_MODELS;i++)
                sprintf (localmodels[i], "*%i", i);
 
@@ -246,7 +252,7 @@ void SV_SendServerinfo (client_t *client)
        MSG_WriteString (&client->message,message);
 
        MSG_WriteByte (&client->message, svc_serverinfo);
-       MSG_WriteLong (&client->message, DPPROTOCOL_VERSION2);
+       MSG_WriteLong (&client->message, DPPROTOCOL_VERSION3);
        MSG_WriteByte (&client->message, svs.maxclients);
 
        if (!coop.integer && deathmatch.integer)
@@ -333,7 +339,14 @@ void SV_ConnectClient (int clientnum)
                        client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
        }
 
+#if NOROUTINGFIX
        SV_SendServerinfo (client);
+#else
+       // send serverinfo on first nop
+       client->waitingforconnect = true;
+       client->sendsignon = true;
+       client->spawned = false;                // need prespawn, spawn, etc
+#endif
 }
 
 
@@ -406,12 +419,12 @@ crosses a waterline.
 */
 
 int            fatbytes;
-byte   fatpvs[MAX_MAP_LEAFS/8];
+qbyte  fatpvs[MAX_MAP_LEAFS/8];
 
 void SV_AddToFatPVS (vec3_t org, mnode_t *node)
 {
        int             i;
-       byte    *pvs;
+       qbyte   *pvs;
        mplane_t        *plane;
        float   d;
 
@@ -451,7 +464,7 @@ Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
 given point.
 =============
 */
-byte *SV_FatPVS (vec3_t org)
+qbyte *SV_FatPVS (vec3_t org)
 {
        fatbytes = (sv.worldmodel->numleafs+31)>>3;
        memset (fatpvs, 0, fatbytes);
@@ -462,7 +475,7 @@ byte *SV_FatPVS (vec3_t org)
 //=============================================================================
 
 
-int SV_BoxTouchingPVS (byte *pvs, vec3_t mins, vec3_t maxs, mnode_t *node)
+int SV_BoxTouchingPVS (qbyte *pvs, vec3_t mins, vec3_t maxs, mnode_t *node)
 {
        int leafnum;
 loc0:
@@ -507,30 +520,20 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
 {
        int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects;
        int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
-       byte *pvs;
-       vec3_t org, origin, angles, entmins, entmaxs;
-       float nextfullupdate;
+       qbyte *pvs;
+       vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
+       float nextfullupdate, alphaf;
        edict_t *ent;
        eval_t *val;
        entity_state_t *baseline; // LordHavoc: delta or startup baseline
        trace_t trace;
        model_t *model;
-       double testeye[3];
-       double testorigin[3];
 
        Mod_CheckLoaded(sv.worldmodel);
 
 // find the client's PVS
-       VectorAdd (clent->v.origin, clent->v.view_ofs, org);
-       VectorCopy (org, testeye);
-       pvs = SV_FatPVS (org);
-       /*
-       // dp protocol
-       MSG_WriteByte(msg, svc_playerposition);
-       MSG_WriteFloat(msg, org[0]);
-       MSG_WriteFloat(msg, org[1]);
-       MSG_WriteFloat(msg, org[2]);
-       */
+       VectorAdd (clent->v.origin, clent->v.view_ofs, testeye);
+       pvs = SV_FatPVS (testeye);
 
        culled_pvs = 0;
        culled_portal = 0;
@@ -648,7 +651,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        }
 
                        // or not visible through the portals
-                       if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs))
+                       if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
                        {
                                culled_portal++;
                                continue;
@@ -662,22 +665,22 @@ 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]);
 
-                               memset (&trace, 0, sizeof(trace_t));
-                               trace.fraction = 1;
-                               trace.allsolid = true;
-                               VectorCopy(testorigin, trace.endpos);
-
-                               VectorCopy(org, RecursiveHullCheckInfo.start);
-                               VectorSubtract(testorigin, testeye, RecursiveHullCheckInfo.dist);
-                               RecursiveHullCheckInfo.hull = sv.worldmodel->hulls;
-                               RecursiveHullCheckInfo.trace = &trace;
-                               SV_RecursiveHullCheck (sv.worldmodel->hulls->firstclipnode, 0, 1, testeye, testorigin);
+                               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;
                                else
                                {
-                                       if (realtime > client->visibletime[e])
+                                       //test nearest point on bbox
+                                       testorigin[0] = bound(entmins[0], testeye[0], entmaxs[0]);
+                                       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 (trace.fraction == 1)
+                                               client->visibletime[e] = realtime + 1;
+                                       else if (realtime > client->visibletime[e])
                                        {
                                                culled_trace++;
                                                continue;
@@ -687,23 +690,23 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        visibleentities++;
                }
 
-               alpha = 255;
+               alphaf = 255.0f;
                scale = 16;
                glowcolor = 254;
                effects = ent->v.effects;
 
                if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
                if (val->_float != 0)
-                       alpha = (int) (val->_float * 255.0);
+                       alphaf = val->_float * 255.0f;
 
                // HalfLife support
                if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)))
                if (val->_float != 0)
-                       alpha = (int) val->_float;
+                       alphaf = val->_float;
 
-               if (alpha == 0)
-                       alpha = 255;
-               alpha = bound(0, alpha, 255);
+               if (alphaf == 0.0f)
+                       alphaf = 255.0f;
+               alpha = bound(0, alphaf, 255);
 
                if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
                if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
@@ -775,17 +778,14 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        bits |= U_STEP;
 
                // LordHavoc: old stuff, but rewritten to have more exact tolerances
-//             if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0))                                             bits |= U_ORIGIN1;
-//             if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0))                                             bits |= U_ORIGIN2;
-//             if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0))                                             bits |= U_ORIGIN3;
                if (origin[0] != baseline->origin[0])                                                                                   bits |= U_ORIGIN1;
                if (origin[1] != baseline->origin[1])                                                                                   bits |= U_ORIGIN2;
                if (origin[2] != baseline->origin[2])                                                                                   bits |= U_ORIGIN3;
                if (((int)(angles[0]*(256.0/360.0)) & 255) != ((int)(baseline->angles[0]*(256.0/360.0)) & 255)) bits |= U_ANGLE1;
                if (((int)(angles[1]*(256.0/360.0)) & 255) != ((int)(baseline->angles[1]*(256.0/360.0)) & 255)) bits |= U_ANGLE2;
                if (((int)(angles[2]*(256.0/360.0)) & 255) != ((int)(baseline->angles[2]*(256.0/360.0)) & 255)) bits |= U_ANGLE3;
-               if (baseline->colormap != (byte) ent->v.colormap)                                                               bits |= U_COLORMAP;
-               if (baseline->skin != (byte) ent->v.skin)                                                                               bits |= U_SKIN;
+               if (baseline->colormap != (qbyte) ent->v.colormap)                                                              bits |= U_COLORMAP;
+               if (baseline->skin != (qbyte) ent->v.skin)                                                                              bits |= U_SKIN;
                if ((baseline->frame & 0x00FF) != ((int) ent->v.frame & 0x00FF))                                bits |= U_FRAME;
                if ((baseline->effects & 0x00FF) != ((int) ent->v.effects & 0x00FF))                    bits |= U_EFFECTS;
                if ((baseline->modelindex & 0x00FF) != ((int) ent->v.modelindex & 0x00FF))              bits |= U_MODEL;
@@ -865,14 +865,13 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
 {
        int e, clentnum, flags, alpha, glowcolor, glowsize, scale, effects;
        int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
-       byte *pvs;
-       vec3_t org, origin, angles, entmins, entmaxs;
+       float alphaf;
+       qbyte *pvs;
+       vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
        edict_t *ent;
        eval_t *val;
        trace_t trace;
        model_t *model;
-       double testeye[3];
-       double testorigin[3];
        entity_frame_t entityframe;
        entity_state_t *s;
 
@@ -882,10 +881,19 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
        Mod_CheckLoaded(sv.worldmodel);
 
 // find the client's PVS
+       // the real place being tested from
        VectorAdd (clent->v.origin, clent->v.view_ofs, testeye);
-       VectorCopy (testeye, org);
-       pvs = SV_FatPVS (org);
-       EntityFrame_Clear(&entityframe, org);
+       pvs = SV_FatPVS (testeye);
+
+       // the place being reported (to consider the fact the client still
+       // applies the view_ofs[2], so we have to only send the fractional part
+       // of view_ofs[2], undoing what the client will redo)
+       VectorCopy (testeye, testorigin);
+       e = (int) clent->v.view_ofs[2] & 255;
+       if (e >= 128)
+               e -= 256;
+       testorigin[2] -= (float) e;
+       EntityFrame_Clear(&entityframe, testorigin);
 
        culled_pvs = 0;
        culled_portal = 0;
@@ -999,7 +1007,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        }
 
                        // or not visible through the portals
-                       if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs))
+                       if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
                        {
                                culled_portal++;
                                continue;
@@ -1012,16 +1020,7 @@ 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]);
 
-                               memset (&trace, 0, sizeof(trace_t));
-                               trace.fraction = 1;
-                               trace.allsolid = true;
-                               VectorCopy(testorigin, trace.endpos);
-
-                               VectorCopy(org, RecursiveHullCheckInfo.start);
-                               VectorSubtract(testorigin, testeye, RecursiveHullCheckInfo.dist);
-                               RecursiveHullCheckInfo.hull = sv.worldmodel->hulls;
-                               RecursiveHullCheckInfo.trace = &trace;
-                               SV_RecursiveHullCheck (sv.worldmodel->hulls->firstclipnode, 0, 1, testeye, testorigin);
+                               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;
@@ -1037,23 +1036,23 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        visibleentities++;
                }
 
-               alpha = 255;
+               alphaf = 255.0f;
                scale = 16;
                glowcolor = 254;
                effects = ent->v.effects;
 
                if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
                if (val->_float != 0)
-                       alpha = (int) (val->_float * 255.0);
+                       alphaf = val->_float * 255.0;
 
                // HalfLife support
                if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)))
                if (val->_float != 0)
-                       alpha = (int) val->_float;
+                       alphaf = val->_float;
 
-               if (alpha == 0)
-                       alpha = 255;
-               alpha = bound(0, alpha, 255);
+               if (alphaf == 0.0f)
+                       alphaf = 255.0f;
+               alpha = bound(0, alphaf, 255);
 
                if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
                if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
@@ -1088,6 +1087,9 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
 
                if (ent->v.movetype == MOVETYPE_STEP)
                        flags |= RENDER_STEP;
+               // don't send an entity if it's coordinates would wrap around
+               if ((effects & EF_LOWPRECISION) && origin[0] >= -32768 && origin[1] >= -32768 && origin[2] >= -32768 && origin[0] <= 32767 && origin[1] <= 32767 && origin[2] <= 32767)
+                       flags |= RENDER_LOWPRECISION;
 
                s = EntityFrame_NewEntity(&entityframe, e);
                // if we run out of space, abort
@@ -1095,6 +1097,8 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        break;
                VectorCopy(origin, s->origin);
                VectorCopy(angles, s->angles);
+               if (ent->v.colormap >= 1024)
+                       flags |= RENDER_COLORMAPPED;
                s->colormap = ent->v.colormap;
                s->skin = ent->v.skin;
                s->frame = ent->v.frame;
@@ -1144,6 +1148,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        int             items;
        eval_t  *val;
        vec3_t  punchvector;
+       qbyte   viewzoom;
 
 //
 // send a damage message
@@ -1177,7 +1182,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
 
        bits = 0;
 
-       //if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
+       if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
                bits |= SU_VIEWHEIGHT;
 
        if (ent->v.idealpitch)
@@ -1205,6 +1210,20 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
                VectorCopy(val->vector, punchvector);
 
+       i = 255;
+       if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
+       {
+               i = val->_float * 255.0f;
+               if (i == 0)
+                       i = 255;
+               else
+                       i = bound(0, i, 255);
+       }
+       viewzoom = i;
+
+       if (viewzoom != 255)
+               bits |= SU_VIEWZOOM;
+
        for (i=0 ; i<3 ; i++)
        {
                if (ent->v.punchangle[i])
@@ -1221,8 +1240,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        if (ent->v.armorvalue)
                bits |= SU_ARMOR;
 
-//     if (ent->v.weapon)
-               bits |= SU_WEAPON;
+       bits |= SU_WEAPON;
 
        if (bits >= 65536)
                bits |= SU_EXTEND1;
@@ -1239,8 +1257,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                MSG_WriteByte(msg, bits >> 24);
 
        if (bits & SU_VIEWHEIGHT)
-               //MSG_WriteChar (msg, ent->v.view_ofs[2]);
-               MSG_WriteChar (msg, 0);
+               MSG_WriteChar (msg, ent->v.view_ofs[2]);
 
        if (bits & SU_IDEALPITCH)
                MSG_WriteChar (msg, ent->v.idealpitch);
@@ -1287,6 +1304,9 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        {
                MSG_WriteByte (msg, ent->v.weapon);
        }
+
+       if (bits & SU_VIEWZOOM)
+               MSG_WriteByte (msg, viewzoom);
 }
 
 /*
@@ -1296,7 +1316,7 @@ SV_SendClientDatagram
 */
 qboolean SV_SendClientDatagram (client_t *client)
 {
-       byte            buf[MAX_DATAGRAM];
+       qbyte           buf[MAX_DATAGRAM];
        sizebuf_t       msg;
 
        msg.data = buf;
@@ -1306,14 +1326,17 @@ qboolean SV_SendClientDatagram (client_t *client)
        MSG_WriteByte (&msg, svc_time);
        MSG_WriteFloat (&msg, sv.time);
 
-// add the client specific data to the datagram
-       SV_WriteClientdataToMessage (client->edict, &msg);
+       if (client->spawned)
+       {
+               // add the client specific data to the datagram
+               SV_WriteClientdataToMessage (client->edict, &msg);
 
-       SV_WriteEntitiesToClient (client, client->edict, &msg);
+               SV_WriteEntitiesToClient (client, client->edict, &msg);
 
-// copy the server datagram if there is space
-       if (msg.cursize + sv.datagram.cursize < msg.maxsize)
-               SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
+               // copy the server datagram if there is space
+               if (msg.cursize + sv.datagram.cursize < msg.maxsize)
+                       SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
+       }
 
 // send the datagram
        if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
@@ -1342,7 +1365,7 @@ void SV_UpdateToReliableMessages (void)
                {
                        for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
                        {
-                               if (!client->active)
+                               if (!client->active || !client->spawned)
                                        continue;
                                MSG_WriteByte (&client->message, svc_updatefrags);
                                MSG_WriteByte (&client->message, i);
@@ -1375,7 +1398,7 @@ message buffer
 void SV_SendNop (client_t *client)
 {
        sizebuf_t       msg;
-       byte            buf[4];
+       qbyte           buf[4];
 
        msg.data = buf;
        msg.maxsize = sizeof(buf);
@@ -1406,6 +1429,14 @@ void SV_SendClientMessages (void)
                if (!host_client->active)
                        continue;
 
+#ifndef NOROUTINGFIX
+               if (host_client->sendserverinfo)
+               {
+                       host_client->sendserverinfo = false;
+                       SV_SendServerinfo (host_client);
+               }
+#endif
+
                if (host_client->spawned)
                {
                        if (!SV_SendClientDatagram (host_client))
@@ -1439,10 +1470,7 @@ void SV_SendClientMessages (void)
                if (host_client->message.cursize || host_client->dropasap)
                {
                        if (!NET_CanSendMessage (host_client->netconnection))
-                       {
-//                             I_Printf ("can't write\n");
                                continue;
-                       }
 
                        if (host_client->dropasap)
                                SV_DropClient (false);  // went to another level
@@ -1531,7 +1559,7 @@ void SV_CreateBaseline (void)
                else
                {
                        svent->baseline.colormap = 0;
-                       svent->baseline.modelindex = svent->v.modelindex; //SV_ModelIndex(pr_strings + svent->v.model);
+                       svent->baseline.modelindex = svent->v.modelindex;
                }
 
                large = false;
@@ -1748,7 +1776,7 @@ void SV_SpawnServer (char *server)
 
 // serverflags are for cross level information (sigils)
        pr_global_struct->serverflags = svs.serverflags;
-       
+
        ED_LoadFromFile (sv.worldmodel->entities);
        // LordHavoc: clear world angles (to fix e3m3.bsp)
        VectorClear(sv.edicts->v.angles);
@@ -1761,6 +1789,7 @@ void SV_SpawnServer (char *server)
 // 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 ();
 
        Mod_PurgeUnused();
@@ -1777,3 +1806,4 @@ void SV_SpawnServer (char *server)
 
        Con_DPrintf ("Server spawned.\n");
 }
+