From: havoc Date: Sat, 26 Apr 2003 10:21:02 +0000 (+0000) Subject: reverted dynamic allocation of sv.edicts because there are FAR too many broken pointe... X-Git-Tag: xonotic-v0.1.0preview~6646 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=97d61bec83f6475e58128ac915c50d013b8fec48;p=xonotic%2Fdarkplaces.git reverted dynamic allocation of sv.edicts because there are FAR too many broken pointer cases, however shrinking the edict_t to just a couple pointers and dynamically allocating the data they point to, keeps memory usage way down git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2989 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_main.c b/cl_main.c index ce00b637..03e34070 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1572,7 +1572,7 @@ static void CL_PModel_f (void) } host_client->pmodel = i; - if ((val = GETEDICTFIELDVALUE(EDICT_NUM(host_client->edictnumber), eval_pmodel))) + if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel))) val->_float = i; } diff --git a/host.c b/host.c index d11b8f66..c5c783b5 100644 --- a/host.c +++ b/host.c @@ -455,12 +455,12 @@ void SV_DropClient (qboolean crash) // note: don't clear name yet net_activeconnections--; - if (sv.active && host_client->edictnumber && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts) + if (sv.active && host_client->edict && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts) { // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = pr_global_struct->self; - pr_global_struct->self = EDICT_TO_PROG(EDICT_NUM(host_client->edictnumber)); + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing"); pr_global_struct->self = saveSelf; } diff --git a/host_cmd.c b/host_cmd.c index 1aca802b..f2737124 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -89,7 +89,7 @@ void Host_Status_f (void) } else hours = 0; - print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)EDICT_NUM(client->edictnumber)->v->frags, hours, minutes, seconds); + print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->v->frags, hours, minutes, seconds); print (" %s\n", client->netconnection->address); } } @@ -418,7 +418,7 @@ void Host_Savegame_f (void) for (i=0 ; iv->health <= 0) ) + if (svs.clients[i].active && (svs.clients[i].edict->v->health <= 0) ) { Con_Printf ("Can't savegame with a dead player\n"); return; @@ -602,11 +602,11 @@ void Host_PerformLoadGame(char *name) // parse an edict ent = EDICT_NUM(entnum); memset (ent->v, 0, progs->entityfields * 4); - ent->free = false; + ent->e->free = false; ED_ParseEdict (start, ent); // link it into the bsp tree - if (!ent->free) + if (!ent->e->free) SV_LinkEdict (ent, false); } @@ -665,7 +665,7 @@ void Host_Name_f (void) if (strcmp(host_client->name, newName) != 0) Con_Printf ("%s renamed to %s\n", host_client->name, newName); strcpy (host_client->name, newName); - EDICT_NUM(host_client->edictnumber)->v->netname = PR_SetString(host_client->name); + sv_player->v->netname = PR_SetString(host_client->name); // send notification to all clients @@ -740,7 +740,7 @@ void Host_Say(qboolean teamonly) { if (!client || !client->active || !client->spawned) continue; - if (teamplay.integer && teamonly && EDICT_NUM(client->edictnumber)->v->team != EDICT_NUM(save->edictnumber)->v->team) + if (teamplay.integer && teamonly && client->edict->v->team != save->edict->v->team) continue; host_client = client; SV_ClientPrintf("%s", text); @@ -883,13 +883,13 @@ void Host_Color_f(void) Con_DPrintf("Calling SV_ChangeTeam\n"); pr_global_struct->time = sv.time; pr_globals[OFS_PARM0] = playercolor; - pr_global_struct->self = EDICT_TO_PROG(EDICT_NUM(host_client->edictnumber)); + pr_global_struct->self = EDICT_TO_PROG(sv_player); PR_ExecuteProgram (SV_ChangeTeam, ""); } else { host_client->colors = playercolor; - EDICT_NUM(host_client->edictnumber)->v->team = bottom + 1; + sv_player->v->team = bottom + 1; // send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); @@ -918,7 +918,7 @@ void Host_Kill_f (void) } pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(sv_player); + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram (pr_global_struct->ClientKill, "QC function ClientKill is missing"); } @@ -1014,6 +1014,8 @@ void Host_Spawn_f (void) // send all current names, colors, and frag counts SZ_Clear (&host_client->message); + ent = sv_player; + // run the entrance script if (sv.loadgame) { @@ -1034,9 +1036,7 @@ void Host_Spawn_f (void) { eval_t *val; // set up the edict - ent = EDICT_NUM(host_client->edictnumber); - - memset (ent->v, 0, progs->entityfields * 4); + ED_ClearEdict(ent); ent->v->colormap = NUM_FOR_EDICT(ent); ent->v->team = (host_client->colors & 15) + 1; ent->v->netname = PR_SetString(host_client->name); @@ -1110,7 +1110,6 @@ void Host_Spawn_f (void) // in a state where it is expecting the client to correct the angle // and it won't happen if the game was just loaded, so you wind up // with a permanent head tilt - ent = EDICT_NUM( 1 + (host_client - svs.clients) ); MSG_WriteByte (&host_client->message, svc_setangle); for (i=0 ; i < 2 ; i++) MSG_WriteAngle (&host_client->message, ent->v->angles[i] ); diff --git a/net_dgrm.c b/net_dgrm.c index b271f9d7..b3f7fae2 100644 --- a/net_dgrm.c +++ b/net_dgrm.c @@ -916,7 +916,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void) MSG_WriteByte(&net_message, playerNumber); MSG_WriteString(&net_message, client->name); MSG_WriteLong(&net_message, client->colors); - MSG_WriteLong(&net_message, (int)EDICT_NUM(client->edictnumber)->v->frags); + MSG_WriteLong(&net_message, (int)client->edict->v->frags); MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); MSG_WriteString(&net_message, client->netconnection->address); *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); diff --git a/pr_cmds.c b/pr_cmds.c index 0da857a8..e33360bb 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -851,7 +851,7 @@ int PF_newcheckclient (int check) if (i == check) break; // didn't find anything else - if (ent->free) + if (ent->e->free) continue; if (ent->v->health <= 0) continue; @@ -903,7 +903,7 @@ void PF_checkclient (void) // return check if it might be visible ent = EDICT_NUM(sv.lastcheck); - if (ent->free || ent->v->health <= 0) + if (ent->e->free || ent->v->health <= 0) { RETURN_EDICT(sv.edicts); return; @@ -1036,7 +1036,7 @@ void PF_findradius (void) for (i=1 ; ibuiltinsprofile++; - if (ent->free) + if (ent->e->free) continue; if (ent->v->solid == SOLID_NOT) continue; @@ -1159,7 +1159,7 @@ void PF_Find (void) { pr_xfunction->builtinsprofile++; ed = EDICT_NUM(e); - if (ed->free) + if (ed->e->free) continue; t = E_STRING(ed,f); if (!t) @@ -1190,7 +1190,7 @@ void PF_FindFloat (void) { pr_xfunction->builtinsprofile++; ed = EDICT_NUM(e); - if (ed->free) + if (ed->e->free) continue; if (E_FLOAT(ed,f) == s) { @@ -1225,7 +1225,7 @@ void PF_findchain (void) for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) { pr_xfunction->builtinsprofile++; - if (ent->free) + if (ent->e->free) continue; t = E_STRING(ent,f); if (!t) @@ -1258,7 +1258,7 @@ void PF_findchainfloat (void) for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) { pr_xfunction->builtinsprofile++; - if (ent->free) + if (ent->e->free) continue; if (E_FLOAT(ent,f) != s) continue; @@ -1428,7 +1428,7 @@ void PF_droptofloor (void) ent->v->groundentity = EDICT_TO_PROG(trace.ent); G_FLOAT(OFS_RETURN) = 1; // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->suspendedinairflag = true; + ent->e->suspendedinairflag = true; } } @@ -1527,7 +1527,7 @@ void PF_nextent (void) return; } ent = EDICT_NUM(i); - if (!ent->free) + if (!ent->e->free) { RETURN_EDICT(ent); return; @@ -2103,7 +2103,7 @@ void PF_setcolor (void) client = &svs.clients[entnum-1]; client->colors = i; - EDICT_NUM(client->edictnumber)->v->team = (i & 15) + 1; + client->edict->v->team = (i & 15) + 1; MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); MSG_WriteByte (&sv.reliable_datagram, entnum - 1); @@ -2547,7 +2547,7 @@ static msurface_t *getsurface(edict_t *ed, int surfnum) { int modelindex; model_t *model; - if (!ed || ed->free) + if (!ed || ed->e->free) return NULL; modelindex = ed->v->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) @@ -2582,7 +2582,7 @@ void PF_getsurfacepoint(void) int pointnum; VectorClear(G_VECTOR(OFS_RETURN)); ed = G_EDICT(OFS_PARM0); - if (!ed || ed->free) + if (!ed || ed->e->free) return; if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) return; @@ -2628,7 +2628,7 @@ void PF_getsurfacenearpoint(void) ed = G_EDICT(OFS_PARM0); point = G_VECTOR(OFS_PARM1); - if (!ed || ed->free) + if (!ed || ed->e->free) return; modelindex = ed->v->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) @@ -2668,7 +2668,7 @@ void PF_getsurfaceclippedpoint(void) vec3_t p, out; VectorClear(G_VECTOR(OFS_RETURN)); ed = G_EDICT(OFS_PARM0); - if (!ed || ed->free) + if (!ed || ed->e->free) return; if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) return; diff --git a/pr_edict.c b/pr_edict.c index d7875c5d..ec7ffb83 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -185,7 +185,7 @@ Sets everything to NULL void ED_ClearEdict (edict_t *e) { memset (e->v, 0, progs->entityfields * 4); - e->free = false; + e->e->free = false; } /* @@ -210,7 +210,7 @@ edict_t *ED_Alloc (void) e = EDICT_NUM(i); // the first couple seconds of server time can involve a lot of // freeing and allocating, so relax the replacement policy - if (e->free && ( e->freetime < 2 || sv.time - e->freetime > 0.5 ) ) + if (e->e->free && ( e->e->freetime < 2 || sv.time - e->e->freetime > 0.5 ) ) { ED_ClearEdict (e); return e; @@ -241,7 +241,7 @@ void ED_Free (edict_t *ed) { SV_UnlinkEdict (ed); // unlink from world bsp - ed->free = true; + ed->e->free = true; ed->v->model = 0; ed->v->takedamage = 0; ed->v->modelindex = 0; @@ -253,7 +253,7 @@ void ED_Free (edict_t *ed) ed->v->nextthink = -1; ed->v->solid = 0; - ed->freetime = sv.time; + ed->e->freetime = sv.time; } //=========================================================================== @@ -561,7 +561,7 @@ void ED_Print (edict_t *ed) int type; char tempstring[8192], tempstring2[260]; // temporary string buffers - if (ed->free) + if (ed->e->free) { Con_Printf ("FREE\n"); return; @@ -636,7 +636,7 @@ void ED_Write (qfile_t *f, edict_t *ed) FS_Printf (f, "{\n"); - if (ed->free) + if (ed->e->free) { FS_Printf (f, "}\n"); return; @@ -724,7 +724,7 @@ void ED_Count (void) for (i=0 ; ifree) + if (ent->e->free) continue; active++; if (ent->v->solid) @@ -1021,7 +1021,7 @@ const char *ED_ParseEdict (const char *data, edict_t *ent) } if (!init) - ent->free = true; + ent->e->free = true; return data; } @@ -1118,7 +1118,7 @@ void ED_LoadFromFile (const char *data) pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (func - pr_functions, ""); spawned++; - if (ent->free) + if (ent->e->free) died++; } @@ -1413,7 +1413,7 @@ void PR_Fields_f (void) for (ednum = 0;ednum < MAX_EDICTS;ednum++) { ed = EDICT_NUM(ednum); - if (ed->free) + if (ed->e->free) continue; for (i = 1;i < progs->numfielddefs;i++) { @@ -1596,7 +1596,7 @@ int NUM_FOR_EDICT(edict_t *e) //} //#define EDICT_TO_PROG(e) ((qbyte *)(((edict_t *)e)->v) - (qbyte *)(sv.edictsfields)) -//#define PROG_TO_EDICT(e) (sv.edictstable[(e) / (progs->entityfields * 4)]) +//#define PROG_TO_EDICT(e) (sv.edicts + ((e) / (progs->entityfields * 4))) int EDICT_TO_PROG(edict_t *e) { int n; @@ -1610,8 +1610,8 @@ edict_t *PROG_TO_EDICT(int n) { if ((unsigned int)n >= (unsigned int)sv.max_edicts) Host_Error("PROG_TO_EDICT: invalid edict number %i\n", n); - return sv.edictstable[n]; // EXPERIMENTAL - //return sv.edictstable[(n) / (progs->entityfields * 4)]; + return sv.edicts + n; // EXPERIMENTAL + //return sv.edicts + ((n) / (progs->entityfields * 4)); } */ diff --git a/progs.h b/progs.h index 929bd27c..415a11d6 100644 --- a/progs.h +++ b/progs.h @@ -43,11 +43,14 @@ typedef struct link_s #define ENTITYGRIDAREAS 16 -// the entire server entity structure -typedef struct edict_s +typedef struct edict_engineprivate_s { // true if this edict is unused qboolean free; + // sv.time when the object was freed (to prevent early reuse which could + // mess up client interpolation or obscure severe QuakeC bugs) + float freetime; + // physics grid areas this edict is linked into link_t areagrid[ENTITYGRIDAREAS]; // since the areagrid can have multiple references to one entity, @@ -64,16 +67,23 @@ typedef struct edict_s // LordHavoc: gross hack to make floating items still work int suspendedinairflag; - // sv.time when the object was freed (to prevent early reuse which could - // mess up client interpolation or obscure severe QuakeC bugs) - float freetime; // used by PushMove to keep track of where objects were before they were // moved, in case they need to be moved back vec3_t moved_from; vec3_t moved_fromangles; - // edict fields (stored in another array) +} +edict_engineprivate_t; + +// the entire server entity structure +// NOTE: keep this small! priv and v are dynamic but this struct is not! +typedef struct edict_s +{ + // engine-private fields (stored in dynamically resized array) + edict_engineprivate_t *e; + // QuakeC fields (stored in dynamically resized array) entvars_t *v; -} edict_t; +} +edict_t; // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... see pr_edict.c for the functions which use these. extern int eval_gravity; @@ -144,6 +154,7 @@ void PR_Crash (void); edict_t *ED_Alloc (void); void ED_Free (edict_t *ed); +void ED_ClearEdict (edict_t *e); char *ED_NewString (const char *string); // returns a copy of the string allocated from the server's string heap @@ -158,7 +169,7 @@ void ED_ParseGlobals (const char *data); void ED_LoadFromFile (const char *data); edict_t *EDICT_NUM_ERROR(int n, char *filename, int fileline); -#define EDICT_NUM(n) (((n) >= 0 && (n) < sv.max_edicts) ? sv.edictstable[(n)] : EDICT_NUM_ERROR(n, __FILE__, __LINE__)) +#define EDICT_NUM(n) (((n) >= 0 && (n) < sv.max_edicts) ? sv.edicts + (n) : EDICT_NUM_ERROR(n, __FILE__, __LINE__)) //int NUM_FOR_EDICT_ERROR(edict_t *e); #define NUM_FOR_EDICT(e) ((edict_t *)(e) - sv.edicts) diff --git a/server.h b/server.h index 47e917c2..a54fbf00 100644 --- a/server.h +++ b/server.h @@ -67,13 +67,17 @@ typedef struct char *lightstyles[MAX_LIGHTSTYLES]; int num_edicts; int max_edicts; - // can NOT be array indexed, because edict_t is variable sized, but can be used to reference the world ent + // small edict_t structures which just contain pointers + // (allocated at server startup only) edict_t *edicts; - // can be array indexed - edict_t **edictstable; - // array of QC edict field variables + // engine private edict information + // (dynamically resized - always access through edict_t!) + edict_engineprivate_t *edictsengineprivate; + // QuakeC fields array + // (dynamically resized - always access through edict_t!) void *edictsfields; // PushMove sometimes has to move entities back from a failed move + // (dynamically resized) edict_t **moved_edicts; // some actions are only valid during load server_state_t state; @@ -127,8 +131,8 @@ typedef struct client_s // can be added to at any time, copied and clear once per frame sizebuf_t message; qbyte msgbuf[MAX_DATAGRAM]; - // (clientnum+1) - int edictnumber; + // EDICT_NUM(clientnum+1) + edict_t *edict; // for printing to other people char name[32]; int colors; diff --git a/sv_main.c b/sv_main.c index d6edc1a8..73827de4 100644 --- a/sv_main.c +++ b/sv_main.c @@ -287,7 +287,7 @@ void SV_SendServerinfo (client_t *client) // set view MSG_WriteByte (&client->message, svc_setview); - MSG_WriteShort (&client->message, client->edictnumber); + MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict)); MSG_WriteByte (&client->message, svc_signonnum); MSG_WriteByte (&client->message, 1); @@ -306,9 +306,7 @@ once for a player each game, not once for each level change. */ void SV_ConnectClient (int clientnum) { - edict_t *ent; client_t *client; - int edictnum; struct qsocket_s *netconnection; int i; float spawn_parms[NUM_SPAWN_PARMS]; @@ -317,10 +315,6 @@ void SV_ConnectClient (int clientnum) Con_DPrintf ("Client %s connected\n", client->netconnection->address); - edictnum = clientnum+1; - - ent = EDICT_NUM(edictnum); - // set up the client_t netconnection = client->netconnection; @@ -332,7 +326,7 @@ void SV_ConnectClient (int clientnum) strcpy (client->name, "unconnected"); client->active = true; client->spawned = false; - client->edictnumber = edictnum; + client->edict = EDICT_NUM(clientnum+1); client->message.data = client->msgbuf; client->message.maxsize = sizeof(client->msgbuf); client->message.allowoverflow = true; // we can catch it @@ -761,7 +755,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) bits = bits | U_EXTERIORMODEL; // send an update - baseline = &ent->baseline; + baseline = &ent->e->baseline; if (((int)ent->v->effects & EF_DELTA) && sv_deltacompress.integer) { @@ -769,7 +763,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (realtime < client->nextfullupdate[e]) { bits |= U_DELTA; - baseline = &ent->deltabaseline; + baseline = &ent->e->deltabaseline; } else nextfullupdate = realtime + 0.5f; @@ -809,17 +803,17 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (((int) baseline->frame & 0xFF00) != ((int) ent->v->modelindex & 0xFF00)) bits |= U_MODEL2; // update delta baseline - VectorCopy(ent->v->origin, ent->deltabaseline.origin); - VectorCopy(ent->v->angles, ent->deltabaseline.angles); - ent->deltabaseline.colormap = ent->v->colormap; - ent->deltabaseline.skin = ent->v->skin; - ent->deltabaseline.frame = ent->v->frame; - ent->deltabaseline.effects = ent->v->effects; - ent->deltabaseline.modelindex = ent->v->modelindex; - ent->deltabaseline.alpha = alpha; - ent->deltabaseline.scale = scale; - ent->deltabaseline.glowsize = glowsize; - ent->deltabaseline.glowcolor = glowcolor; + VectorCopy(ent->v->origin, ent->e->deltabaseline.origin); + VectorCopy(ent->v->angles, ent->e->deltabaseline.angles); + ent->e->deltabaseline.colormap = ent->v->colormap; + ent->e->deltabaseline.skin = ent->v->skin; + ent->e->deltabaseline.frame = ent->v->frame; + ent->e->deltabaseline.effects = ent->v->effects; + ent->e->deltabaseline.modelindex = ent->v->modelindex; + ent->e->deltabaseline.alpha = alpha; + ent->e->deltabaseline.scale = scale; + ent->e->deltabaseline.glowsize = glowsize; + ent->e->deltabaseline.glowcolor = glowcolor; // write the message if (bits >= 16777216) @@ -915,7 +909,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) ent = NEXT_EDICT(sv.edicts); for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent)) { - if (ent->free) + if (ent->e->free) continue; flags = 0; @@ -1403,9 +1397,9 @@ qboolean SV_SendClientDatagram (client_t *client) if (client->spawned) { // add the client specific data to the datagram - SV_WriteClientdataToMessage (EDICT_NUM(client->edictnumber), &msg); + SV_WriteClientdataToMessage (client->edict, &msg); - SV_WriteEntitiesToClient (client, EDICT_NUM(client->edictnumber), &msg); + SV_WriteEntitiesToClient (client, client->edict, &msg); // copy the server datagram if there is space if (msg.cursize + sv.datagram.cursize < msg.maxsize) @@ -1429,13 +1423,14 @@ SV_UpdateToReliableMessages */ void SV_UpdateToReliableMessages (void) { - int i, j; + int i, j; client_t *client; // check for changes to be sent over the reliable streams for (i=0, host_client = svs.clients ; iold_frags != EDICT_NUM(host_client->edictnumber)->v->frags) + sv_player = host_client->edict; + if (host_client->old_frags != sv_player->v->frags) { for (j=0, client = svs.clients ; jmessage, svc_updatefrags); MSG_WriteByte (&client->message, i); - MSG_WriteShort (&client->message, EDICT_NUM(host_client->edictnumber)->v->frags); + MSG_WriteShort (&client->message, sv_player->v->frags); } - host_client->old_frags = EDICT_NUM(host_client->edictnumber)->v->frags; + host_client->old_frags = sv_player->v->frags; } } - for (j=0, client = svs.clients ; jactive) + if (!host_client->active) continue; - SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); + SZ_Write (&host_client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize); } SZ_Clear (&sv.reliable_datagram); @@ -1613,31 +1608,31 @@ void SV_CreateBaseline (void) svent = EDICT_NUM(entnum); // LordHavoc: always clear state values, whether the entity is in use or not - ClearStateToDefault(&svent->baseline); + ClearStateToDefault(&svent->e->baseline); - if (svent->free) + if (svent->e->free) continue; if (entnum > svs.maxclients && !svent->v->modelindex) continue; // create entity baseline - VectorCopy (svent->v->origin, svent->baseline.origin); - VectorCopy (svent->v->angles, svent->baseline.angles); - svent->baseline.frame = svent->v->frame; - svent->baseline.skin = svent->v->skin; + VectorCopy (svent->v->origin, svent->e->baseline.origin); + VectorCopy (svent->v->angles, svent->e->baseline.angles); + svent->e->baseline.frame = svent->v->frame; + svent->e->baseline.skin = svent->v->skin; if (entnum > 0 && entnum <= svs.maxclients) { - svent->baseline.colormap = entnum; - svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl"); + svent->e->baseline.colormap = entnum; + svent->e->baseline.modelindex = SV_ModelIndex("progs/player.mdl"); } else { - svent->baseline.colormap = 0; - svent->baseline.modelindex = svent->v->modelindex; + svent->e->baseline.colormap = 0; + svent->e->baseline.modelindex = svent->v->modelindex; } large = false; - if (svent->baseline.modelindex & 0xFF00 || svent->baseline.frame & 0xFF00) + if (svent->e->baseline.modelindex & 0xFF00 || svent->e->baseline.frame & 0xFF00) large = true; // add to the message @@ -1649,20 +1644,20 @@ void SV_CreateBaseline (void) if (large) { - MSG_WriteShort (&sv.signon, svent->baseline.modelindex); - MSG_WriteShort (&sv.signon, svent->baseline.frame); + MSG_WriteShort (&sv.signon, svent->e->baseline.modelindex); + MSG_WriteShort (&sv.signon, svent->e->baseline.frame); } else { - MSG_WriteByte (&sv.signon, svent->baseline.modelindex); - MSG_WriteByte (&sv.signon, svent->baseline.frame); + MSG_WriteByte (&sv.signon, svent->e->baseline.modelindex); + MSG_WriteByte (&sv.signon, svent->e->baseline.frame); } - MSG_WriteByte (&sv.signon, svent->baseline.colormap); - MSG_WriteByte (&sv.signon, svent->baseline.skin); + MSG_WriteByte (&sv.signon, svent->e->baseline.colormap); + MSG_WriteByte (&sv.signon, svent->e->baseline.skin); for (i=0 ; i<3 ; i++) { - MSG_WriteDPCoord(&sv.signon, svent->baseline.origin[i]); - MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]); + MSG_WriteDPCoord(&sv.signon, svent->e->baseline.origin[i]); + MSG_WriteAngle(&sv.signon, svent->e->baseline.angles[i]); } } } @@ -1714,7 +1709,7 @@ void SV_SaveSpawnparms (void) continue; // call the progs to get default spawn parms for the new client - pr_global_struct->self = EDICT_TO_PROG(EDICT_NUM(host_client->edictnumber)); + pr_global_struct->self = EDICT_TO_PROG(host_client->edict); PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing"); for (j=0 ; jspawn_parms[j] = (&pr_global_struct->parm1)[j]; @@ -1724,37 +1719,37 @@ void SV_SaveSpawnparms (void) void SV_IncreaseEdicts(void) { int i; - edict_t *e; + edict_t *ent; int oldmax_edicts = sv.max_edicts; - void *oldedicts = sv.edicts; + void *oldedictsengineprivate = sv.edictsengineprivate; void *oldedictsfields = sv.edictsfields; - void *oldedictstable = sv.edictstable; void *oldmoved_edicts = sv.moved_edicts; + // links don't survive the transition, so unlink everything for (i = 0;i < sv.max_edicts;i++) - SV_UnlinkEdict (sv.edictstable[i]); + SV_UnlinkEdict (sv.edicts + i); SV_ClearWorld(); sv.max_edicts = min(sv.max_edicts + 32, MAX_EDICTS); - sv.edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t)); + sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t)); sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size); - sv.edictstable = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *)); sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *)); - memcpy(sv.edicts , oldedicts , oldmax_edicts * sizeof(edict_t)); + 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++) { - e = sv.edictstable[i] = sv.edicts + i; - e->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size); + 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) - SV_LinkEdict(e, false); + SV_LinkEdict(ent, false); } - Mem_Free(oldedicts); + Mem_Free(oldedictsengineprivate); Mem_Free(oldedictsfields); - Mem_Free(oldedictstable); Mem_Free(oldmoved_edicts); } @@ -1810,23 +1805,24 @@ void SV_SpawnServer (const char *server) // allocate server memory // start out with just enough room for clients and a reasonable estimate of entities - sv.max_edicts = ((svs.maxclients + 1) + 31) & ~31; - sv.max_edicts = max(sv.max_edicts, 128); + sv.max_edicts = ((svs.maxclients + 128) + 31) & ~31; + sv.max_edicts = min(sv.max_edicts, MAX_EDICTS); // clear the edict memory pool Mem_EmptyPool(sv_edicts_mempool); // edict_t structures (hidden from progs) - sv.edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t)); + sv.edicts = Mem_Alloc(sv_edicts_mempool, MAX_EDICTS * sizeof(edict_t)); + // engine private structures (hidden from progs) + sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t)); // progs fields, often accessed by server sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size); - // table of edict pointers, for quick lookup of edicts - sv.edictstable = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *)); // used by PushMove to move back pushed entities sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *)); for (i = 0;i < sv.max_edicts;i++) { - sv.edictstable[i] = sv.edicts + i; - sv.edictstable[i]->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size); + ent = sv.edicts + i; + ent->e = sv.edictsengineprivate + i; + ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size); } sv.datagram.maxsize = sizeof(sv.datagram_buf); @@ -1844,7 +1840,7 @@ void SV_SpawnServer (const char *server) // leave slots at start for clients only sv.num_edicts = svs.maxclients+1; for (i=0 ; iv, 0, progs->entityfields * 4); - ent->free = false; + ent->e->free = false; ent->v->model = PR_SetString(sv.modelname); ent->v->modelindex = 1; // world model ent->v->solid = SOLID_BSP; diff --git a/sv_phys.c b/sv_phys.c index 5847ad52..e031f19e 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -75,7 +75,7 @@ void SV_CheckAllEnts (void) check = NEXT_EDICT(sv.edicts); for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check)) { - if (check->free) + if (check->e->free) continue; if (check->v->movetype == MOVETYPE_PUSH || check->v->movetype == MOVETYPE_NONE @@ -154,7 +154,7 @@ qboolean SV_RunThink (edict_t *ent) pr_global_struct->self = EDICT_TO_PROG(ent); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); PR_ExecuteProgram (ent->v->think, "NULL think function"); - return !ent->free; + return !ent->e->free; } /* @@ -304,7 +304,7 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) SV_Impact (ent, trace.ent); // break if removed by the impact function - if (ent->free) + if (ent->e->free) break; } @@ -399,7 +399,7 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) SV_Impact (ent, trace.ent); // break if removed by the impact function - if (ent->free) + if (ent->e->free) break; } @@ -646,7 +646,7 @@ void SV_PushMove (edict_t *pusher, float movetime) check = NEXT_EDICT(sv.edicts); for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check)) { - if (check->free) + if (check->e->free) continue; if (check->v->movetype == MOVETYPE_PUSH || check->v->movetype == MOVETYPE_NONE @@ -686,8 +686,8 @@ void SV_PushMove (edict_t *pusher, float movetime) if (check->v->movetype != MOVETYPE_WALK) check->v->flags = (int)check->v->flags & ~FL_ONGROUND; - VectorCopy (check->v->origin, check->moved_from); - VectorCopy (check->v->angles, check->moved_fromangles); + VectorCopy (check->v->origin, check->e->moved_from); + VectorCopy (check->v->angles, check->e->moved_fromangles); sv.moved_edicts[num_moved++] = check; // try moving the contacted entity @@ -727,8 +727,8 @@ void SV_PushMove (edict_t *pusher, float movetime) for (i = 0;i < num_moved;i++) { ed = sv.moved_edicts[i]; - VectorCopy (ed->moved_from, ed->v->origin); - VectorCopy (ed->moved_fromangles, ed->v->angles); + VectorCopy (ed->e->moved_from, ed->v->origin); + VectorCopy (ed->e->moved_fromangles, ed->v->angles); SV_LinkEdict (ed, false); } @@ -778,7 +778,7 @@ void SV_Physics_Pusher (edict_t *ent) pr_global_struct->self = EDICT_TO_PROG(ent); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); PR_ExecuteProgram (ent->v->think, "NULL think function"); - if (ent->free) + if (ent->e->free) return; } @@ -1000,7 +1000,7 @@ void SV_WalkMove (edict_t *ent) if (sv_nostep.integer) return; - if ( (int)sv_player->v->flags & FL_WATERJUMP ) + if ( (int)ent->v->flags & FL_WATERJUMP ) return; VectorCopy (ent->v->origin, nosteporg); @@ -1277,18 +1277,18 @@ void SV_Physics_Toss (edict_t *ent) groundentity = PROG_TO_EDICT(ent->v->groundentity); if (groundentity->v->solid == SOLID_BSP) { - ent->suspendedinairflag = true; + ent->e->suspendedinairflag = true; return; } - else if (ent->suspendedinairflag && groundentity->free) + else if (ent->e->suspendedinairflag && groundentity->e->free) { // leave it suspended in the air ent->v->groundentity = 0; - ent->suspendedinairflag = false; + ent->e->suspendedinairflag = false; return; } } - ent->suspendedinairflag = false; + ent->e->suspendedinairflag = false; SV_CheckVelocity (ent); @@ -1302,7 +1302,7 @@ void SV_Physics_Toss (edict_t *ent) // move origin VectorScale (ent->v->velocity, sv.frametime, move); trace = SV_PushEntity (ent, move, vec3_origin); - if (ent->free) + if (ent->e->free) return; if (trace.fraction < 1) @@ -1437,7 +1437,7 @@ void SV_Physics (void) ent = sv.edicts; for (i=0 ; ifree) + if (ent->e->free) continue; if (pr_global_struct->force_retouch) diff --git a/sv_user.c b/sv_user.c index 6e02dcbd..f895390f 100644 --- a/sv_user.c +++ b/sv_user.c @@ -464,7 +464,6 @@ void SV_ReadClientMove (usercmd_t *move) int bits; eval_t *val; float total; - edict_t *e = EDICT_NUM(host_client->edictnumber); // read ping time host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = sv.time - MSG_ReadFloat (); @@ -477,7 +476,7 @@ void SV_ReadClientMove (usercmd_t *move) // if paused or a local game, don't predict if (sv_predict.integer && (svs.maxclients > 1) && (!sv.paused)) host_client->latency = host_client->ping; - if ((val = GETEDICTFIELDVALUE(e, eval_ping))) + if ((val = GETEDICTFIELDVALUE(sv_player, eval_ping))) val->_float = host_client->ping * 1000.0; // read current angles @@ -485,13 +484,13 @@ void SV_ReadClientMove (usercmd_t *move) for (i = 0;i < 3;i++) angle[i] = MSG_ReadFloat (); - VectorCopy (angle, e->v->v_angle); + VectorCopy (angle, sv_player->v->v_angle); // read movement move->forwardmove = MSG_ReadShort (); move->sidemove = MSG_ReadShort (); move->upmove = MSG_ReadShort (); - if ((val = GETEDICTFIELDVALUE(e, eval_movement))) + if ((val = GETEDICTFIELDVALUE(sv_player, eval_movement))) { val->vector[0] = move->forwardmove; val->vector[1] = move->sidemove; @@ -500,19 +499,19 @@ void SV_ReadClientMove (usercmd_t *move) // read buttons bits = MSG_ReadByte (); - e->v->button0 = bits & 1; - e->v->button2 = (bits & 2)>>1; + sv_player->v->button0 = bits & 1; + sv_player->v->button2 = (bits & 2)>>1; // LordHavoc: added 6 new buttons - if ((val = GETEDICTFIELDVALUE(e, eval_button3))) val->_float = ((bits >> 2) & 1); - if ((val = GETEDICTFIELDVALUE(e, eval_button4))) val->_float = ((bits >> 3) & 1); - if ((val = GETEDICTFIELDVALUE(e, eval_button5))) val->_float = ((bits >> 4) & 1); - if ((val = GETEDICTFIELDVALUE(e, eval_button6))) val->_float = ((bits >> 5) & 1); - if ((val = GETEDICTFIELDVALUE(e, eval_button7))) val->_float = ((bits >> 6) & 1); - if ((val = GETEDICTFIELDVALUE(e, eval_button8))) val->_float = ((bits >> 7) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button3))) val->_float = ((bits >> 2) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button4))) val->_float = ((bits >> 3) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button5))) val->_float = ((bits >> 4) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button6))) val->_float = ((bits >> 5) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button7))) val->_float = ((bits >> 6) & 1); + if ((val = GETEDICTFIELDVALUE(sv_player, eval_button8))) val->_float = ((bits >> 7) & 1); i = MSG_ReadByte (); if (i) - e->v->impulse = i; + sv_player->v->impulse = i; } /* @@ -639,7 +638,7 @@ void SV_RunClients (void) if (!host_client->active) continue; - sv_player = EDICT_NUM(host_client->edictnumber); + sv_player = host_client->edict; if (!SV_ReadClientMessage ()) { diff --git a/world.c b/world.c index 6fceef78..b1215762 100644 --- a/world.c +++ b/world.c @@ -184,10 +184,10 @@ void SV_UnlinkEdict (edict_t *ent) int i; for (i = 0;i < ENTITYGRIDAREAS;i++) { - if (ent->areagrid[i].prev) + if (ent->e->areagrid[i].prev) { - RemoveLink (&ent->areagrid[i]); - ent->areagrid[i].prev = ent->areagrid[i].next = NULL; + RemoveLink (&ent->e->areagrid[i]); + ent->e->areagrid[i].prev = ent->e->areagrid[i].next = NULL; } } } @@ -250,9 +250,9 @@ void SV_TouchAreaGrid(edict_t *ent) { next = l->next; touch = EDICT_NUM(l->entitynumber); - if (touch->areagridmarknumber == sv_areagrid_marknumber) + if (touch->e->areagridmarknumber == sv_areagrid_marknumber) continue; - touch->areagridmarknumber = sv_areagrid_marknumber; + touch->e->areagridmarknumber = sv_areagrid_marknumber; if (ent->v->absmin[0] > touch->v->absmax[0] || ent->v->absmax[0] < touch->v->absmin[0] || ent->v->absmin[1] > touch->v->absmax[1] @@ -294,9 +294,9 @@ void SV_LinkEdict_AreaGrid(edict_t *ent) { // wow, something outside the grid, store it as such if (ent->v->solid == SOLID_TRIGGER) - InsertLinkBefore (&ent->areagrid[0], &sv_areagrid_outside.trigger_edicts, NUM_FOR_EDICT(ent)); + InsertLinkBefore (&ent->e->areagrid[0], &sv_areagrid_outside.trigger_edicts, NUM_FOR_EDICT(ent)); else - InsertLinkBefore (&ent->areagrid[0], &sv_areagrid_outside.solid_edicts, NUM_FOR_EDICT(ent)); + InsertLinkBefore (&ent->e->areagrid[0], &sv_areagrid_outside.solid_edicts, NUM_FOR_EDICT(ent)); return; } @@ -307,9 +307,9 @@ void SV_LinkEdict_AreaGrid(edict_t *ent) for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++, gridnum++) { if (ent->v->solid == SOLID_TRIGGER) - InsertLinkBefore (&ent->areagrid[gridnum], &grid->trigger_edicts, NUM_FOR_EDICT(ent)); + InsertLinkBefore (&ent->e->areagrid[gridnum], &grid->trigger_edicts, NUM_FOR_EDICT(ent)); else - InsertLinkBefore (&ent->areagrid[gridnum], &grid->solid_edicts, NUM_FOR_EDICT(ent)); + InsertLinkBefore (&ent->e->areagrid[gridnum], &grid->solid_edicts, NUM_FOR_EDICT(ent)); } } } @@ -324,13 +324,13 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) { model_t *model; - if (ent->areagrid[0].prev) + if (ent->e->areagrid[0].prev) SV_UnlinkEdict (ent); // unlink from old position if (ent == sv.edicts) return; // don't add the world - if (ent->free) + if (ent->e->free) return; // set the abs box @@ -495,9 +495,9 @@ void SV_ClipToNode(moveclip_t *clip, link_t *list) { next = l->next; touch = EDICT_NUM(l->entitynumber); - if (touch->areagridmarknumber == sv_areagrid_marknumber) + if (touch->e->areagridmarknumber == sv_areagrid_marknumber) continue; - touch->areagridmarknumber = sv_areagrid_marknumber; + touch->e->areagridmarknumber = sv_areagrid_marknumber; sv_areagrid_stats_entitychecks++; if (clip->boxmins[0] > touch->v->absmax[0]