diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index fa1ba406b..0c07cbf6f 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void SV_CleanupEnts(void); extern cvar_t sv_nailhack; +extern cvar_t sv_cullentities_trace; +extern cvar_t sv_cullplayers_trace; /* ============================================================================= @@ -1383,6 +1385,39 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) } #endif + +qboolean Cull_Traceline(edict_t *viewer, edict_t *seen) +{ + int i; + trace_t tr; + vec3_t start; + vec3_t end; + + if (seen->v->solid == SOLID_BSP) + return false; //bsp ents are never culled this way + + //stage 1: check against their origin + VectorAdd(viewer->v->origin, viewer->v->view_ofs, start); + tr.fraction = 1; + if (!sv.worldmodel->funcs.Trace (sv.worldmodel, 1, 0, start, seen->v->origin, vec3_origin, vec3_origin, &tr)) + return false; //wasn't blocked + + //stage 2: check against their bbox + for (i = 0; i < 8; i++) + { + end[0] = seen->v->origin[0] + ((i&1)?seen->v->mins[0]:seen->v->maxs[0]); + end[1] = seen->v->origin[1] + ((i&2)?seen->v->mins[1]:seen->v->maxs[1]); + end[2] = seen->v->origin[2] + ((i&4)?seen->v->mins[2]+0.1:seen->v->maxs[2]); + + tr.fraction = 1; + if (!sv.worldmodel->funcs.Trace (sv.worldmodel, 1, 0, start, end, vec3_origin, vec3_origin, &tr)) + return false; //this trace went through, so don't cull + } + + return true; +} + + /* ============= SV_WritePlayersToClient @@ -1669,6 +1704,9 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size if (!((int)clent->v->dimension_see & ((int)ent->v->dimension_seen | (int)ent->v->dimension_ghost))) continue; //not in this dimension - sorry... + if (sv_cullplayers_trace.value || sv_cullentities_trace.value) + if (Cull_Traceline(clent, ent)) + continue; } if (SV_AddCSQCUpdate(client, ent)) @@ -2405,6 +2443,14 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (!((int)client->edict->v->dimension_see & ((int)ent->v->dimension_seen | (int)ent->v->dimension_ghost))) continue; //not in this dimension - sorry... + + if (!ignorepvs && ent != clent) + { //more expensive culling + if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value) + if (Cull_Traceline(clent, ent)) + continue; + } + if (SV_AddCSQCUpdate(client, ent)) //csqc took it. continue; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 5c0ea9615..3f67969ac 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -125,6 +125,8 @@ cvar_t sv_maxdrate = SCVAR("sv_maxdrate", "10000"); cvar_t sv_bigcoords = SCVARF("sv_bigcoords", "", CVAR_SERVERINFO); +cvar_t sv_cullplayers_trace = SCVARF("sv_cullplayers_trace", "", CVAR_SERVERINFO); +cvar_t sv_cullentities_trace = SCVARF("sv_cullentities_trace", "", CVAR_SERVERINFO); cvar_t sv_phs = SCVAR("sv_phs", "1"); cvar_t sv_resetparms = SCVAR("sv_resetparms", "0"); @@ -3160,6 +3162,8 @@ void SV_InitLocal (void) Cvar_Register (&sv_highchars, cvargroup_servercontrol); Cvar_Register (&sv_phs, cvargroup_servercontrol); + Cvar_Register (&sv_cullplayers_trace, cvargroup_servercontrol); + Cvar_Register (&sv_cullentities_trace, cvargroup_servercontrol); Cvar_Register (&sv_csqcdebug, cvargroup_servercontrol);