]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_entframe.c
(Round 1) Break up protocol.c
[xonotic/darkplaces.git] / cl_entframe.c
1 #include "quakedef.h"
2 #include "protocol.h"
3
4 // (client) adds a entity_frame to the database, for future reference
5 void EntityFrame_AddFrame_Client(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata)
6 {
7         int n, e;
8         entity_frameinfo_t *info;
9
10         VectorCopy(eye, d->eye);
11
12         // figure out how many entity slots are used already
13         if (d->numframes)
14         {
15                 n = d->frames[d->numframes - 1].endentity - d->frames[0].firstentity;
16                 if (n + numentities > MAX_ENTITY_DATABASE || d->numframes >= MAX_ENTITY_HISTORY)
17                 {
18                         // ran out of room, dump database
19                         EntityFrame_ClearDatabase(d);
20                 }
21         }
22
23         info = &d->frames[d->numframes];
24         info->framenum = framenum;
25         e = -1000;
26         // make sure we check the newly added frame as well, but we haven't incremented numframes yet
27         for (n = 0;n <= d->numframes;n++)
28         {
29                 if (e >= d->frames[n].framenum)
30                 {
31                         if (e == framenum)
32                                 Con_Print("EntityFrame_AddFrame: tried to add out of sequence frame to database\n");
33                         else
34                                 Con_Print("EntityFrame_AddFrame: out of sequence frames in database\n");
35                         return;
36                 }
37                 e = d->frames[n].framenum;
38         }
39         // if database still has frames after that...
40         if (d->numframes)
41                 info->firstentity = d->frames[d->numframes - 1].endentity;
42         else
43                 info->firstentity = 0;
44         info->endentity = info->firstentity + numentities;
45         d->numframes++;
46
47         n = info->firstentity % MAX_ENTITY_DATABASE;
48         e = MAX_ENTITY_DATABASE - n;
49         if (e > numentities)
50                 e = numentities;
51         memcpy(d->entitydata + n, entitydata, sizeof(entity_state_t) * e);
52         if (numentities > e)
53                 memcpy(d->entitydata, entitydata + e, sizeof(entity_state_t) * (numentities - e));
54 }
55
56 // (client) reads a frame from network stream
57 void EntityFrame_CL_ReadFrame(void)
58 {
59         int i, number, removed;
60         entity_frame_t *f, *delta;
61         entity_state_t *e, *old, *oldend;
62         entity_t *ent;
63         entityframe_database_t *d;
64         if (!cl.entitydatabase)
65                 cl.entitydatabase = EntityFrame_AllocDatabase(cls.levelmempool);
66         d = cl.entitydatabase;
67         f = &d->framedata;
68         delta = &d->deltaframe;
69
70         EntityFrame_Clear(f, NULL, -1);
71
72         // read the frame header info
73         f->time = cl.mtime[0];
74         number = MSG_ReadLong(&cl_message);
75         f->framenum = MSG_ReadLong(&cl_message);
76         CL_NewFrameReceived(f->framenum);
77         f->eye[0] = MSG_ReadFloat(&cl_message);
78         f->eye[1] = MSG_ReadFloat(&cl_message);
79         f->eye[2] = MSG_ReadFloat(&cl_message);
80         EntityFrame_AckFrame(d, number);
81         EntityFrame_FetchFrame(d, number, delta);
82         old = delta->entitydata;
83         oldend = old + delta->numentities;
84         // read entities until we hit the magic 0xFFFF end tag
85         while ((number = (unsigned short) MSG_ReadShort(&cl_message)) != 0xFFFF && !cl_message.badread)
86         {
87                 if (cl_message.badread)
88                         Host_Error("EntityFrame_Read: read error");
89                 removed = number & 0x8000;
90                 number &= 0x7FFF;
91                 if (number >= MAX_EDICTS)
92                         Host_Error("EntityFrame_Read: number (%i) >= MAX_EDICTS (%i)", number, MAX_EDICTS);
93
94                 // seek to entity, while copying any skipped entities (assume unchanged)
95                 while (old < oldend && old->number < number)
96                 {
97                         if (f->numentities >= MAX_ENTITY_DATABASE)
98                                 Host_Error("EntityFrame_Read: entity list too big");
99                         f->entitydata[f->numentities] = *old++;
100                         f->entitydata[f->numentities++].time = cl.mtime[0];
101                 }
102                 if (removed)
103                 {
104                         if (old < oldend && old->number == number)
105                                 old++;
106                         else
107                                 Con_Printf("EntityFrame_Read: REMOVE on unused entity %i\n", number);
108                 }
109                 else
110                 {
111                         if (f->numentities >= MAX_ENTITY_DATABASE)
112                                 Host_Error("EntityFrame_Read: entity list too big");
113
114                         // reserve this slot
115                         e = f->entitydata + f->numentities++;
116
117                         if (old < oldend && old->number == number)
118                         {
119                                 // delta from old entity
120                                 *e = *old++;
121                         }
122                         else
123                         {
124                                 // delta from defaults
125                                 *e = defaultstate;
126                         }
127
128                         if (cl.num_entities <= number)
129                         {
130                                 cl.num_entities = number + 1;
131                                 if (number >= cl.max_entities)
132                                         CL_ExpandEntities(number);
133                         }
134                         cl.entities_active[number] = true;
135                         e->active = ACTIVE_NETWORK;
136                         e->time = cl.mtime[0];
137                         e->number = number;
138                         EntityState_ReadFields(e, EntityState_ReadExtendBits());
139                 }
140         }
141         while (old < oldend)
142         {
143                 if (f->numentities >= MAX_ENTITY_DATABASE)
144                         Host_Error("EntityFrame_Read: entity list too big");
145                 f->entitydata[f->numentities] = *old++;
146                 f->entitydata[f->numentities++].time = cl.mtime[0];
147         }
148         EntityFrame_AddFrame_Client(d, f->eye, f->framenum, f->numentities, f->entitydata);
149
150         memset(cl.entities_active, 0, cl.num_entities * sizeof(unsigned char));
151         number = 1;
152         for (i = 0;i < f->numentities;i++)
153         {
154                 for (;number < f->entitydata[i].number && number < cl.num_entities;number++)
155                 {
156                         if (cl.entities_active[number])
157                         {
158                                 cl.entities_active[number] = false;
159                                 cl.entities[number].state_current.active = ACTIVE_NOT;
160                         }
161                 }
162                 if (number >= cl.num_entities)
163                         break;
164                 // update the entity
165                 ent = &cl.entities[number];
166                 ent->state_previous = ent->state_current;
167                 ent->state_current = f->entitydata[i];
168                 CL_MoveLerpEntityStates(ent);
169                 // the entity lives again...
170                 cl.entities_active[number] = true;
171                 number++;
172         }
173         for (;number < cl.num_entities;number++)
174         {
175                 if (cl.entities_active[number])
176                 {
177                         cl.entities_active[number] = false;
178                         cl.entities[number].state_current.active = ACTIVE_NOT;
179                 }
180         }
181 }
182
183
184 // (client) returns the frame number of the most recent frame recieved
185 int EntityFrame_MostRecentlyRecievedFrameNum(entityframe_database_t *d)
186 {
187         if (d->numframes)
188                 return d->frames[d->numframes - 1].framenum;
189         else
190                 return -1;
191 }