void SV_VM_Init();
void SV_VM_Setup();
+void VM_AutoSentStats_Clear (void);
+void EntityFrameCSQC_ClearVersions (void);
+void EntityFrameCSQC_InitClientVersions (int client, qboolean clear);
+void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
+void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_state_t *states);
+
+
// select which protocol to host, this is fed to Protocol_EnumForName
cvar_t sv_protocolname = {0, "sv_protocolname", "DP7"};
cvar_t sv_ratelimitlocalplayer = {0, "sv_ratelimitlocalplayer", "0"};
==============================================================================
*/
+static const char *SV_InitCmd; //[515]: svprogs able to send cmd to client on connect
/*
================
SV_SendServerinfo
dpsnprintf (message, sizeof (message), "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, prog->filecrc);
MSG_WriteString (&client->message,message);
+ // LordHavoc: this does not work on dedicated servers, needs fixing.
+extern qboolean csqc_loaded;
+//[515]: init csprogs according to version of svprogs, check the crc, etc.
+ if(csqc_loaded && (cls.state == ca_dedicated || PRVM_NUM_FOR_EDICT(client->edict) != 1))
+ {
+ MSG_WriteByte (&client->message, svc_stufftext);
+ if(SV_InitCmd)
+ MSG_WriteString (&client->message, va("csqc_progcrc %i;%s\n", csqc_progcrc.integer, SV_InitCmd));
+ else
+ MSG_WriteString (&client->message, va("csqc_progcrc %i\n", csqc_progcrc.integer));
+ }
+
MSG_WriteByte (&client->message, svc_serverinfo);
MSG_WriteLong (&client->message, Protocol_NumberForEnum(sv.protocol));
MSG_WriteByte (&client->message, svs.maxclients);
client = svs.clients + clientnum;
+ if(netconnection)//[515]: bots don't play with csqc =)
+ EntityFrameCSQC_InitClientVersions(clientnum, false);
+
// set up the client_t
if (sv.loadgame)
memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
static entity_state_t sendentities[MAX_EDICTS];
static entity_state_t *sendentitiesindex[MAX_EDICTS];
-void SV_PrepareEntitiesForSending(void)
+qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *cs, int e)
{
- int e, i;
- float f;
+ int i;
unsigned int modelindex, effects, flags, glowsize, lightstyle, lightpflags, light[4], specialvisibilityradius;
+ unsigned int customizeentityforclient;
+ float f;
vec3_t cullmins, cullmaxs;
model_t *model;
- prvm_edict_t *ent;
prvm_eval_t *val;
- entity_state_t cs;
- // send all entities that touch the pvs
- numsendentities = 0;
- sendentitiesindex[0] = NULL;
- for (e = 1, ent = PRVM_NEXT_EDICT(prog->edicts);e < prog->num_edicts;e++, ent = PRVM_NEXT_EDICT(ent))
- {
- sendentitiesindex[e] = NULL;
- // the 2 billion unit check is actually to detect NAN origins (we really don't want to send those)
- if (ent->priv.server->free || VectorLength2(ent->fields.server->origin) > 2000000000.0*2000000000.0)
- continue;
-
- // this check disabled because it is never true
- //if (numsendentities >= MAX_EDICTS)
- // continue;
- // EF_NODRAW prevents sending for any reason except for your own
- // client, so we must keep all clients in this superset
- effects = (unsigned)ent->fields.server->effects;
- if (e > svs.maxclients && (effects & EF_NODRAW))
- continue;
-
- // we can omit invisible entities with no effects that are not clients
- // LordHavoc: this could kill tags attached to an invisible entity, I
- // just hope we never have to support that case
- i = (int)ent->fields.server->modelindex;
- modelindex = (i >= 1 && i < MAX_MODELS && *PRVM_GetString(ent->fields.server->model)) ? i : 0;
-
- flags = 0;
- i = (int)(PRVM_GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
- glowsize = (unsigned char)bound(0, i, 255);
- if (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
- flags |= RENDER_GLOWTRAIL;
-
- f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[0]*256;
- light[0] = (unsigned short)bound(0, f, 65535);
- f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[1]*256;
- light[1] = (unsigned short)bound(0, f, 65535);
- f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[2]*256;
- light[2] = (unsigned short)bound(0, f, 65535);
- f = PRVM_GETEDICTFIELDVALUE(ent, eval_light_lev)->_float;
- light[3] = (unsigned short)bound(0, f, 65535);
- lightstyle = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_style)->_float;
- lightpflags = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
-
- if (gamemode == GAME_TENEBRAE)
+ // EF_NODRAW prevents sending for any reason except for your own
+ // client, so we must keep all clients in this superset
+ effects = (unsigned)ent->fields.server->effects;
+
+ // we can omit invisible entities with no effects that are not clients
+ // LordHavoc: this could kill tags attached to an invisible entity, I
+ // just hope we never have to support that case
+ i = (int)ent->fields.server->modelindex;
+ modelindex = (i >= 1 && i < MAX_MODELS && *PRVM_GetString(ent->fields.server->model)) ? i : 0;
+
+ flags = 0;
+ i = (int)(PRVM_GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
+ glowsize = (unsigned char)bound(0, i, 255);
+ if (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
+ flags |= RENDER_GLOWTRAIL;
+
+ f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[0]*256;
+ light[0] = (unsigned short)bound(0, f, 65535);
+ f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[1]*256;
+ light[1] = (unsigned short)bound(0, f, 65535);
+ f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[2]*256;
+ light[2] = (unsigned short)bound(0, f, 65535);
+ f = PRVM_GETEDICTFIELDVALUE(ent, eval_light_lev)->_float;
+ light[3] = (unsigned short)bound(0, f, 65535);
+ lightstyle = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_style)->_float;
+ lightpflags = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
+
+ if (gamemode == GAME_TENEBRAE)
+ {
+ // tenebrae's EF_FULLDYNAMIC conflicts with Q2's EF_NODRAW
+ if (effects & 16)
{
- // tenebrae's EF_FULLDYNAMIC conflicts with Q2's EF_NODRAW
- if (effects & 16)
- {
- effects &= ~16;
- lightpflags |= PFLAGS_FULLDYNAMIC;
- }
- // tenebrae's EF_GREEN conflicts with DP's EF_ADDITIVE
- if (effects & 32)
- {
- effects &= ~32;
- light[0] = 0.2;
- light[1] = 1;
- light[2] = 0.2;
- light[3] = 200;
- lightpflags |= PFLAGS_FULLDYNAMIC;
- }
+ effects &= ~16;
+ lightpflags |= PFLAGS_FULLDYNAMIC;
}
-
- specialvisibilityradius = 0;
- if (lightpflags & PFLAGS_FULLDYNAMIC)
- specialvisibilityradius = max(specialvisibilityradius, light[3]);
- if (glowsize)
- specialvisibilityradius = max(specialvisibilityradius, glowsize * 4);
- if (flags & RENDER_GLOWTRAIL)
- specialvisibilityradius = max(specialvisibilityradius, 100);
- if (effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
+ // tenebrae's EF_GREEN conflicts with DP's EF_ADDITIVE
+ if (effects & 32)
{
- if (effects & EF_BRIGHTFIELD)
- specialvisibilityradius = max(specialvisibilityradius, 80);
- if (effects & EF_MUZZLEFLASH)
- specialvisibilityradius = max(specialvisibilityradius, 100);
- if (effects & EF_BRIGHTLIGHT)
- specialvisibilityradius = max(specialvisibilityradius, 400);
- if (effects & EF_DIMLIGHT)
- specialvisibilityradius = max(specialvisibilityradius, 200);
- if (effects & EF_RED)
- specialvisibilityradius = max(specialvisibilityradius, 200);
- if (effects & EF_BLUE)
- specialvisibilityradius = max(specialvisibilityradius, 200);
- if (effects & EF_FLAME)
- specialvisibilityradius = max(specialvisibilityradius, 250);
- if (effects & EF_STARDUST)
- specialvisibilityradius = max(specialvisibilityradius, 100);
+ effects &= ~32;
+ light[0] = 0.2;
+ light[1] = 1;
+ light[2] = 0.2;
+ light[3] = 200;
+ lightpflags |= PFLAGS_FULLDYNAMIC;
}
- if (e > svs.maxclients && (!modelindex && !specialvisibilityradius))
- continue;
+ }
- cs = defaultstate;
- cs.active = true;
- cs.number = e;
- VectorCopy(ent->fields.server->origin, cs.origin);
- VectorCopy(ent->fields.server->angles, cs.angles);
- cs.flags = flags;
- cs.effects = effects;
- cs.colormap = (unsigned)ent->fields.server->colormap;
- cs.modelindex = modelindex;
- cs.skin = (unsigned)ent->fields.server->skin;
- cs.frame = (unsigned)ent->fields.server->frame;
- cs.viewmodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
- cs.exteriormodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
- cs.nodrawtoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
- cs.drawonlytoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
- cs.tagentity = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
- cs.tagindex = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
- cs.glowsize = glowsize;
-
- // don't need to init cs.colormod because the defaultstate did that for us
- //cs.colormod[0] = cs.colormod[1] = cs.colormod[2] = 32;
- val = PRVM_GETEDICTFIELDVALUE(ent, eval_colormod);
- if (val->vector[0] || val->vector[1] || val->vector[2])
- {
- i = val->vector[0] * 32.0f;cs.colormod[0] = bound(0, i, 255);
- i = val->vector[1] * 32.0f;cs.colormod[1] = bound(0, i, 255);
- i = val->vector[2] * 32.0f;cs.colormod[2] = bound(0, i, 255);
- }
+ specialvisibilityradius = 0;
+ if (lightpflags & PFLAGS_FULLDYNAMIC)
+ specialvisibilityradius = max(specialvisibilityradius, light[3]);
+ if (glowsize)
+ specialvisibilityradius = max(specialvisibilityradius, glowsize * 4);
+ if (flags & RENDER_GLOWTRAIL)
+ specialvisibilityradius = max(specialvisibilityradius, 100);
+ if (effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
+ {
+ if (effects & EF_BRIGHTFIELD)
+ specialvisibilityradius = max(specialvisibilityradius, 80);
+ if (effects & EF_MUZZLEFLASH)
+ specialvisibilityradius = max(specialvisibilityradius, 100);
+ if (effects & EF_BRIGHTLIGHT)
+ specialvisibilityradius = max(specialvisibilityradius, 400);
+ if (effects & EF_DIMLIGHT)
+ specialvisibilityradius = max(specialvisibilityradius, 200);
+ if (effects & EF_RED)
+ specialvisibilityradius = max(specialvisibilityradius, 200);
+ if (effects & EF_BLUE)
+ specialvisibilityradius = max(specialvisibilityradius, 200);
+ if (effects & EF_FLAME)
+ specialvisibilityradius = max(specialvisibilityradius, 250);
+ if (effects & EF_STARDUST)
+ specialvisibilityradius = max(specialvisibilityradius, 100);
+ }
- cs.modelindex = modelindex;
+ // early culling checks
+ // (final culling is done by SV_MarkWriteEntityStateToClient)
+ customizeentityforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_customizeentityforclient)->function;
+ if (!customizeentityforclient)
+ {
+ if (e > svs.maxclients && (!modelindex && !specialvisibilityradius))
+ return false;
+ // this 2 billion unit check is actually to detect NAN origins
+ // (we really don't want to send those)
+ if (VectorLength2(ent->fields.server->origin) > 2000000000.0*2000000000.0)
+ return false;
+ }
- cs.alpha = 255;
- f = (PRVM_GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
- if (f)
- {
- i = (int)f;
- cs.alpha = (unsigned char)bound(0, i, 255);
- }
- // halflife
- f = (PRVM_GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
- if (f)
- {
- i = (int)f;
- cs.alpha = (unsigned char)bound(0, i, 255);
- }
- cs.scale = 16;
- f = (PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
- if (f)
- {
- i = (int)f;
- cs.scale = (unsigned char)bound(0, i, 255);
- }
+ *cs = defaultstate;
+ cs->active = true;
+ cs->number = e;
+ VectorCopy(ent->fields.server->origin, cs->origin);
+ VectorCopy(ent->fields.server->angles, cs->angles);
+ cs->flags = flags;
+ cs->effects = effects;
+ cs->colormap = (unsigned)ent->fields.server->colormap;
+ cs->modelindex = modelindex;
+ cs->skin = (unsigned)ent->fields.server->skin;
+ cs->frame = (unsigned)ent->fields.server->frame;
+ cs->viewmodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
+ cs->exteriormodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
+ cs->nodrawtoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
+ cs->drawonlytoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
+ cs->customizeentityforclient = customizeentityforclient;
+ cs->tagentity = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
+ cs->tagindex = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
+ cs->glowsize = glowsize;
+
+ // don't need to init cs->colormod because the defaultstate did that for us
+ //cs->colormod[0] = cs->colormod[1] = cs->colormod[2] = 32;
+ val = PRVM_GETEDICTFIELDVALUE(ent, eval_colormod);
+ if (val->vector[0] || val->vector[1] || val->vector[2])
+ {
+ i = val->vector[0] * 32.0f;cs->colormod[0] = bound(0, i, 255);
+ i = val->vector[1] * 32.0f;cs->colormod[1] = bound(0, i, 255);
+ i = val->vector[2] * 32.0f;cs->colormod[2] = bound(0, i, 255);
+ }
+
+ cs->modelindex = modelindex;
- cs.glowcolor = 254;
- f = (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
- if (f)
- cs.glowcolor = (int)f;
+ cs->alpha = 255;
+ f = (PRVM_GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
+ if (f)
+ {
+ i = (int)f;
+ cs->alpha = (unsigned char)bound(0, i, 255);
+ }
+ // halflife
+ f = (PRVM_GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
+ if (f)
+ {
+ i = (int)f;
+ cs->alpha = (unsigned char)bound(0, i, 255);
+ }
- if (PRVM_GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
- cs.effects |= EF_FULLBRIGHT;
+ cs->scale = 16;
+ f = (PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
+ if (f)
+ {
+ i = (int)f;
+ cs->scale = (unsigned char)bound(0, i, 255);
+ }
- if (ent->fields.server->movetype == MOVETYPE_STEP)
- cs.flags |= RENDER_STEP;
- if ((cs.effects & EF_LOWPRECISION) && cs.origin[0] >= -32768 && cs.origin[1] >= -32768 && cs.origin[2] >= -32768 && cs.origin[0] <= 32767 && cs.origin[1] <= 32767 && cs.origin[2] <= 32767)
- cs.flags |= RENDER_LOWPRECISION;
- if (ent->fields.server->colormap >= 1024)
- cs.flags |= RENDER_COLORMAPPED;
- if (cs.viewmodelforclient)
- cs.flags |= RENDER_VIEWMODEL; // show relative to the view
-
- cs.light[0] = light[0];
- cs.light[1] = light[1];
- cs.light[2] = light[2];
- cs.light[3] = light[3];
- cs.lightstyle = lightstyle;
- cs.lightpflags = lightpflags;
-
- cs.specialvisibilityradius = specialvisibilityradius;
-
- // calculate the visible box of this entity (don't use the physics box
- // as that is often smaller than a model, and would not count
- // specialvisibilityradius)
- if ((model = sv.models[modelindex]))
+ cs->glowcolor = 254;
+ f = (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
+ if (f)
+ cs->glowcolor = (int)f;
+
+ if (PRVM_GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
+ cs->effects |= EF_FULLBRIGHT;
+
+ if (ent->fields.server->movetype == MOVETYPE_STEP)
+ cs->flags |= RENDER_STEP;
+ if ((cs->effects & EF_LOWPRECISION) && cs->origin[0] >= -32768 && cs->origin[1] >= -32768 && cs->origin[2] >= -32768 && cs->origin[0] <= 32767 && cs->origin[1] <= 32767 && cs->origin[2] <= 32767)
+ cs->flags |= RENDER_LOWPRECISION;
+ if (ent->fields.server->colormap >= 1024)
+ cs->flags |= RENDER_COLORMAPPED;
+ if (cs->viewmodelforclient)
+ cs->flags |= RENDER_VIEWMODEL; // show relative to the view
+
+ cs->light[0] = light[0];
+ cs->light[1] = light[1];
+ cs->light[2] = light[2];
+ cs->light[3] = light[3];
+ cs->lightstyle = lightstyle;
+ cs->lightpflags = lightpflags;
+
+ cs->specialvisibilityradius = specialvisibilityradius;
+
+ // calculate the visible box of this entity (don't use the physics box
+ // as that is often smaller than a model, and would not count
+ // specialvisibilityradius)
+ if ((model = sv.models[modelindex]))
+ {
+ float scale = cs->scale * (1.0f / 16.0f);
+ if (cs->angles[0] || cs->angles[2]) // pitch and roll
{
- float scale = cs.scale * (1.0f / 16.0f);
- if (cs.angles[0] || cs.angles[2]) // pitch and roll
- {
- VectorMA(cs.origin, scale, model->rotatedmins, cullmins);
- VectorMA(cs.origin, scale, model->rotatedmaxs, cullmaxs);
- }
- else if (cs.angles[1])
- {
- VectorMA(cs.origin, scale, model->yawmins, cullmins);
- VectorMA(cs.origin, scale, model->yawmaxs, cullmaxs);
- }
- else
- {
- VectorMA(cs.origin, scale, model->normalmins, cullmins);
- VectorMA(cs.origin, scale, model->normalmaxs, cullmaxs);
- }
+ VectorMA(cs->origin, scale, model->rotatedmins, cullmins);
+ VectorMA(cs->origin, scale, model->rotatedmaxs, cullmaxs);
}
- else
+ else if (cs->angles[1])
{
- VectorCopy(cs.origin, cullmins);
- VectorCopy(cs.origin, cullmaxs);
+ VectorMA(cs->origin, scale, model->yawmins, cullmins);
+ VectorMA(cs->origin, scale, model->yawmaxs, cullmaxs);
}
- if (specialvisibilityradius)
+ else
{
- cullmins[0] = min(cullmins[0], cs.origin[0] - specialvisibilityradius);
- cullmins[1] = min(cullmins[1], cs.origin[1] - specialvisibilityradius);
- cullmins[2] = min(cullmins[2], cs.origin[2] - specialvisibilityradius);
- cullmaxs[0] = max(cullmaxs[0], cs.origin[0] + specialvisibilityradius);
- cullmaxs[1] = max(cullmaxs[1], cs.origin[1] + specialvisibilityradius);
- cullmaxs[2] = max(cullmaxs[2], cs.origin[2] + specialvisibilityradius);
+ VectorMA(cs->origin, scale, model->normalmins, cullmins);
+ VectorMA(cs->origin, scale, model->normalmaxs, cullmaxs);
}
- if (!VectorCompare(cullmins, ent->priv.server->cullmins) || !VectorCompare(cullmaxs, ent->priv.server->cullmaxs))
+ }
+ else
+ {
+ VectorCopy(cs->origin, cullmins);
+ VectorCopy(cs->origin, cullmaxs);
+ }
+ if (specialvisibilityradius)
+ {
+ cullmins[0] = min(cullmins[0], cs->origin[0] - specialvisibilityradius);
+ cullmins[1] = min(cullmins[1], cs->origin[1] - specialvisibilityradius);
+ cullmins[2] = min(cullmins[2], cs->origin[2] - specialvisibilityradius);
+ cullmaxs[0] = max(cullmaxs[0], cs->origin[0] + specialvisibilityradius);
+ cullmaxs[1] = max(cullmaxs[1], cs->origin[1] + specialvisibilityradius);
+ cullmaxs[2] = max(cullmaxs[2], cs->origin[2] + specialvisibilityradius);
+ }
+ if (!VectorCompare(cullmins, ent->priv.server->cullmins) || !VectorCompare(cullmaxs, ent->priv.server->cullmaxs))
+ {
+ VectorCopy(cullmins, ent->priv.server->cullmins);
+ VectorCopy(cullmaxs, ent->priv.server->cullmaxs);
+ ent->priv.server->pvs_numclusters = -1;
+ if (sv.worldmodel && sv.worldmodel->brush.FindBoxClusters)
{
- VectorCopy(cullmins, ent->priv.server->cullmins);
- VectorCopy(cullmaxs, ent->priv.server->cullmaxs);
- ent->priv.server->pvs_numclusters = -1;
- if (sv.worldmodel && sv.worldmodel->brush.FindBoxClusters)
- {
- i = sv.worldmodel->brush.FindBoxClusters(sv.worldmodel, cullmins, cullmaxs, MAX_ENTITYCLUSTERS, ent->priv.server->pvs_clusterlist);
- if (i <= MAX_ENTITYCLUSTERS)
- ent->priv.server->pvs_numclusters = i;
- }
+ i = sv.worldmodel->brush.FindBoxClusters(sv.worldmodel, cullmins, cullmaxs, MAX_ENTITYCLUSTERS, ent->priv.server->pvs_clusterlist);
+ if (i <= MAX_ENTITYCLUSTERS)
+ ent->priv.server->pvs_numclusters = i;
}
+ }
+
+ return true;
+}
- sendentitiesindex[e] = sendentities + numsendentities;
- sendentities[numsendentities++] = cs;
+void SV_PrepareEntitiesForSending(void)
+{
+ int e;
+ prvm_edict_t *ent;
+ // send all entities that touch the pvs
+ numsendentities = 0;
+ sendentitiesindex[0] = NULL;
+ memset(sendentitiesindex, 0, prog->num_edicts * sizeof(entity_state_t *));
+ for (e = 1, ent = PRVM_NEXT_EDICT(prog->edicts);e < prog->num_edicts;e++, ent = PRVM_NEXT_EDICT(ent))
+ {
+ if (!ent->priv.server->free && SV_PrepareEntityForSending(ent, sendentities + numsendentities, e))
+ {
+ sendentitiesindex[e] = sendentities + numsendentities;
+ numsendentities++;
+ }
}
}
sententitiesconsideration[s->number] = sententitiesmark;
sv_writeentitiestoclient_totalentities++;
+ if (s->customizeentityforclient)
+ {
+ prog->globals.server->self = s->number;
+ prog->globals.server->other = sv_writeentitiestoclient_clentnum;
+ PRVM_ExecuteProgram(s->customizeentityforclient, "customizeentityforclient: NULL function");
+ if(!PRVM_G_FLOAT(OFS_RETURN) || !SV_PrepareEntityForSending(PRVM_EDICT_NUM(s->number), s, s->number))
+ return;
+ }
+
// never reject player
if (s->number != sv_writeentitiestoclient_clentnum)
{
{
int i, numsendstates;
entity_state_t *s;
+ extern int csqc_clent;
// if there isn't enough space to accomplish anything, skip it
if (msg->cursize + 25 > msg->maxsize)
if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
sv_writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv_writeentitiestoclient_testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
- sv_writeentitiestoclient_clentnum = PRVM_EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
+ csqc_clent = sv_writeentitiestoclient_clentnum = PRVM_EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
sententitiesmark++;
if (sv_cullentities_stats.integer)
Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
+ EntityFrameCSQC_WriteFrame(msg, numsendstates, sendstates);
+
if (client->entitydatabase5)
EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats, client->movesequence);
else if (client->entitydatabase4)
if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_punchvector)))
VectorCopy(val->vector, punchvector);
- // FIXME: cache weapon model name and index in client struct to save time
+ // cache weapon model name and index in client struct to save time
// (this search can be almost 1% of cpu time!)
s = PRVM_GetString(ent->fields.server->weaponmodel);
if (strcmp(s, client->weaponmodel))
// add the client specific data to the datagram
SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
+ VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
// expand packet size to allow effects to go over the rate limit
ent->fields.server = (void *)((unsigned char *)prog->edictsfields + i * prog->edict_size);
}*/
+ // reset client csqc entity versions right away.
+ for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
+ EntityFrameCSQC_InitClientVersions(i, true);
+
sv.datagram.maxsize = sizeof(sv.datagram_buf);
sv.datagram.cursize = 0;
sv.datagram.data = sv.datagram_buf;
int eval_button6;
int eval_button7;
int eval_button8;
+int eval_button9;
+int eval_button10;
+int eval_button11;
+int eval_button12;
+int eval_button13;
+int eval_button14;
+int eval_button15;
+int eval_button16;
int eval_buttonuse;
int eval_buttonchat;
int eval_glow_size;
int eval_colormod;
int eval_playermodel;
int eval_playerskin;
+int eval_SendEntity;
+int eval_Version;
+int eval_customizeentityforclient;
mfunction_t *SV_PlayerPhysicsQC;
mfunction_t *EndFrameQC;
//KrimZon - SERVER COMMANDS IN QUAKEC
mfunction_t *SV_ParseClientCommandQC;
+ddef_t *PRVM_ED_FindGlobal(const char *name);
+
void SV_VM_FindEdictFieldOffsets(void)
{
eval_gravity = PRVM_ED_FindFieldOffset("gravity");
eval_button6 = PRVM_ED_FindFieldOffset("button6");
eval_button7 = PRVM_ED_FindFieldOffset("button7");
eval_button8 = PRVM_ED_FindFieldOffset("button8");
+ eval_button9 = PRVM_ED_FindFieldOffset("button9");
+ eval_button10 = PRVM_ED_FindFieldOffset("button10");
+ eval_button11 = PRVM_ED_FindFieldOffset("button11");
+ eval_button12 = PRVM_ED_FindFieldOffset("button12");
+ eval_button13 = PRVM_ED_FindFieldOffset("button13");
+ eval_button14 = PRVM_ED_FindFieldOffset("button14");
+ eval_button15 = PRVM_ED_FindFieldOffset("button15");
+ eval_button16 = PRVM_ED_FindFieldOffset("button16");
eval_buttonuse = PRVM_ED_FindFieldOffset("buttonuse");
eval_buttonchat = PRVM_ED_FindFieldOffset("buttonchat");
eval_glow_size = PRVM_ED_FindFieldOffset("glow_size");
eval_colormod = PRVM_ED_FindFieldOffset("colormod");
eval_playermodel = PRVM_ED_FindFieldOffset("playermodel");
eval_playerskin = PRVM_ED_FindFieldOffset("playerskin");
+ eval_SendEntity = PRVM_ED_FindFieldOffset("SendEntity");
+ eval_Version = PRVM_ED_FindFieldOffset("Version");
+ eval_customizeentityforclient = PRVM_ED_FindFieldOffset("customizeentityforclient");
// LordHavoc: allowing QuakeC to override the player movement code
SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
//KrimZon - SERVER COMMANDS IN QUAKEC
SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
+
+ //[515]: init stufftext string (it is sent before svc_serverinfo)
+ if(PRVM_ED_FindGlobal("SV_InitCmd") && PRVM_ED_FindGlobal("SV_InitCmd")->type & ev_string)
+ SV_InitCmd = PRVM_G_STRING(PRVM_ED_FindGlobal("SV_InitCmd")->ofs);
+ else
+ SV_InitCmd = NULL;
}
#define REQFIELDS (sizeof(reqfields) / sizeof(prvm_required_field_t))
{ev_float, "button6"},
{ev_float, "button7"},
{ev_float, "button8"},
+ {ev_float, "button9"},
+ {ev_float, "button10"},
+ {ev_float, "button11"},
+ {ev_float, "button12"},
+ {ev_float, "button13"},
+ {ev_float, "button14"},
+ {ev_float, "button15"},
+ {ev_float, "button16"},
{ev_float, "buttonchat"},
{ev_float, "buttonuse"},
{ev_float, "clientcolors"},
{ev_float, "scale"},
{ev_float, "style"},
{ev_float, "tag_index"},
+ {ev_float, "Version"},
{ev_float, "viewzoom"},
{ev_vector, "color"},
{ev_vector, "colormod"},
{ev_vector, "movement"},
{ev_vector, "punchvector"},
{ev_string, "playermodel"},
- {ev_string, "playerskin"}
+ {ev_string, "playerskin"},
+ {ev_function, "SendEntity"},
+ {ev_function, "customizeentityforclient"},
};
void SV_VM_Setup(void)
PRVM_LoadProgs( sv_progs.string, 0, NULL, REQFIELDS, reqfields );
SV_VM_FindEdictFieldOffsets();
+ VM_AutoSentStats_Clear();//[515]: csqc
+ EntityFrameCSQC_ClearVersions();//[515]: csqc
+
PRVM_End;
}