diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 16940f28b..f01167b71 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -926,6 +926,7 @@ typedef struct model_s int numtextures; texture_t **textures; + qbyte *pvs, *phs; // fully expanded and decompressed qbyte *visdata; void *vis; qbyte *lightdata; diff --git a/engine/server/server.h b/engine/server/server.h index 830751445..67db8445a 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -157,7 +157,6 @@ typedef struct int spawned_observer_slots; model_t *models[MAX_PRECACHE_MODELS]; - qbyte *pvs, *phs; // fully expanded and decompressed struct client_s *skipbprintclient; //SV_BroadcastPrint skips this client diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 9476eb25e..4b76d03a4 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -2598,6 +2598,42 @@ void SV_PrecacheList_f(void) } } +void SV_MemInfo_f(void) +{ + int sz, i, fr, csfr; + laggedpacket_t *lp; + client_t *cl; + Cmd_ExecuteString("mod_memlist;hunkprint", Cmd_ExecLevel); + for (i = 0; i < svs.allocated_client_slots; i++) + { + cl = &svs.clients[i]; + if (cl->state) + { + Con_Printf("%s\n", cl->name); + sz = 0; + for (lp = cl->laggedpacket; lp; lp = lp->next) + sz += lp->length; + + fr = 0; + if (cl->pendingentbits) + { + int maxents = cl->frameunion.frames[0].entities.max_entities; /*this is the max number of ents updated per frame. we can't track more, so...*/ + fr = sizeof(cl)*UPDATE_BACKUP+ + sizeof(*cl->pendingentbits)*cl->max_net_ents+ + sizeof(unsigned int)*maxents*UPDATE_BACKUP+ + sizeof(unsigned int)*maxents*UPDATE_BACKUP; + } + else + fr = (sizeof(client_frame_t)+sizeof(entity_state_t)*cl->frameunion.frames[0].entities.max_entities)*UPDATE_BACKUP; + fr += sizeof(*cl->sentents.entities) * cl->sentents.max_entities; + + csfr = sizeof(*cl->csqcentversions) * cl->max_net_ents; + + Con_Printf("%i minping=%i frame=%i, csqc=%i\n", sizeof(svs.clients[i]), sz, fr, csfr); + } + } +} + /* ================== SV_InitOperatorCommands @@ -2683,6 +2719,8 @@ void SV_InitOperatorCommands (void) Cmd_AddCommand ("pin_delete", SV_Pin_Delete_f); Cmd_AddCommand ("pin_add", SV_Pin_Add_f); + Cmd_AddCommand("sv_meminfo", SV_MemInfo_f); + // Cmd_AddCommand ("reallyevilhack", SV_ReallyEvilHack_f); if (isDedicated) diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index fdbea791d..121e5b905 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -3364,7 +3364,8 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t { int cluster; unsigned char *mask; - if (sv.phs) + qbyte *phs = sv.world.worldmodel->phs; + if (phs) { //FIXME: this lookup should be cachable or something. if (client->edict) @@ -3373,7 +3374,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t cluster = -1; //mvd if (cluster >= 0) { - mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + mask = phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); cluster = sv.world.worldmodel->funcs.ClusterForPoint (sv.world.worldmodel, ent->v->origin); if (cluster >= 0 && !(mask[cluster>>3] & (1<<(cluster&7)) ) ) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index addfc2006..3d53ad53f 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -435,39 +435,41 @@ void SV_CalcPHS (void) unsigned *dest, *src; qbyte *scan, *lf; int count, vcount; + model_t *model = sv.world.worldmodel; - if (sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) + if (model->pvs || model->fromgame == fg_quake2 || model->fromgame == fg_quake3) { //PHS calcs are pointless with Q2 bsps return; } - num = sv.world.worldmodel->numclusters; + //FIXME: this can take a significant time on some maps, and should ideally be pushed to a worker thread. + num = model->numclusters; rowwords = (num+31)>>5; rowbytes = rowwords*4; if (!sv_calcphs.ival || (sv_calcphs.ival == 2 && (rowbytes*num >= 0x100000 || (!deathmatch.ival && !coop.ival)))) { - sv.pvs = ZG_Malloc(&sv.world.worldmodel->memgroup, rowbytes*num); - scan = sv.pvs; + model->pvs = ZG_Malloc(&model->memgroup, rowbytes*num); + scan = model->pvs; for (i=0 ; ifuncs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes); + lf = model->funcs.ClusterPVS(model, i, scan, rowbytes); if (lf != scan) memcpy (scan, lf, rowbytes); } Con_DPrintf("Skipping PHS\n"); - sv.phs = NULL; + model->phs = NULL; return; } - sv.pvs = ZG_Malloc(&sv.world.worldmodel->memgroup, rowbytes*num); - scan = sv.pvs; + model->pvs = ZG_Malloc(&model->memgroup, rowbytes*num); + scan = model->pvs; vcount = 0; for (i=0 ; ifuncs.ClusterPVS(sv.world.worldmodel, i, scan, rowbytes); + lf = model->funcs.ClusterPVS(model, i, scan, rowbytes); if (lf != scan) memcpy (scan, lf, rowbytes); if (i == 0) @@ -483,7 +485,7 @@ void SV_CalcPHS (void) if (developer.value) Con_TPrintf ("Building PHS...\n"); - sv.phs = ZG_Malloc (&sv.world.worldmodel->memgroup, rowbytes*num); + model->phs = ZG_Malloc (&model->memgroup, rowbytes*num); /*this routine takes an exponential amount of time, so cache it if its too big*/ if (rowbytes*num >= 0x100000) @@ -495,7 +497,7 @@ void SV_CalcPHS (void) VFS_READ(f, hdr, sizeof(hdr)); if (memcmp(hdr, "QPHS\1\0\0\0", 8) || VFS_GETLEN(f) != rowbytes*num + 8) { - VFS_READ(f, sv.phs, rowbytes*num); + VFS_READ(f, model->phs, rowbytes*num); VFS_CLOSE(f); Con_DPrintf("Loaded cached PHS\n"); return; @@ -507,8 +509,8 @@ void SV_CalcPHS (void) } count = 0; - scan = sv.pvs; - dest = (unsigned *)sv.phs; + scan = model->pvs; + dest = (unsigned *)model->phs; for (i=0 ; i= num) continue; - src = (unsigned *)sv.pvs + index*rowwords; + src = (unsigned *)model->pvs + index*rowwords; for (l=0 ; lphs, rowbytes*num); VFS_CLOSE(f); Con_Printf("Written PHS cache (%u bytes)\n", rowbytes*num); } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 53389901e..eed7c2cab 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1828,7 +1828,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client) if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp)) { char *ptr; - int maxents = client->max_net_ents;//maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/ + int maxents = /*client->max_net_ents;//*/maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/ ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+ sizeof(*client->pendingentbits)*client->max_net_ents+ sizeof(unsigned int)*maxents*UPDATE_BACKUP+ @@ -3862,7 +3862,7 @@ if necessary void SV_CheckTimeouts (void) { int i; - client_t *cl; + client_t *cl, *cont; float droptime; int nclients; @@ -3875,7 +3875,10 @@ void SV_CheckTimeouts (void) { if (!cl->spectator) nclients++; - if (cl->netchan.last_received < droptime && cl->netchan.remote_address.type != NA_LOOPBACK && cl->protocol != SCP_BAD) + cont = cl; + if (cont->controller) + cont = cont->controller; + if (cont->netchan.last_received < droptime && cl->netchan.remote_address.type != NA_LOOPBACK && cl->protocol != SCP_BAD) { SV_BroadcastTPrintf (PRINT_HIGH, "Client %s timed out\n", cl->name); SV_DropClient (cl); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 9f48eccae..450292d5a 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -776,13 +776,13 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: - if (!sv.phs) /*broadcast if no pvs*/ + if (!sv.world.worldmodel->phs) /*broadcast if no pvs*/ mask = NULL; else { cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin); if (cluster >= 0) - mask = sv.phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + mask = sv.world.worldmodel->phs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); else mask = NULL; } @@ -793,7 +793,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int case MULTICAST_PVS: cluster = sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, origin); if (cluster >= 0) - mask = sv.pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); + mask = sv.world.worldmodel->pvs + cluster * 4*((sv.world.worldmodel->numclusters+31)>>5); else mask = NULL; break;