-
Notifications
You must be signed in to change notification settings - Fork 41
/
cl_ents4.c
135 lines (134 loc) · 4.59 KB
/
cl_ents4.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "quakedef.h"
#include "protocol.h"
void EntityFrame4_CL_ReadFrame(void)
{
int i, n, cnumber, referenceframenum, framenum, enumber, done, stopnumber, skip = false;
entity_state_t *s;
entityframe4_database_t *d;
if (!cl.entitydatabase4)
cl.entitydatabase4 = EntityFrame4_AllocDatabase(cls.levelmempool);
d = cl.entitydatabase4;
// read the number of the frame this refers to
referenceframenum = MSG_ReadLong(&cl_message);
// read the number of this frame
framenum = MSG_ReadLong(&cl_message);
CL_NewFrameReceived(framenum);
// read the start number
enumber = (unsigned short) MSG_ReadShort(&cl_message);
if (developer_networkentities.integer >= 10)
{
Con_Printf("recv svc_entities num:%i ref:%i database: ref:%i commits:", framenum, referenceframenum, d->referenceframenum);
for (i = 0;i < MAX_ENTITY_HISTORY;i++)
if (d->commit[i].numentities)
Con_Printf(" %i", d->commit[i].framenum);
Con_Print("\n");
}
if (!EntityFrame4_AckFrame(d, referenceframenum, false))
{
Con_Print("EntityFrame4_CL_ReadFrame: reference frame invalid (VERY BAD ERROR), this update will be skipped\n");
skip = true;
}
d->currentcommit = NULL;
for (i = 0;i < MAX_ENTITY_HISTORY;i++)
{
if (!d->commit[i].numentities)
{
d->currentcommit = d->commit + i;
d->currentcommit->framenum = framenum;
d->currentcommit->numentities = 0;
}
}
if (d->currentcommit == NULL)
{
Con_Printf("EntityFrame4_CL_ReadFrame: error while decoding frame %i: database full, reading but not storing this update\n", framenum);
skip = true;
}
done = false;
while (!done && !cl_message.badread)
{
// read the number of the modified entity
// (gaps will be copied unmodified)
n = (unsigned short)MSG_ReadShort(&cl_message);
if (n == 0x8000)
{
// no more entities in this update, but we still need to copy the
// rest of the reference entities (final gap)
done = true;
// read end of range number, then process normally
n = (unsigned short)MSG_ReadShort(&cl_message);
}
// high bit means it's a remove message
cnumber = n & 0x7FFF;
// if this is a live entity we may need to expand the array
if (cl.num_entities <= cnumber && !(n & 0x8000))
{
cl.num_entities = cnumber + 1;
if (cnumber >= cl.max_entities)
CL_ExpandEntities(cnumber);
}
// add one (the changed one) if not done
stopnumber = cnumber + !done;
// process entities in range from the last one to the changed one
for (;enumber < stopnumber;enumber++)
{
if (skip || enumber >= cl.num_entities)
{
if (enumber == cnumber && (n & 0x8000) == 0)
{
entity_state_t tempstate;
EntityState_ReadFields(&tempstate, EntityState_ReadExtendBits());
}
continue;
}
// slide the current into the previous slot
cl.entities[enumber].state_previous = cl.entities[enumber].state_current;
// copy a new current from reference database
cl.entities[enumber].state_current = *EntityFrame4_GetReferenceEntity(d, enumber);
s = &cl.entities[enumber].state_current;
// if this is the one to modify, read more data...
if (enumber == cnumber)
{
if (n & 0x8000)
{
// simply removed
if (developer_networkentities.integer >= 2)
Con_Printf("entity %i: remove\n", enumber);
*s = defaultstate;
}
else
{
// read the changes
if (developer_networkentities.integer >= 2)
Con_Printf("entity %i: update\n", enumber);
s->active = ACTIVE_NETWORK;
EntityState_ReadFields(s, EntityState_ReadExtendBits());
}
}
else if (developer_networkentities.integer >= 4)
Con_Printf("entity %i: copy\n", enumber);
// set the cl.entities_active flag
cl.entities_active[enumber] = (s->active == ACTIVE_NETWORK);
// set the update time
s->time = cl.mtime[0];
// fix the number (it gets wiped occasionally by copying from defaultstate)
s->number = enumber;
// check if we need to update the lerp stuff
if (s->active == ACTIVE_NETWORK)
CL_MoveLerpEntityStates(&cl.entities[enumber]);
// add this to the commit entry whether it is modified or not
if (d->currentcommit)
EntityFrame4_AddCommitEntity(d, &cl.entities[enumber].state_current);
// print extra messages if desired
if (developer_networkentities.integer >= 2 && cl.entities[enumber].state_current.active != cl.entities[enumber].state_previous.active)
{
if (cl.entities[enumber].state_current.active == ACTIVE_NETWORK)
Con_Printf("entity #%i has become active\n", enumber);
else if (cl.entities[enumber].state_previous.active)
Con_Printf("entity #%i has become inactive\n", enumber);
}
}
}
d->currentcommit = NULL;
if (skip)
EntityFrame4_ResetDatabase(d);
}