📄 cl_ents.c
字号:
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_ents.c -- entity parsing and management
#include "client.h"
extern struct model_s *cl_mod_powerscreen;
//PGM
int vidref_val;
//PGM
/*
=========================================================================
FRAME PARSING
=========================================================================
*/
#if 0
typedef struct
{
int modelindex;
int num; // entity number
int effects;
vec3_t origin;
vec3_t oldorigin;
vec3_t angles;
qboolean present;
} projectile_t;
#define MAX_PROJECTILES 64
projectile_t cl_projectiles[MAX_PROJECTILES];
void CL_ClearProjectiles (void)
{
int i;
for (i = 0; i < MAX_PROJECTILES; i++) {
// if (cl_projectiles[i].present)
// Com_DPrintf("PROJ: %d CLEARED\n", cl_projectiles[i].num);
cl_projectiles[i].present = false;
}
}
/*
=====================
CL_ParseProjectiles
Flechettes are passed as efficient temporary entities
=====================
*/
void CL_ParseProjectiles (void)
{
int i, c, j;
byte bits[8];
byte b;
projectile_t pr;
int lastempty = -1;
qboolean old = false;
c = MSG_ReadByte (&net_message);
for (i=0 ; i<c ; i++)
{
bits[0] = MSG_ReadByte (&net_message);
bits[1] = MSG_ReadByte (&net_message);
bits[2] = MSG_ReadByte (&net_message);
bits[3] = MSG_ReadByte (&net_message);
bits[4] = MSG_ReadByte (&net_message);
pr.origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
pr.origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
pr.origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
VectorCopy(pr.origin, pr.oldorigin);
if (bits[4] & 64)
pr.effects = EF_BLASTER;
else
pr.effects = 0;
if (bits[4] & 128) {
old = true;
bits[0] = MSG_ReadByte (&net_message);
bits[1] = MSG_ReadByte (&net_message);
bits[2] = MSG_ReadByte (&net_message);
bits[3] = MSG_ReadByte (&net_message);
bits[4] = MSG_ReadByte (&net_message);
pr.oldorigin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
pr.oldorigin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
pr.oldorigin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
}
bits[0] = MSG_ReadByte (&net_message);
bits[1] = MSG_ReadByte (&net_message);
bits[2] = MSG_ReadByte (&net_message);
pr.angles[0] = 360*bits[0]/256;
pr.angles[1] = 360*bits[1]/256;
pr.modelindex = bits[2];
b = MSG_ReadByte (&net_message);
pr.num = (b & 0x7f);
if (b & 128) // extra entity number byte
pr.num |= (MSG_ReadByte (&net_message) << 7);
pr.present = true;
// find if this projectile already exists from previous frame
for (j = 0; j < MAX_PROJECTILES; j++) {
if (cl_projectiles[j].modelindex) {
if (cl_projectiles[j].num == pr.num) {
// already present, set up oldorigin for interpolation
if (!old)
VectorCopy(cl_projectiles[j].origin, pr.oldorigin);
cl_projectiles[j] = pr;
break;
}
} else
lastempty = j;
}
// not present previous frame, add it
if (j == MAX_PROJECTILES) {
if (lastempty != -1) {
cl_projectiles[lastempty] = pr;
}
}
}
}
/*
=============
CL_LinkProjectiles
=============
*/
void CL_AddProjectiles (void)
{
int i, j;
projectile_t *pr;
entity_t ent;
memset (&ent, 0, sizeof(ent));
for (i=0, pr=cl_projectiles ; i < MAX_PROJECTILES ; i++, pr++)
{
// grab an entity to fill in
if (pr->modelindex < 1)
continue;
if (!pr->present) {
pr->modelindex = 0;
continue; // not present this frame (it was in the previous frame)
}
ent.model = cl.model_draw[pr->modelindex];
// interpolate origin
for (j=0 ; j<3 ; j++)
{
ent.origin[j] = ent.oldorigin[j] = pr->oldorigin[j] + cl.lerpfrac *
(pr->origin[j] - pr->oldorigin[j]);
}
if (pr->effects & EF_BLASTER)
CL_BlasterTrail (pr->oldorigin, ent.origin);
V_AddLight (pr->origin, 200, 1, 1, 0);
VectorCopy (pr->angles, ent.angles);
V_AddEntity (&ent);
}
}
#endif
/*
=================
CL_ParseEntityBits
Returns the entity number and the header bits
=================
*/
int bitcounts[32]; /// just for protocol profiling
int CL_ParseEntityBits (unsigned *bits)
{
unsigned b, total;
int i;
int number;
total = MSG_ReadByte (&net_message);
if (total & U_MOREBITS1)
{
b = MSG_ReadByte (&net_message);
total |= b<<8;
}
if (total & U_MOREBITS2)
{
b = MSG_ReadByte (&net_message);
total |= b<<16;
}
if (total & U_MOREBITS3)
{
b = MSG_ReadByte (&net_message);
total |= b<<24;
}
// count the bits for net profiling
for (i=0 ; i<32 ; i++)
if (total&(1<<i))
bitcounts[i]++;
if (total & U_NUMBER16)
number = MSG_ReadShort (&net_message);
else
number = MSG_ReadByte (&net_message);
*bits = total;
return number;
}
/*
==================
CL_ParseDelta
Can go from either a baseline or a previous packet_entity
==================
*/
void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
{
// set everything to the state we are delta'ing from
*to = *from;
VectorCopy (from->origin, to->old_origin);
to->number = number;
if (bits & U_MODEL)
to->modelindex = MSG_ReadByte (&net_message);
if (bits & U_MODEL2)
to->modelindex2 = MSG_ReadByte (&net_message);
if (bits & U_MODEL3)
to->modelindex3 = MSG_ReadByte (&net_message);
if (bits & U_MODEL4)
to->modelindex4 = MSG_ReadByte (&net_message);
if (bits & U_FRAME8)
to->frame = MSG_ReadByte (&net_message);
if (bits & U_FRAME16)
to->frame = MSG_ReadShort (&net_message);
if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors
to->skinnum = MSG_ReadLong(&net_message);
else if (bits & U_SKIN8)
to->skinnum = MSG_ReadByte(&net_message);
else if (bits & U_SKIN16)
to->skinnum = MSG_ReadShort(&net_message);
if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
to->effects = MSG_ReadLong(&net_message);
else if (bits & U_EFFECTS8)
to->effects = MSG_ReadByte(&net_message);
else if (bits & U_EFFECTS16)
to->effects = MSG_ReadShort(&net_message);
if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
to->renderfx = MSG_ReadLong(&net_message);
else if (bits & U_RENDERFX8)
to->renderfx = MSG_ReadByte(&net_message);
else if (bits & U_RENDERFX16)
to->renderfx = MSG_ReadShort(&net_message);
if (bits & U_ORIGIN1)
to->origin[0] = MSG_ReadCoord (&net_message);
if (bits & U_ORIGIN2)
to->origin[1] = MSG_ReadCoord (&net_message);
if (bits & U_ORIGIN3)
to->origin[2] = MSG_ReadCoord (&net_message);
if (bits & U_ANGLE1)
to->angles[0] = MSG_ReadAngle(&net_message);
if (bits & U_ANGLE2)
to->angles[1] = MSG_ReadAngle(&net_message);
if (bits & U_ANGLE3)
to->angles[2] = MSG_ReadAngle(&net_message);
if (bits & U_OLDORIGIN)
MSG_ReadPos (&net_message, to->old_origin);
if (bits & U_SOUND)
to->sound = MSG_ReadByte (&net_message);
if (bits & U_EVENT)
to->event = MSG_ReadByte (&net_message);
else
to->event = 0;
if (bits & U_SOLID)
to->solid = MSG_ReadShort (&net_message);
}
/*
==================
CL_DeltaEntity
Parses deltas from the given base and adds the resulting entity
to the current frame
==================
*/
void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits)
{
centity_t *ent;
entity_state_t *state;
ent = &cl_entities[newnum];
state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
cl.parse_entities++;
frame->num_entities++;
CL_ParseDelta (old, state, newnum, bits);
// some data changes will force no lerping
if (state->modelindex != ent->current.modelindex
|| state->modelindex2 != ent->current.modelindex2
|| state->modelindex3 != ent->current.modelindex3
|| state->modelindex4 != ent->current.modelindex4
|| abs(state->origin[0] - ent->current.origin[0]) > 512
|| abs(state->origin[1] - ent->current.origin[1]) > 512
|| abs(state->origin[2] - ent->current.origin[2]) > 512
|| state->event == EV_PLAYER_TELEPORT
|| state->event == EV_OTHER_TELEPORT
)
{
ent->serverframe = -99;
}
if (ent->serverframe != cl.frame.serverframe - 1)
{ // wasn't in last update, so initialize some things
ent->trailcount = 1024; // for diminishing rocket / grenade trails
// duplicate the current state so lerping doesn't hurt anything
ent->prev = *state;
if (state->event == EV_OTHER_TELEPORT)
{
VectorCopy (state->origin, ent->prev.origin);
VectorCopy (state->origin, ent->lerp_origin);
}
else
{
VectorCopy (state->old_origin, ent->prev.origin);
VectorCopy (state->old_origin, ent->lerp_origin);
}
}
else
{ // shuffle the last state to previous
ent->prev = ent->current;
}
ent->serverframe = cl.frame.serverframe;
ent->current = *state;
}
/*
==================
CL_ParsePacketEntities
An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
{
int newnum;
int bits;
entity_state_t *oldstate;
int oldindex, oldnum;
newframe->parse_entities = cl.parse_entities;
newframe->num_entities = 0;
// delta from the entities present in oldframe
oldindex = 0;
if (!oldframe)
oldnum = 99999;
else
{
if (oldindex >= oldframe->num_entities)
oldnum = 99999;
else
{
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
oldnum = oldstate->number;
}
}
while (1)
{
newnum = CL_ParseEntityBits (&bits);
if (newnum >= MAX_EDICTS)
Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);
if (net_message.readcount > net_message.cursize)
Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
if (!newnum)
break;
while (oldnum < newnum)
{ // one or more entities from the old packet are unchanged
if (cl_shownet->value == 3)
Com_Printf (" unchanged: %i\n", oldnum);
CL_DeltaEntity (newframe, oldnum, oldstate, 0);
oldindex++;
if (oldindex >= oldframe->num_entities)
oldnum = 99999;
else
{
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
oldnum = oldstate->number;
}
}
if (bits & U_REMOVE)
{ // the entity present in oldframe is not in the current frame
if (cl_shownet->value == 3)
Com_Printf (" remove: %i\n", newnum);
if (oldnum != newnum)
Com_Printf ("U_REMOVE: oldnum != newnum\n");
oldindex++;
if (oldindex >= oldframe->num_entities)
oldnum = 99999;
else
{
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
oldnum = oldstate->number;
}
continue;
}
if (oldnum == newnum)
{ // delta from previous state
if (cl_shownet->value == 3)
Com_Printf (" delta: %i\n", newnum);
CL_DeltaEntity (newframe, newnum, oldstate, bits);
oldindex++;
if (oldindex >= oldframe->num_entities)
oldnum = 99999;
else
{
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
oldnum = oldstate->number;
}
continue;
}
if (oldnum > newnum)
{ // delta from baseline
if (cl_shownet->value == 3)
Com_Printf (" baseline: %i\n", newnum);
CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
continue;
}
}
// any remaining entities in the old frame are copied over
while (oldnum != 99999)
{ // one or more entities from the old packet are unchanged
if (cl_shownet->value == 3)
Com_Printf (" unchanged: %i\n", oldnum);
CL_DeltaEntity (newframe, oldnum, oldstate, 0);
oldindex++;
if (oldindex >= oldframe->num_entities)
oldnum = 99999;
else
{
oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
oldnum = oldstate->number;
}
}
}
/*
===================
CL_ParsePlayerstate
===================
*/
void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -