extern cvar_t sv_accelerate;
extern cvar_t sv_idealpitchscale;
extern cvar_t sv_aim;
+ extern cvar_t sv_predict;
Cvar_RegisterVariable (&sv_maxvelocity);
Cvar_RegisterVariable (&sv_gravity);
Cvar_RegisterVariable (&sv_idealpitchscale);
Cvar_RegisterVariable (&sv_aim);
Cvar_RegisterVariable (&sv_nostep);
+ Cvar_RegisterVariable (&sv_predict);
for (i=0 ; i<MAX_MODELS ; i++)
sprintf (localmodels[i], "*%i", i);
if (sv.datagram.cursize > MAX_DATAGRAM-16)
return;
MSG_WriteByte (&sv.datagram, svc_particle);
- MSG_WriteCoord (&sv.datagram, org[0]);
- MSG_WriteCoord (&sv.datagram, org[1]);
- MSG_WriteCoord (&sv.datagram, org[2]);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
for (i=0 ; i<3 ; i++)
{
v = dir[i]*16;
MSG_WriteByte (&sv.datagram, color);
}
+/*
+==================
+SV_StartEffect
+
+Make sure the event gets sent to all clients
+==================
+*/
+void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
+{
+ if (sv.datagram.cursize > MAX_DATAGRAM-18)
+ return;
+ if (modelindex >= 256)
+ {
+ MSG_WriteByte (&sv.datagram, svc_effect2);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
+ MSG_WriteShort (&sv.datagram, modelindex);
+ MSG_WriteByte (&sv.datagram, startframe);
+ MSG_WriteByte (&sv.datagram, framecount);
+ MSG_WriteByte (&sv.datagram, framerate);
+ }
+ else
+ {
+ MSG_WriteByte (&sv.datagram, svc_effect);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
+ MSG_WriteByte (&sv.datagram, modelindex);
+ MSG_WriteByte (&sv.datagram, startframe);
+ MSG_WriteByte (&sv.datagram, framecount);
+ MSG_WriteByte (&sv.datagram, framerate);
+ }
+}
+
/*
==================
SV_StartSound
weapon, feet, etc.
Channel 0 is an auto-allocate channel, the others override anything
-allready running on that entity/channel pair.
+already running on that entity/channel pair.
An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off. (max 4 attenuation)
int ent;
if (volume < 0 || volume > 255)
- Sys_Error ("SV_StartSound: volume = %i", volume);
+ Host_Error ("SV_StartSound: volume = %i", volume);
if (attenuation < 0 || attenuation > 4)
- Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
+ Host_Error ("SV_StartSound: attenuation = %f", attenuation);
if (channel < 0 || channel > 7)
- Sys_Error ("SV_StartSound: channel = %i", channel);
+ Host_Error ("SV_StartSound: channel = %i", channel);
if (sv.datagram.cursize > MAX_DATAGRAM-16)
return;
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
field_mask |= SND_ATTENUATION;
-// directed messages go only to the entity the are targeted on
- MSG_WriteByte (&sv.datagram, svc_sound);
+// directed messages go only to the entity they are targeted on
+ if (sound_num >= 256)
+ MSG_WriteByte (&sv.datagram, svc_sound2);
+ else
+ MSG_WriteByte (&sv.datagram, svc_sound);
MSG_WriteByte (&sv.datagram, field_mask);
if (field_mask & SND_VOLUME)
MSG_WriteByte (&sv.datagram, volume);
if (field_mask & SND_ATTENUATION)
MSG_WriteByte (&sv.datagram, attenuation*64);
MSG_WriteShort (&sv.datagram, channel);
- MSG_WriteByte (&sv.datagram, sound_num);
+ if (sound_num >= 256)
+ MSG_WriteShort (&sv.datagram, sound_num);
+ else
+ MSG_WriteByte (&sv.datagram, sound_num);
for (i=0 ; i<3 ; i++)
- MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
+ MSG_WriteFloatCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
}
/*
char message[2048];
MSG_WriteByte (&client->message, svc_print);
-#ifdef NEHAHRA
- sprintf (message, "%c\nDPNEHAHRA VERSION %4.2f SERVER (%i CRC)", 2, DP_VERSION, pr_crc);
-#else
- sprintf (message, "%c\nDARKPLACES VERSION %4.2f SERVER (%i CRC)", 2, DP_VERSION, pr_crc);
-#endif
+ sprintf (message, "%c\nDARKPLACES VERSION %4.2f BUILD %i SERVER (%i CRC)", 2, VERSION, buildnumber, pr_crc);
MSG_WriteString (&client->message,message);
MSG_WriteByte (&client->message, svc_serverinfo);
- MSG_WriteLong (&client->message, PROTOCOL_VERSION);
+ MSG_WriteLong (&client->message, DPPROTOCOL_VERSION);
MSG_WriteByte (&client->message, svs.maxclients);
if (!coop.value && deathmatch.value)
client->message.maxsize = sizeof(client->msgbuf);
client->message.allowoverflow = true; // we can catch it
-#ifdef IDGODS
- client->privileged = IsID(&client->netconnection->addr);
-#else
- client->privileged = false;
-#endif
-
if (sv.loadgame)
memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
else
{
// call the progs to get default spawn parms for the new client
- PR_ExecuteProgram (pr_global_struct->SetNewParms);
+ PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
}
=============
*/
-void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
+void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
{
int e, i, clentnum, bits, alpha, glowcolor, glowsize, scale, colormod, modred, modgreen, modblue, dodelta, effects;
byte *pvs;
// find the client's PVS
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
pvs = SV_FatPVS (org);
+ /*
+ if (dpprotocol)
+ {
+ MSG_WriteByte(msg, svc_playerposition);
+ MSG_WriteFloat(msg, org[0]);
+ MSG_WriteFloat(msg, org[1]);
+ MSG_WriteFloat(msg, org[2]);
+ }
+ */
+ MSG_WriteByte(msg, svc_entitiesbegin);
+ MSG_WriteShort(msg, 1);
- clentnum = NUM_FOR_EDICT(clent); // LordHavoc: for comparison purposes
+ clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
// send over all entities (except the client) that touch the pvs
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
colormod = 255;
effects = ent->v.effects;
- if (val = GETEDICTFIELDVALUE(ent, eval_alpha))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
if ((alpha = (int) (val->_float * 255.0)) == 0)
alpha = 255;
- if (val = GETEDICTFIELDVALUE(ent, eval_renderamt)) // HalfLife support
- alpha -= (int) val->_float;
+ if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)) && val->_float != 0) // HalfLife support
+ alpha = (int) val->_float;
if (alpha < 0) alpha = 0;
if (alpha > 255) alpha = 255;
- if (val = GETEDICTFIELDVALUE(ent, eval_glow_size))
- glowsize = (int) val->_float >> 3;
- if (glowsize > 127) glowsize = 127;
- if (glowsize < -128) glowsize = -128;
+ if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size)))
+ glowsize = (int) val->_float >> 2;
+ if (glowsize > 255) glowsize = 255;
+ if (glowsize < 0) glowsize = 0;
- if (val = GETEDICTFIELDVALUE(ent, eval_scale))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
if (scale < 0) scale = 0;
if (scale > 255) scale = 255;
- if (val = GETEDICTFIELDVALUE(ent, eval_glow_trail))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail)))
if (val->_float != 0)
bits |= U_GLOWTRAIL;
- if (val = GETEDICTFIELDVALUE(ent, eval_glow_color))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color)))
if (val->_float != 0)
glowcolor = (int) val->_float;
- if (val = GETEDICTFIELDVALUE(ent, eval_fullbright))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright)))
if (val->_float != 0)
effects |= EF_FULLBRIGHT;
- if (val = GETEDICTFIELDVALUE(ent, eval_colormod))
+ if ((val = GETEDICTFIELDVALUE(ent, eval_colormod)))
if (val->vector[0] != 0 || val->vector[1] != 0 || val->vector[2] != 0)
{
modred = val->vector[0] * 8.0;if (modred < 0) modred = 0;if (modred > 7) modred = 7;
// send an update
bits = 0;
- dodelta = FALSE;
+ dodelta = false;
if ((int)ent->v.effects & EF_DELTA)
- dodelta = cl.time < ent->nextfullupdate; // every half second a full update is forced
+ dodelta = realtime < client->nextfullupdate[e]; // every half second a full update is forced
if (dodelta)
{
}
else
{
- ent->nextfullupdate = cl.time + 0.5;
+ client->nextfullupdate[e] = realtime + 0.5;
baseline = &ent->baseline;
}
angles[0] = angles[0] * movelerp + ent->stepoldangles[0];
angles[1] = angles[1] * movelerp + ent->stepoldangles[1];
angles[2] = angles[2] * movelerp + ent->stepoldangles[2];
+ VectorMA(origin, host_client->latency, ent->v.velocity, origin);
}
else // copy as they are
{
- VectorCopy(ent->v.origin, origin);
+// VectorCopy(ent->v.origin, origin);
VectorCopy(ent->v.angles, angles);
+ VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin);
if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
{
// update lerp positions
}
// LordHavoc: old stuff, but rewritten to have more exact tolerances
- if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1;
- if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2;
- if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3;
+// if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1;
+// if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2;
+// if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3;
+ if (origin[0] != baseline->origin[0]) bits |= U_ORIGIN1;
+ if (origin[1] != baseline->origin[1]) bits |= U_ORIGIN2;
+ if (origin[2] != baseline->origin[2]) bits |= U_ORIGIN3;
if ((int)(angles[0]*(256.0/360.0)) != (int)(baseline->angles[0]*(256.0/360.0))) bits |= U_ANGLE1;
if ((int)(angles[1]*(256.0/360.0)) != (int)(baseline->angles[1]*(256.0/360.0))) bits |= U_ANGLE2;
if ((int)(angles[2]*(256.0/360.0)) != (int)(baseline->angles[2]*(256.0/360.0))) bits |= U_ANGLE3;
- if (baseline->colormap != (int) ent->v.colormap) bits |= U_COLORMAP;
- if (baseline->skin != (int) ent->v.skin) bits |= U_SKIN;
+ if (baseline->colormap != (byte) ent->v.colormap) bits |= U_COLORMAP;
+ if (baseline->skin != (byte) ent->v.skin) bits |= U_SKIN;
if ((baseline->frame & 0x00FF) != ((int) ent->v.frame & 0x00FF)) bits |= U_FRAME;
if ((baseline->effects & 0x00FF) != ((int) ent->v.effects & 0x00FF)) bits |= U_EFFECTS;
- if (baseline->modelindex != (int) ent->v.modelindex) bits |= U_MODEL;
+ if (baseline->modelindex != (byte) ent->v.modelindex) bits |= U_MODEL;
// LordHavoc: new stuff
if (baseline->alpha != alpha) bits |= U_ALPHA;
if (baseline->glowcolor != glowcolor) bits |= U_GLOWCOLOR;
if (baseline->colormod != colormod) bits |= U_COLORMOD;
if (((int) baseline->frame & 0xFF00) != ((int) ent->v.frame & 0xFF00)) bits |= U_FRAME2;
+ if (((int) baseline->frame & 0xFF00) != ((int) ent->v.modelindex & 0xFF00)) bits |= U_MODEL2;
// update delta baseline
VectorCopy(ent->v.origin, ent->deltabaseline.origin);
if (bits & U_COLORMAP) MSG_WriteByte (msg, ent->v.colormap);
if (bits & U_SKIN) MSG_WriteByte (msg, ent->v.skin);
if (bits & U_EFFECTS) MSG_WriteByte (msg, ent->v.effects);
- if (bits & U_ORIGIN1) MSG_WriteCoord (msg, origin[0]);
+ if (bits & U_ORIGIN1) MSG_WriteFloatCoord (msg, origin[0]);
if (bits & U_ANGLE1) MSG_WriteAngle(msg, angles[0]);
- if (bits & U_ORIGIN2) MSG_WriteCoord (msg, origin[1]);
+ if (bits & U_ORIGIN2) MSG_WriteFloatCoord (msg, origin[1]);
if (bits & U_ANGLE2) MSG_WriteAngle(msg, angles[1]);
- if (bits & U_ORIGIN3) MSG_WriteCoord (msg, origin[2]);
+ if (bits & U_ORIGIN3) MSG_WriteFloatCoord (msg, origin[2]);
if (bits & U_ANGLE3) MSG_WriteAngle(msg, angles[2]);
// LordHavoc: new stuff
if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
if (bits & U_COLORMOD) MSG_WriteByte(msg, colormod);
if (bits & U_FRAME2) MSG_WriteByte(msg, (int)ent->v.frame >> 8);
+ if (bits & U_MODEL2) MSG_WriteByte(msg, (int)ent->v.modelindex >> 8);
}
+
+ MSG_WriteByte(msg, svc_entitiesend);
+ MSG_WriteShort(msg, MAX_EDICTS);
}
/*
edict_t *other;
int items;
eval_t *val;
+ vec3_t punchvector;
//
// send a damage message
MSG_WriteByte (msg, ent->v.dmg_save);
MSG_WriteByte (msg, ent->v.dmg_take);
for (i=0 ; i<3 ; i++)
- MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
+ MSG_WriteFloatCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
ent->v.dmg_take = 0;
ent->v.dmg_save = 0;
if ( ent->v.waterlevel >= 2)
bits |= SU_INWATER;
+ // dpprotocol
+ VectorClear(punchvector);
+ if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
+ VectorCopy(val->vector, punchvector);
+
for (i=0 ; i<3 ; i++)
{
if (ent->v.punchangle[i])
bits |= (SU_PUNCH1<<i);
+ if (punchvector[i]) // dpprotocol
+ bits |= (SU_PUNCHVEC1<<i); // dpprotocol
if (ent->v.velocity[i])
bits |= (SU_VELOCITY1<<i);
}
// if (ent->v.weapon)
bits |= SU_WEAPON;
+ if (bits >= 65536)
+ bits |= SU_EXTEND1;
+ if (bits >= 16777216)
+ bits |= SU_EXTEND2;
+
// send the data
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteShort (msg, bits);
+ if (bits & SU_EXTEND1)
+ MSG_WriteByte(msg, bits >> 16);
+ if (bits & SU_EXTEND2)
+ MSG_WriteByte(msg, bits >> 24);
if (bits & SU_VIEWHEIGHT)
MSG_WriteChar (msg, ent->v.view_ofs[2]);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
- MSG_WriteChar (msg, ent->v.punchangle[i]);
+ MSG_WritePreciseAngle(msg, ent->v.punchangle[i]); // dpprotocol
+ if (bits & (SU_PUNCHVEC1<<i)) // dpprotocol
+ MSG_WriteFloatCoord(msg, punchvector[i]); // dpprotocol
if (bits & (SU_VELOCITY1<<i))
MSG_WriteChar (msg, ent->v.velocity[i]/16);
}
// add the client specific data to the datagram
SV_WriteClientdataToMessage (client->edict, &msg);
- SV_WriteEntitiesToClient (client->edict, &msg);
+ SV_WriteEntitiesToClient (client, client->edict, &msg);
// copy the server datagram if there is space
if (msg.cursize + sv.datagram.cursize < msg.maxsize)
SV_DropClient (false); // went to another level
else
{
- if (NET_SendMessage (host_client->netconnection
- , &host_client->message) == -1)
+ if (NET_SendMessage (host_client->netconnection, &host_client->message) == -1)
SV_DropClient (true); // if the message couldn't send, kick off
SZ_Clear (&host_client->message);
host_client->last_message = realtime;
if (!strcmp(sv.model_precache[i], name))
return i;
if (i==MAX_MODELS || !sv.model_precache[i])
- Sys_Error ("SV_ModelIndex: model %s not precached", name);
+ Host_Error ("SV_ModelIndex: model %s not precached", name);
return i;
}
MSG_WriteByte (&sv.signon, svent->baseline.skin);
for (i=0 ; i<3 ; i++)
{
- MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
+ MSG_WriteFloatCoord(&sv.signon, svent->baseline.origin[i]);
MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
}
}
// call the progs to get default spawn parms for the new client
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram (pr_global_struct->SetChangeParms);
+ 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];
}
sv.state = ss_active;
// run two frames to allow everything to settle
- host_frametime = 0.1;
+ sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
SV_Physics ();
SV_Physics ();
Con_DPrintf ("Server spawned.\n");
}
-
-// LordHavoc: added light checking to the server
-int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end);
-void SV_LightPoint (vec3_t color, vec3_t p)
-{
- vec3_t end;
-
- if (!sv.worldmodel->lightdata)
- {
- color[0] = color[1] = color[2] = 255;
- return;
- }
-
- end[0] = p[0];
- end[1] = p[1];
- end[2] = p[2] - 2048;
-
- color[0] = color[1] = color[2] = 0;
- RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
-}