]> git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_ents4.c
Fix a bug in Cvar_RegisterVirtual which was corrupting memory when adding a second...
[xonotic/darkplaces.git] / sv_ents4.c
1 #include "quakedef.h"
2 #include "protocol.h"
3
4 qbool EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t **states)
5 {
6         prvm_prog_t *prog = SVVM_prog;
7         const entity_state_t *e, *s;
8         entity_state_t inactiveentitystate;
9         int i, n, startnumber;
10         sizebuf_t buf;
11         unsigned char data[128];
12
13         // if there isn't enough space to accomplish anything, skip it
14         if (msg->cursize + 24 > maxsize)
15                 return false;
16
17         // prepare the buffer
18         memset(&buf, 0, sizeof(buf));
19         buf.data = data;
20         buf.maxsize = sizeof(data);
21
22         for (i = 0;i < MAX_ENTITY_HISTORY;i++)
23                 if (!d->commit[i].numentities)
24                         break;
25         // if commit buffer full, just don't bother writing an update this frame
26         if (i == MAX_ENTITY_HISTORY)
27                 return false;
28         d->currentcommit = d->commit + i;
29
30         // this state's number gets played around with later
31         inactiveentitystate = defaultstate;
32
33         d->currentcommit->numentities = 0;
34         d->currentcommit->framenum = ++d->latestframenumber;
35         MSG_WriteByte(msg, svc_entities);
36         MSG_WriteLong(msg, d->referenceframenum);
37         MSG_WriteLong(msg, d->currentcommit->framenum);
38         if (developer_networkentities.integer >= 10)
39         {
40                 Con_Printf("send svc_entities num:%i ref:%i (database: ref:%i commits:", d->currentcommit->framenum, d->referenceframenum, d->referenceframenum);
41                 for (i = 0;i < MAX_ENTITY_HISTORY;i++)
42                         if (d->commit[i].numentities)
43                                 Con_Printf(" %i", d->commit[i].framenum);
44                 Con_Print(")\n");
45         }
46         if (d->currententitynumber >= prog->max_edicts)
47                 startnumber = 1;
48         else
49                 startnumber = bound(1, d->currententitynumber, prog->max_edicts - 1);
50         MSG_WriteShort(msg, startnumber);
51         // reset currententitynumber so if the loop does not break it we will
52         // start at beginning next frame (if it does break, it will set it)
53         d->currententitynumber = 1;
54         for (i = 0, n = startnumber;n < prog->max_edicts;n++)
55         {
56                 if (PRVM_serveredictfunction((&prog->edicts[n]), SendEntity))
57                         continue;
58                 // find the old state to delta from
59                 e = EntityFrame4_GetReferenceEntity(d, n);
60                 // prepare the buffer
61                 SZ_Clear(&buf);
62                 // entity exists, build an update (if empty there is no change)
63                 // find the state in the list
64                 for (;i < numstates && states[i]->number < n;i++);
65                 // make the message
66                 s = states[i];
67                 if (s->number == n)
68                 {
69                         // build the update
70                         EntityState_WriteUpdate(s, &buf, e);
71                 }
72                 else
73                 {
74                         inactiveentitystate.number = n;
75                         s = &inactiveentitystate;
76                         if (e->active == ACTIVE_NETWORK)
77                         {
78                                 // entity used to exist but doesn't anymore, send remove
79                                 MSG_WriteShort(&buf, n | 0x8000);
80                         }
81                 }
82                 // if the commit is full, we're done this frame
83                 if (msg->cursize + buf.cursize > maxsize - 4)
84                 {
85                         // next frame we will continue where we left off
86                         break;
87                 }
88                 // add the entity to the commit
89                 EntityFrame4_AddCommitEntity(d, s);
90                 // if the message is empty, skip out now
91                 if (buf.cursize)
92                 {
93                         // write the message to the packet
94                         SZ_Write(msg, buf.data, buf.cursize);
95                 }
96         }
97         d->currententitynumber = n;
98
99         // remove world message (invalid, and thus a good terminator)
100         MSG_WriteShort(msg, 0x8000);
101         // write the number of the end entity
102         MSG_WriteShort(msg, d->currententitynumber);
103         // just to be sure
104         d->currentcommit = NULL;
105
106         return true;
107 }