}
host_client->pmodel = i;
- if ((val = GETEDICTFIELDVALUE(EDICT_NUM(host_client->edictnumber), eval_pmodel)))
+ if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)))
val->_float = i;
}
// 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;
}
}
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);
}
}
for (i=0 ; i<svs.maxclients ; i++)
{
- if (svs.clients[i].active && (EDICT_NUM(svs.clients[i].edictnumber)->v->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;
// 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);
}
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
{
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);
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);
}
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");
}
// send all current names, colors, and frag counts
SZ_Clear (&host_client->message);
+ ent = sv_player;
+
// run the entrance script
if (sv.loadgame)
{
{
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);
// 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] );
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));
if (i == check)
break; // didn't find anything else
- if (ent->free)
+ if (ent->e->free)
continue;
if (ent->v->health <= 0)
continue;
// 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;
for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
{
pr_xfunction->builtinsprofile++;
- if (ent->free)
+ if (ent->e->free)
continue;
if (ent->v->solid == SOLID_NOT)
continue;
{
pr_xfunction->builtinsprofile++;
ed = EDICT_NUM(e);
- if (ed->free)
+ if (ed->e->free)
continue;
t = E_STRING(ed,f);
if (!t)
{
pr_xfunction->builtinsprofile++;
ed = EDICT_NUM(e);
- if (ed->free)
+ if (ed->e->free)
continue;
if (E_FLOAT(ed,f) == s)
{
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)
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;
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;
}
}
return;
}
ent = EDICT_NUM(i);
- if (!ent->free)
+ if (!ent->e->free)
{
RETURN_EDICT(ent);
return;
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);
{
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)
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;
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)
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;
void ED_ClearEdict (edict_t *e)
{
memset (e->v, 0, progs->entityfields * 4);
- e->free = false;
+ e->e->free = false;
}
/*
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;
{
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;
ed->v->nextthink = -1;
ed->v->solid = 0;
- ed->freetime = sv.time;
+ ed->e->freetime = sv.time;
}
//===========================================================================
int type;
char tempstring[8192], tempstring2[260]; // temporary string buffers
- if (ed->free)
+ if (ed->e->free)
{
Con_Printf ("FREE\n");
return;
FS_Printf (f, "{\n");
- if (ed->free)
+ if (ed->e->free)
{
FS_Printf (f, "}\n");
return;
for (i=0 ; i<sv.num_edicts ; i++)
{
ent = EDICT_NUM(i);
- if (ent->free)
+ if (ent->e->free)
continue;
active++;
if (ent->v->solid)
}
if (!init)
- ent->free = true;
+ ent->e->free = true;
return data;
}
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (func - pr_functions, "");
spawned++;
- if (ent->free)
+ if (ent->e->free)
died++;
}
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++)
{
//}
//#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;
{
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));
}
*/
#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,
// 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;
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
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)
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;
// 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;
// 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);
*/
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];
Con_DPrintf ("Client %s connected\n", client->netconnection->address);
- edictnum = clientnum+1;
-
- ent = EDICT_NUM(edictnum);
-
// set up the client_t
netconnection = client->netconnection;
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
bits = bits | U_EXTERIORMODEL;
// send an update
- baseline = &ent->baseline;
+ baseline = &ent->e->baseline;
if (((int)ent->v->effects & EF_DELTA) && sv_deltacompress.integer)
{
if (realtime < client->nextfullupdate[e])
{
bits |= U_DELTA;
- baseline = &ent->deltabaseline;
+ baseline = &ent->e->deltabaseline;
}
else
nextfullupdate = realtime + 0.5f;
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)
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;
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)
*/
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 ; i<svs.maxclients ; i++, host_client++)
{
- if (host_client->old_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 ; j<svs.maxclients ; j++, client++)
{
continue;
MSG_WriteByte (&client->message, 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 ; j<svs.maxclients ; j++, client++)
+ for (j=0, host_client = svs.clients ; j<svs.maxclients ; j++, host_client++)
{
- if (!client->active)
+ 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);
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
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]);
}
}
}
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 ; j<NUM_SPAWN_PARMS ; j++)
host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
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);
}
// 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);
// leave slots at start for clients only
sv.num_edicts = svs.maxclients+1;
for (i=0 ; i<svs.maxclients ; i++)
- svs.clients[i].edictnumber = i+1;
+ svs.clients[i].edict = EDICT_NUM(i+1);
sv.state = ss_loading;
sv.paused = false;
//
ent = EDICT_NUM(0);
memset (ent->v, 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;
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
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;
}
/*
SV_Impact (ent, trace.ent);
// break if removed by the impact function
- if (ent->free)
+ if (ent->e->free)
break;
}
SV_Impact (ent, trace.ent);
// break if removed by the impact function
- if (ent->free)
+ if (ent->e->free)
break;
}
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
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
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);
}
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;
}
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);
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);
// 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)
ent = sv.edicts;
for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
{
- if (ent->free)
+ if (ent->e->free)
continue;
if (pr_global_struct->force_retouch)
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 ();
// 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
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;
// 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;
}
/*
if (!host_client->active)
continue;
- sv_player = EDICT_NUM(host_client->edictnumber);
+ sv_player = host_client->edict;
if (!SV_ReadClientMessage ())
{
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;
}
}
}
{
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]
{
// 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;
}
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));
}
}
}
{
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
{
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]