sv_main.c
来自「quake1 dos源代码最新版本」· C语言 代码 · 共 1,327 行 · 第 1/3 页
C
1,327 行
pvs = Mod_LeafPVS ( (mleaf_t *)node, sv.worldmodel);
for (i=0 ; i<fatbytes ; i++)
fatpvs[i] |= pvs[i];
}
return;
}
plane = node->plane;
d = DotProduct (org, plane->normal) - plane->dist;
if (d > 8)
node = node->children[0];
else if (d < -8)
node = node->children[1];
else
{ // go down both
SV_AddToFatPVS (org, node->children[0]);
node = node->children[1];
}
}
}
/*
=============
SV_FatPVS
Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
given point.
=============
*/
byte *SV_FatPVS (vec3_t org)
{
fatbytes = (sv.worldmodel->numleafs+31)>>3;
Q_memset (fatpvs, 0, fatbytes);
SV_AddToFatPVS (org, sv.worldmodel->nodes);
return fatpvs;
}
//=============================================================================
/*
=============
SV_WriteEntitiesToClient
=============
*/
void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
{
int e, i;
int bits;
byte *pvs;
vec3_t org;
float miss;
edict_t *ent;
// find the client's PVS
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
pvs = SV_FatPVS (org);
// send over all entities (excpet the client) that touch the pvs
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
{
#ifdef QUAKE2
// don't send if flagged for NODRAW and there are no lighting effects
if (ent->v.effects == EF_NODRAW)
continue;
#endif
// ignore if not touching a PV leaf
if (ent != clent) // clent is always sent
{
// ignore ents without visible models
if (!ent->v.modelindex || !pr_strings[ent->v.model])
continue;
for (i=0 ; i < ent->num_leafs ; i++)
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
break;
if (i == ent->num_leafs)
continue; // not visible
}
if (msg->maxsize - msg->cursize < 16)
{
Con_Printf ("packet overflow\n");
return;
}
// send an update
bits = 0;
for (i=0 ; i<3 ; i++)
{
miss = ent->v.origin[i] - ent->baseline.origin[i];
if ( miss < -0.1 || miss > 0.1 )
bits |= U_ORIGIN1<<i;
}
if ( ent->v.angles[0] != ent->baseline.angles[0] )
bits |= U_ANGLE1;
if ( ent->v.angles[1] != ent->baseline.angles[1] )
bits |= U_ANGLE2;
if ( ent->v.angles[2] != ent->baseline.angles[2] )
bits |= U_ANGLE3;
if (ent->v.movetype == MOVETYPE_STEP)
bits |= U_NOLERP; // don't mess up the step animation
if (ent->baseline.colormap != ent->v.colormap)
bits |= U_COLORMAP;
if (ent->baseline.skin != ent->v.skin)
bits |= U_SKIN;
if (ent->baseline.frame != ent->v.frame)
bits |= U_FRAME;
if (ent->baseline.effects != ent->v.effects)
bits |= U_EFFECTS;
if (ent->baseline.modelindex != ent->v.modelindex)
bits |= U_MODEL;
if (e >= 256)
bits |= U_LONGENTITY;
if (bits >= 256)
bits |= U_MOREBITS;
//
// write the message
//
MSG_WriteByte (msg,bits | U_SIGNAL);
if (bits & U_MOREBITS)
MSG_WriteByte (msg, bits>>8);
if (bits & U_LONGENTITY)
MSG_WriteShort (msg,e);
else
MSG_WriteByte (msg,e);
if (bits & U_MODEL)
MSG_WriteByte (msg, ent->v.modelindex);
if (bits & U_FRAME)
MSG_WriteByte (msg, ent->v.frame);
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, ent->v.origin[0]);
if (bits & U_ANGLE1)
MSG_WriteAngle(msg, ent->v.angles[0]);
if (bits & U_ORIGIN2)
MSG_WriteCoord (msg, ent->v.origin[1]);
if (bits & U_ANGLE2)
MSG_WriteAngle(msg, ent->v.angles[1]);
if (bits & U_ORIGIN3)
MSG_WriteCoord (msg, ent->v.origin[2]);
if (bits & U_ANGLE3)
MSG_WriteAngle(msg, ent->v.angles[2]);
}
}
/*
=============
SV_CleanupEnts
=============
*/
void SV_CleanupEnts (void)
{
int e;
edict_t *ent;
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
{
ent->v.effects = (int)ent->v.effects & ~EF_MUZZLEFLASH;
}
}
/*
==================
SV_WriteClientdataToMessage
==================
*/
void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
{
int bits;
int i;
edict_t *other;
int items;
#ifndef QUAKE2
eval_t *val;
#endif
//
// send a damage message
//
if (ent->v.dmg_take || ent->v.dmg_save)
{
other = PROG_TO_EDICT(ent->v.dmg_inflictor);
MSG_WriteByte (msg, svc_damage);
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]));
ent->v.dmg_take = 0;
ent->v.dmg_save = 0;
}
//
// send the current viewpos offset from the view entity
//
SV_SetIdealPitch (); // how much to look up / down ideally
// a fixangle might get lost in a dropped packet. Oh well.
if ( ent->v.fixangle )
{
// 2000-05-02 NVS SVC_setangle by Maddes start
// MSG_WriteByte (msg, svc_setangle);
NVS_InitSVCMsg(MSG_ONE, svc_setangle, 0, host_client);
NVS_WriteByte (MSG_ONE, svc_setangle, msg);
// 2000-05-02 NVS SVC_setangle by Maddes end
for (i=0 ; i < 3 ; i++)
// 2000-05-02 NVS SVC_setangle by Maddes start
// MSG_WriteAngle (msg, ent->v.angles[i] );
{
NVS_WriteAngle (MSG_ONE, ent->v.angles[i], msg);
}
if (nvs_current_ssvc->value >= 0.50)
{
for (i=0 ; i < 3 ; i++)
{
NVS_WriteFloat (MSG_ONE, ent->v.angles[i], msg);
}
}
// 2000-05-02 NVS SVC_setangle by Maddes end
ent->v.fixangle = 0;
}
bits = 0;
if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
bits |= SU_VIEWHEIGHT;
if (ent->v.idealpitch)
bits |= SU_IDEALPITCH;
// stuff the sigil bits into the high bits of items for sbar, or else
// mix in items2
#ifdef QUAKE2
items = (int)ent->v.items | ((int)ent->v.items2 << 23);
#else
// 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes start
// val = GetEdictFieldValue(ent, "items2");
val = GETEDICTFIELDVALUE(ent, pr_field_items2);
// 2001-11-15 Better GetEdictFieldValue performance by LordHavoc/Maddes end
if (val)
items = (int)ent->v.items | ((int)val->_float << 23);
else
items = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
#endif
bits |= SU_ITEMS;
if ( (int)ent->v.flags & FL_ONGROUND)
bits |= SU_ONGROUND;
if ( ent->v.waterlevel >= 2)
bits |= SU_INWATER;
for (i=0 ; i<3 ; i++)
{
if (ent->v.punchangle[i])
bits |= (SU_PUNCH1<<i);
if (ent->v.velocity[i])
bits |= (SU_VELOCITY1<<i);
}
if (ent->v.weaponframe)
bits |= SU_WEAPONFRAME;
if (ent->v.armorvalue)
bits |= SU_ARMOR;
// if (ent->v.weapon)
bits |= SU_WEAPON;
// send the data
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteShort (msg, bits);
if (bits & SU_VIEWHEIGHT)
MSG_WriteChar (msg, ent->v.view_ofs[2]);
if (bits & SU_IDEALPITCH)
MSG_WriteChar (msg, ent->v.idealpitch);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
MSG_WriteChar (msg, ent->v.punchangle[i]);
if (bits & (SU_VELOCITY1<<i))
MSG_WriteChar (msg, ent->v.velocity[i]/16);
}
// [always sent] if (bits & SU_ITEMS)
MSG_WriteLong (msg, items);
if (bits & SU_WEAPONFRAME)
MSG_WriteByte (msg, ent->v.weaponframe);
if (bits & SU_ARMOR)
MSG_WriteByte (msg, ent->v.armorvalue);
if (bits & SU_WEAPON)
MSG_WriteByte (msg, SV_ModelIndex(pr_strings+ent->v.weaponmodel));
MSG_WriteShort (msg, ent->v.health);
MSG_WriteByte (msg, ent->v.currentammo);
MSG_WriteByte (msg, ent->v.ammo_shells);
MSG_WriteByte (msg, ent->v.ammo_nails);
MSG_WriteByte (msg, ent->v.ammo_rockets);
MSG_WriteByte (msg, ent->v.ammo_cells);
if (standard_quake)
{
MSG_WriteByte (msg, ent->v.weapon);
}
else
{
for(i=0;i<32;i++)
{
if ( ((int)ent->v.weapon) & (1<<i) )
{
MSG_WriteByte (msg, i);
break;
}
}
}
}
/*
=======================
SV_SendClientDatagram
=======================
*/
qboolean SV_SendClientDatagram (client_t *client)
{
byte buf[MAX_DATAGRAM];
sizebuf_t msg;
msg.data = buf;
msg.maxsize = sizeof(buf);
msg.cursize = 0;
MSG_WriteByte (&msg, svc_time);
MSG_WriteFloat (&msg, sv.time);
// add the client specific data to the datagram
SV_WriteClientdataToMessage (client->edict, &msg);
SV_WriteEntitiesToClient (client->edict, &msg);
// copy the server datagram if there is space
// 2000-05-02 NVS SVC by Maddes start
if (msg.cursize + client->datagram.cursize < msg.maxsize)
SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
// 2000-05-02 NVS SVC by Maddes end
if (msg.cursize + sv.datagram.cursize < msg.maxsize)
SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
// send the datagram
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
{
SV_DropClient (true);// if the message couldn't send, kick off
return false;
}
return true;
}
/*
=======================
SV_UpdateToReliableMessages
=======================
*/
void SV_UpdateToReliableMessages (void)
{
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 != host_client->edict->v.frags)
{
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
{
if (!client->active)
continue;
MSG_WriteByte (&client->message, svc_updatefrags);
MSG_WriteByte (&client->message, i);
MSG_WriteShort (&client->message, host_client->edict->v.frags);
}
host_client->old_frags = host_client->edict->v.frags;
}
}
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
{
if (!client->active)
continue;
SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
}
SZ_Clear (&sv.reliable_datagram);
}
/*
=======================
SV_SendNop
Send a nop message without trashing or sending the accumulated client
message buffer
=======================
*/
void SV_SendNop (client_t *client)
{
sizebuf_t msg;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?