]> icculus.org git repositories - divverent/darkplaces.git/blob - sv_main.c
working code is better than broken code
[divverent/darkplaces.git] / sv_main.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_main.c -- server main program
21
22 #include "quakedef.h"
23 #include "portals.h"
24
25 static cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "0"}; // fast but loose
26 static cvar_t sv_cullentities_portal = {0, "sv_cullentities_portal", "0"}; // extremely accurate visibility checking, but too slow
27 static cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "1"}; // tends to get false negatives, uses a timeout to keep entities visible a short time after becoming hidden
28 static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
29 static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
30
31 server_t sv;
32 server_static_t svs;
33
34 static char localmodels[MAX_MODELS][5];                 // inline model names for precache
35
36 mempool_t *sv_edicts_mempool = NULL;
37 mempool_t *sv_clients_mempool = NULL;
38
39 //============================================================================
40
41 extern void SV_Phys_Init (void);
42 extern void SV_World_Init (void);
43
44 /*
45 ===============
46 SV_Init
47 ===============
48 */
49 void SV_Init (void)
50 {
51         int i;
52
53         Cvar_RegisterVariable (&sv_maxvelocity);
54         Cvar_RegisterVariable (&sv_gravity);
55         Cvar_RegisterVariable (&sv_friction);
56         Cvar_RegisterVariable (&sv_edgefriction);
57         Cvar_RegisterVariable (&sv_stopspeed);
58         Cvar_RegisterVariable (&sv_maxspeed);
59         Cvar_RegisterVariable (&sv_accelerate);
60         Cvar_RegisterVariable (&sv_idealpitchscale);
61         Cvar_RegisterVariable (&sv_aim);
62         Cvar_RegisterVariable (&sv_nostep);
63         Cvar_RegisterVariable (&sv_deltacompress);
64         Cvar_RegisterVariable (&sv_cullentities_pvs);
65         Cvar_RegisterVariable (&sv_cullentities_portal);
66         Cvar_RegisterVariable (&sv_cullentities_trace);
67         Cvar_RegisterVariable (&sv_cullentities_stats);
68         Cvar_RegisterVariable (&sv_entpatch);
69
70         SV_Phys_Init();
71         SV_World_Init();
72
73         for (i = 0;i < MAX_MODELS;i++)
74                 sprintf (localmodels[i], "*%i", i);
75
76         sv_edicts_mempool = Mem_AllocPool("server edicts");
77         sv_clients_mempool = Mem_AllocPool("server clients");
78 }
79
80 /*
81 =============================================================================
82
83 EVENT MESSAGES
84
85 =============================================================================
86 */
87
88 /*
89 ==================
90 SV_StartParticle
91
92 Make sure the event gets sent to all clients
93 ==================
94 */
95 void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
96 {
97         int             i, v;
98
99         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-18)
100                 return;
101         MSG_WriteByte (&sv.datagram, svc_particle);
102         MSG_WriteDPCoord (&sv.datagram, org[0]);
103         MSG_WriteDPCoord (&sv.datagram, org[1]);
104         MSG_WriteDPCoord (&sv.datagram, org[2]);
105         for (i=0 ; i<3 ; i++)
106         {
107                 v = dir[i]*16;
108                 if (v > 127)
109                         v = 127;
110                 else if (v < -128)
111                         v = -128;
112                 MSG_WriteChar (&sv.datagram, v);
113         }
114         MSG_WriteByte (&sv.datagram, count);
115         MSG_WriteByte (&sv.datagram, color);
116 }
117
118 /*
119 ==================
120 SV_StartEffect
121
122 Make sure the event gets sent to all clients
123 ==================
124 */
125 void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
126 {
127         if (modelindex >= 256 || startframe >= 256)
128         {
129                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-19)
130                         return;
131                 MSG_WriteByte (&sv.datagram, svc_effect2);
132                 MSG_WriteDPCoord (&sv.datagram, org[0]);
133                 MSG_WriteDPCoord (&sv.datagram, org[1]);
134                 MSG_WriteDPCoord (&sv.datagram, org[2]);
135                 MSG_WriteShort (&sv.datagram, modelindex);
136                 MSG_WriteShort (&sv.datagram, startframe);
137                 MSG_WriteByte (&sv.datagram, framecount);
138                 MSG_WriteByte (&sv.datagram, framerate);
139         }
140         else
141         {
142                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-17)
143                         return;
144                 MSG_WriteByte (&sv.datagram, svc_effect);
145                 MSG_WriteDPCoord (&sv.datagram, org[0]);
146                 MSG_WriteDPCoord (&sv.datagram, org[1]);
147                 MSG_WriteDPCoord (&sv.datagram, org[2]);
148                 MSG_WriteByte (&sv.datagram, modelindex);
149                 MSG_WriteByte (&sv.datagram, startframe);
150                 MSG_WriteByte (&sv.datagram, framecount);
151                 MSG_WriteByte (&sv.datagram, framerate);
152         }
153 }
154
155 /*
156 ==================
157 SV_StartSound
158
159 Each entity can have eight independant sound sources, like voice,
160 weapon, feet, etc.
161
162 Channel 0 is an auto-allocate channel, the others override anything
163 already running on that entity/channel pair.
164
165 An attenuation of 0 will play full volume everywhere in the level.
166 Larger attenuations will drop off.  (max 4 attenuation)
167
168 ==================
169 */
170 void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
171 {
172         int sound_num, field_mask, i, ent;
173
174         if (volume < 0 || volume > 255)
175                 Host_Error ("SV_StartSound: volume = %i", volume);
176
177         if (attenuation < 0 || attenuation > 4)
178                 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
179
180         if (channel < 0 || channel > 7)
181                 Host_Error ("SV_StartSound: channel = %i", channel);
182
183         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-21)
184                 return;
185
186 // find precache number for sound
187         for (sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
188                 if (!strcmp(sample, sv.sound_precache[sound_num]))
189                         break;
190
191         if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
192         {
193                 Con_Printf ("SV_StartSound: %s not precached\n", sample);
194                 return;
195         }
196
197         ent = NUM_FOR_EDICT(entity);
198
199         field_mask = 0;
200         if (volume != DEFAULT_SOUND_PACKET_VOLUME)
201                 field_mask |= SND_VOLUME;
202         if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
203                 field_mask |= SND_ATTENUATION;
204         if (ent >= 8192)
205                 field_mask |= SND_LARGEENTITY;
206         if (sound_num >= 256 || channel >= 8)
207                 field_mask |= SND_LARGESOUND;
208
209 // directed messages go only to the entity they are targeted on
210         MSG_WriteByte (&sv.datagram, svc_sound);
211         MSG_WriteByte (&sv.datagram, field_mask);
212         if (field_mask & SND_VOLUME)
213                 MSG_WriteByte (&sv.datagram, volume);
214         if (field_mask & SND_ATTENUATION)
215                 MSG_WriteByte (&sv.datagram, attenuation*64);
216         if (field_mask & SND_LARGEENTITY)
217         {
218                 MSG_WriteShort (&sv.datagram, ent);
219                 MSG_WriteByte (&sv.datagram, channel);
220         }
221         else
222                 MSG_WriteShort (&sv.datagram, (ent<<3) | channel);
223         if (field_mask & SND_LARGESOUND)
224                 MSG_WriteShort (&sv.datagram, sound_num);
225         else
226                 MSG_WriteByte (&sv.datagram, sound_num);
227         for (i = 0;i < 3;i++)
228                 MSG_WriteDPCoord (&sv.datagram, entity->v->origin[i]+0.5*(entity->v->mins[i]+entity->v->maxs[i]));
229 }
230
231 /*
232 ==============================================================================
233
234 CLIENT SPAWNING
235
236 ==============================================================================
237 */
238
239 /*
240 ================
241 SV_SendServerinfo
242
243 Sends the first message from the server to a connected client.
244 This will be sent on the initial connection and upon each server load.
245 ================
246 */
247 void SV_SendServerinfo (client_t *client)
248 {
249         char                    **s;
250         char                    message[128];
251
252         // edicts get reallocated on level changes, so we need to update it here
253         client->edict = EDICT_NUM(client->number + 1);
254
255         // LordHavoc: clear entityframe tracking
256         client->entityframenumber = 0;
257         if (client->entitydatabase4)
258                 EntityFrame4_FreeDatabase(client->entitydatabase4);
259         client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_clients_mempool);
260
261         MSG_WriteByte (&client->message, svc_print);
262         sprintf (message, "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, pr_crc);
263         MSG_WriteString (&client->message,message);
264
265         MSG_WriteByte (&client->message, svc_serverinfo);
266         MSG_WriteLong (&client->message, DPPROTOCOL_VERSION4);
267         MSG_WriteByte (&client->message, MAX_SCOREBOARD);
268
269         if (!coop.integer && deathmatch.integer)
270                 MSG_WriteByte (&client->message, GAME_DEATHMATCH);
271         else
272                 MSG_WriteByte (&client->message, GAME_COOP);
273
274         MSG_WriteString (&client->message,PR_GetString(sv.edicts->v->message));
275
276         for (s = sv.model_precache+1 ; *s ; s++)
277                 MSG_WriteString (&client->message, *s);
278         MSG_WriteByte (&client->message, 0);
279
280         for (s = sv.sound_precache+1 ; *s ; s++)
281                 MSG_WriteString (&client->message, *s);
282         MSG_WriteByte (&client->message, 0);
283
284 // send music
285         MSG_WriteByte (&client->message, svc_cdtrack);
286         MSG_WriteByte (&client->message, sv.edicts->v->sounds);
287         MSG_WriteByte (&client->message, sv.edicts->v->sounds);
288
289 // set view
290         MSG_WriteByte (&client->message, svc_setview);
291         MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
292
293         MSG_WriteByte (&client->message, svc_signonnum);
294         MSG_WriteByte (&client->message, 1);
295
296         client->sendsignon = true;
297         client->spawned = false;                // need prespawn, spawn, etc
298 }
299
300 /*
301 ================
302 SV_ConnectClient
303
304 Initializes a client_t for a new net connection.  This will only be called
305 once for a player each game, not once for each level change.
306 ================
307 */
308 void SV_ConnectClient (int clientnum, netconn_t *netconnection)
309 {
310         client_t                *client;
311         int                             i;
312         float                   spawn_parms[NUM_SPAWN_PARMS];
313
314         client = svs.connectedclients[clientnum];
315
316 // set up the client_t
317         if (sv.loadgame)
318                 memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
319         memset (client, 0, sizeof(*client));
320         client->netconnection = netconnection;
321
322         Con_DPrintf("Client %s connected\n", client->netconnection->address);
323
324         strcpy(client->name, "unconnected");
325         strcpy(client->old_name, "unconnected");
326         client->number = clientnum;
327         client->spawned = false;
328         client->edict = EDICT_NUM(clientnum+1);
329         client->message.data = client->msgbuf;
330         client->message.maxsize = sizeof(client->msgbuf);
331         client->message.allowoverflow = true;           // we can catch it
332
333         if (sv.loadgame)
334                 memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
335         else
336         {
337                 // call the progs to get default spawn parms for the new client
338                 PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
339                 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
340                         client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
341         }
342
343         SV_SendServerinfo (client);
344 }
345
346
347 /*
348 ===============================================================================
349
350 FRAME UPDATES
351
352 ===============================================================================
353 */
354
355 /*
356 ==================
357 SV_ClearDatagram
358
359 ==================
360 */
361 void SV_ClearDatagram (void)
362 {
363         SZ_Clear (&sv.datagram);
364 }
365
366 /*
367 =============================================================================
368
369 The PVS must include a small area around the client to allow head bobbing
370 or other small motion on the client side.  Otherwise, a bob might cause an
371 entity that should be visible to not show up, especially when the bob
372 crosses a waterline.
373
374 =============================================================================
375 */
376
377 int             fatbytes;
378 qbyte   fatpvs[MAX_MAP_LEAFS/8];
379
380 void SV_AddToFatPVS (vec3_t org, mnode_t *node)
381 {
382         int             i;
383         qbyte   *pvs;
384         mplane_t        *plane;
385         float   d;
386
387         while (1)
388         {
389         // if this is a leaf, accumulate the pvs bits
390                 if (node->contents < 0)
391                 {
392                         if (node->contents != CONTENTS_SOLID)
393                         {
394                                 pvs = sv.worldmodel->brushq1.LeafPVS(sv.worldmodel, (mleaf_t *)node);
395                                 for (i=0 ; i<fatbytes ; i++)
396                                         fatpvs[i] |= pvs[i];
397                         }
398                         return;
399                 }
400
401                 plane = node->plane;
402                 d = DotProduct (org, plane->normal) - plane->dist;
403                 if (d > 8)
404                         node = node->children[0];
405                 else if (d < -8)
406                         node = node->children[1];
407                 else
408                 {       // go down both
409                         SV_AddToFatPVS (org, node->children[0]);
410                         node = node->children[1];
411                 }
412         }
413 }
414
415 /*
416 =============
417 SV_FatPVS
418
419 Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
420 given point.
421 =============
422 */
423 qbyte *SV_FatPVS (vec3_t org)
424 {
425         fatbytes = (sv.worldmodel->brushq1.numleafs+31)>>3;
426         memset (fatpvs, 0, fatbytes);
427         SV_AddToFatPVS (org, sv.worldmodel->brushq1.nodes);
428         return fatpvs;
429 }
430
431 //=============================================================================
432
433
434 int SV_BoxTouchingPVS (qbyte *pvs, vec3_t mins, vec3_t maxs, mnode_t *node)
435 {
436         int leafnum;
437 loc0:
438         if (node->contents < 0)
439         {
440                 // leaf
441                 if (node->contents == CONTENTS_SOLID)
442                         return false;
443                 leafnum = (mleaf_t *)node - sv.worldmodel->brushq1.leafs - 1;
444                 return pvs[leafnum >> 3] & (1 << (leafnum & 7));
445         }
446
447         // node - recurse down the BSP tree
448         switch (BoxOnPlaneSide(mins, maxs, node->plane))
449         {
450         case 1: // front
451                 node = node->children[0];
452                 goto loc0;
453         case 2: // back
454                 node = node->children[1];
455                 goto loc0;
456         default: // crossing
457                 if (node->children[0]->contents != CONTENTS_SOLID)
458                         if (SV_BoxTouchingPVS (pvs, mins, maxs, node->children[0]))
459                                 return true;
460                 node = node->children[1];
461                 goto loc0;
462         }
463         // never reached
464         return false;
465 }
466
467
468 /*
469 =============
470 SV_WriteEntitiesToClient
471
472 =============
473 */
474 #ifdef QUAKEENTITIES
475 void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
476 {
477         int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects, lightsize;
478         int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
479         qbyte *pvs;
480         vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
481         float nextfullupdate, alphaf;
482         edict_t *ent;
483         eval_t *val;
484         entity_state_t *baseline; // LordHavoc: delta or startup baseline
485         model_t *model;
486
487         Mod_CheckLoaded(sv.worldmodel);
488
489 // find the client's PVS
490         VectorAdd (clent->v->origin, clent->v->view_ofs, testeye);
491         pvs = SV_FatPVS (testeye);
492
493         culled_pvs = 0;
494         culled_portal = 0;
495         culled_trace = 0;
496         visibleentities = 0;
497         totalentities = 0;
498
499         clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
500         // send all entities that touch the pvs
501         ent = NEXT_EDICT(sv.edicts);
502         for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
503         {
504                 bits = 0;
505
506                 // prevent delta compression against this frame (unless actually sent, which will restore this later)
507                 nextfullupdate = client->nextfullupdate[e];
508                 client->nextfullupdate[e] = -1;
509
510                 if (ent != clent) // LordHavoc: always send player
511                 {
512                         if ((val = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
513                         {
514                                 if (val->edict != clentnum)
515                                 {
516                                         // don't show to anyone else
517                                         continue;
518                                 }
519                                 else
520                                         bits |= U_VIEWMODEL; // show relative to the view
521                         }
522                         else
523                         {
524                                 // LordHavoc: never draw something told not to display to this client
525                                 if ((val = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)) && val->edict == clentnum)
526                                         continue;
527                                 if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum)
528                                         continue;
529                         }
530                 }
531
532                 glowsize = 0;
533
534                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size)))
535                         glowsize = (int) val->_float >> 2;
536                 if (glowsize > 255) glowsize = 255;
537                 if (glowsize < 0) glowsize = 0;
538
539                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail)))
540                 if (val->_float != 0)
541                         bits |= U_GLOWTRAIL;
542
543                 if (ent->v->modelindex >= 0 && ent->v->modelindex < MAX_MODELS && *PR_GetString(ent->v->model))
544                 {
545                         model = sv.models[(int)ent->v->modelindex];
546                         Mod_CheckLoaded(model);
547                 }
548                 else
549                 {
550                         model = NULL;
551                         if (ent != clent) // LordHavoc: always send player
552                                 if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
553                                         continue;
554                 }
555
556                 VectorCopy(ent->v->angles, angles);
557                 VectorCopy(ent->v->origin, origin);
558
559                 // ent has survived every check so far, check if it is visible
560                 if (ent != clent && ((bits & U_VIEWMODEL) == 0))
561                 {
562                         // use the predicted origin
563                         entmins[0] = origin[0] - 1.0f;
564                         entmins[1] = origin[1] - 1.0f;
565                         entmins[2] = origin[2] - 1.0f;
566                         entmaxs[0] = origin[0] + 1.0f;
567                         entmaxs[1] = origin[1] + 1.0f;
568                         entmaxs[2] = origin[2] + 1.0f;
569                         // using the model's bounding box to ensure things are visible regardless of their physics box
570                         if (model)
571                         {
572                                 if (ent->v->angles[0] || ent->v->angles[2]) // pitch and roll
573                                 {
574                                         VectorAdd(entmins, model->rotatedmins, entmins);
575                                         VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
576                                 }
577                                 else if (ent->v->angles[1])
578                                 {
579                                         VectorAdd(entmins, model->yawmins, entmins);
580                                         VectorAdd(entmaxs, model->yawmaxs, entmaxs);
581                                 }
582                                 else
583                                 {
584                                         VectorAdd(entmins, model->normalmins, entmins);
585                                         VectorAdd(entmaxs, model->normalmaxs, entmaxs);
586                                 }
587                         }
588
589                         totalentities++;
590
591                         // if not touching a visible leaf
592                         if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->brushq1.nodes))
593                         {
594                                 culled_pvs++;
595                                 continue;
596                         }
597
598                         // or not visible through the portals
599                         if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
600                         {
601                                 culled_portal++;
602                                 continue;
603                         }
604
605                         // don't try to cull embedded brush models with this, they're sometimes huge (spanning several rooms)
606                         if (sv_cullentities_trace.integer && (model == NULL || model->type != mod_brush || model->name[0] != '*'))
607                         {
608                                 // LordHavoc: test random offsets, to maximize chance of detection
609                                 testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
610                                 testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
611                                 testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
612
613                                 if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL).fraction == 1)
614                                         client->visibletime[e] = realtime + 1;
615                                 else
616                                 {
617                                         //test nearest point on bbox
618                                         testorigin[0] = bound(entmins[0], testeye[0], entmaxs[0]);
619                                         testorigin[1] = bound(entmins[1], testeye[1], entmaxs[1]);
620                                         testorigin[2] = bound(entmins[2], testeye[2], entmaxs[2]);
621
622                                         if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL).fraction == 1)
623                                                 client->visibletime[e] = realtime + 1;
624                                         else if (realtime > client->visibletime[e])
625                                         {
626                                                 culled_trace++;
627                                                 continue;
628                                         }
629                                 }
630                         }
631                         visibleentities++;
632                 }
633
634                 alphaf = 255.0f;
635                 scale = 16;
636                 glowcolor = 254;
637                 effects = ent->v->effects;
638
639                 if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
640                 if (val->_float != 0)
641                         alphaf = val->_float * 255.0f;
642
643                 // HalfLife support
644                 if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)))
645                 if (val->_float != 0)
646                         alphaf = val->_float;
647
648                 if (alphaf == 0.0f)
649                         alphaf = 255.0f;
650                 alpha = bound(0, alphaf, 255);
651
652                 if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
653                 if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
654                 if (scale < 0) scale = 0;
655                 if (scale > 255) scale = 255;
656
657                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color)))
658                 if (val->_float != 0)
659                         glowcolor = (int) val->_float;
660
661                 if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright)))
662                 if (val->_float != 0)
663                         effects |= EF_FULLBRIGHT;
664
665                 if (ent != clent)
666                 {
667                         if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
668                         {
669                                 if (model) // model
670                                 {
671                                         // don't send if flagged for NODRAW and there are no effects
672                                         if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
673                                                 continue;
674                                 }
675                                 else // no model and no effects
676                                         continue;
677                         }
678                 }
679
680                 if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32
681                 {
682                         Con_Printf ("packet overflow\n");
683                         // mark the rest of the entities so they can't be delta compressed against this frame
684                         for (;e < sv.num_edicts;e++)
685                         {
686                                 client->nextfullupdate[e] = -1;
687                                 client->visibletime[e] = -1;
688                         }
689                         return;
690                 }
691
692                 if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum)
693                         bits = bits | U_EXTERIORMODEL;
694
695 // send an update
696                 baseline = &ent->e->baseline;
697
698                 if (((int)ent->v->effects & EF_DELTA) && sv_deltacompress.integer)
699                 {
700                         // every half second a full update is forced
701                         if (realtime < client->nextfullupdate[e])
702                         {
703                                 bits |= U_DELTA;
704                                 baseline = &ent->e->deltabaseline;
705                         }
706                         else
707                                 nextfullupdate = realtime + 0.5f;
708                 }
709                 else
710                         nextfullupdate = realtime + 0.5f;
711
712                 // restore nextfullupdate since this is being sent for real
713                 client->nextfullupdate[e] = nextfullupdate;
714
715                 if (e >= 256)
716                         bits |= U_LONGENTITY;
717
718                 if (ent->v->movetype == MOVETYPE_STEP)
719                         bits |= U_STEP;
720
721                 // LordHavoc: old stuff, but rewritten to have more exact tolerances
722                 if (origin[0] != baseline->origin[0])                                                                                   bits |= U_ORIGIN1;
723                 if (origin[1] != baseline->origin[1])                                                                                   bits |= U_ORIGIN2;
724                 if (origin[2] != baseline->origin[2])                                                                                   bits |= U_ORIGIN3;
725                 if (((int)(angles[0]*(256.0/360.0)) & 255) != ((int)(baseline->angles[0]*(256.0/360.0)) & 255)) bits |= U_ANGLE1;
726                 if (((int)(angles[1]*(256.0/360.0)) & 255) != ((int)(baseline->angles[1]*(256.0/360.0)) & 255)) bits |= U_ANGLE2;
727                 if (((int)(angles[2]*(256.0/360.0)) & 255) != ((int)(baseline->angles[2]*(256.0/360.0)) & 255)) bits |= U_ANGLE3;
728                 if (baseline->colormap != (qbyte) ent->v->colormap)                                                             bits |= U_COLORMAP;
729                 if (baseline->skin != (qbyte) ent->v->skin)                                                                             bits |= U_SKIN;
730                 if ((baseline->frame & 0x00FF) != ((int) ent->v->frame & 0x00FF))                               bits |= U_FRAME;
731                 if ((baseline->effects & 0x00FF) != ((int) ent->v->effects & 0x00FF))                   bits |= U_EFFECTS;
732                 if ((baseline->modelindex & 0x00FF) != ((int) ent->v->modelindex & 0x00FF))             bits |= U_MODEL;
733
734                 // LordHavoc: new stuff
735                 if (baseline->alpha != alpha)                                                                                                   bits |= U_ALPHA;
736                 if (baseline->scale != scale)                                                                                                   bits |= U_SCALE;
737                 if (((int) baseline->effects & 0xFF00) != ((int) ent->v->effects & 0xFF00))             bits |= U_EFFECTS2;
738                 if (baseline->glowsize != glowsize)                                                                                             bits |= U_GLOWSIZE;
739                 if (baseline->glowcolor != glowcolor)                                                                                   bits |= U_GLOWCOLOR;
740                 if (((int) baseline->frame & 0xFF00) != ((int) ent->v->frame & 0xFF00))                 bits |= U_FRAME2;
741                 if (((int) baseline->frame & 0xFF00) != ((int) ent->v->modelindex & 0xFF00))            bits |= U_MODEL2;
742
743                 // update delta baseline
744                 VectorCopy(ent->v->origin, ent->e->deltabaseline.origin);
745                 VectorCopy(ent->v->angles, ent->e->deltabaseline.angles);
746                 ent->e->deltabaseline.colormap = ent->v->colormap;
747                 ent->e->deltabaseline.skin = ent->v->skin;
748                 ent->e->deltabaseline.frame = ent->v->frame;
749                 ent->e->deltabaseline.effects = ent->v->effects;
750                 ent->e->deltabaseline.modelindex = ent->v->modelindex;
751                 ent->e->deltabaseline.alpha = alpha;
752                 ent->e->deltabaseline.scale = scale;
753                 ent->e->deltabaseline.glowsize = glowsize;
754                 ent->e->deltabaseline.glowcolor = glowcolor;
755
756                 // write the message
757                 if (bits >= 16777216)
758                         bits |= U_EXTEND2;
759                 if (bits >= 65536)
760                         bits |= U_EXTEND1;
761                 if (bits >= 256)
762                         bits |= U_MOREBITS;
763                 bits |= U_SIGNAL;
764
765                 MSG_WriteByte (msg, bits);
766                 if (bits & U_MOREBITS)
767                         MSG_WriteByte (msg, bits>>8);
768                 // LordHavoc: extend bytes have to be written here due to delta compression
769                 if (bits & U_EXTEND1)
770                         MSG_WriteByte (msg, bits>>16);
771                 if (bits & U_EXTEND2)
772                         MSG_WriteByte (msg, bits>>24);
773
774                 // LordHavoc: old stuff
775                 if (bits & U_LONGENTITY)
776                         MSG_WriteShort (msg,e);
777                 else
778                         MSG_WriteByte (msg,e);
779                 if (bits & U_MODEL)             MSG_WriteByte (msg,     ent->v->modelindex);
780                 if (bits & U_FRAME)             MSG_WriteByte (msg, ent->v->frame);
781                 if (bits & U_COLORMAP)  MSG_WriteByte (msg, ent->v->colormap);
782                 if (bits & U_SKIN)              MSG_WriteByte (msg, ent->v->skin);
783                 if (bits & U_EFFECTS)   MSG_WriteByte (msg, ent->v->effects);
784                 if (bits & U_ORIGIN1)   MSG_WriteDPCoord (msg, origin[0]);
785                 if (bits & U_ANGLE1)    MSG_WriteAngle(msg, angles[0]);
786                 if (bits & U_ORIGIN2)   MSG_WriteDPCoord (msg, origin[1]);
787                 if (bits & U_ANGLE2)    MSG_WriteAngle(msg, angles[1]);
788                 if (bits & U_ORIGIN3)   MSG_WriteDPCoord (msg, origin[2]);
789                 if (bits & U_ANGLE3)    MSG_WriteAngle(msg, angles[2]);
790
791                 // LordHavoc: new stuff
792                 if (bits & U_ALPHA)             MSG_WriteByte(msg, alpha);
793                 if (bits & U_SCALE)             MSG_WriteByte(msg, scale);
794                 if (bits & U_EFFECTS2)  MSG_WriteByte(msg, (int)ent->v->effects >> 8);
795                 if (bits & U_GLOWSIZE)  MSG_WriteByte(msg, glowsize);
796                 if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
797                 if (bits & U_FRAME2)    MSG_WriteByte(msg, (int)ent->v->frame >> 8);
798                 if (bits & U_MODEL2)    MSG_WriteByte(msg, (int)ent->v->modelindex >> 8);
799         }
800
801         if (sv_cullentities_stats.integer)
802                 Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_portal + culled_trace, culled_pvs, culled_portal, culled_trace);
803 }
804 #else
805 static int numsendentities;
806 static entity_state_t sendentities[MAX_EDICTS];
807 static entity_state_t *sendentitiesindex[MAX_EDICTS];
808
809 void SV_PrepareEntitiesForSending(void)
810 {
811         int e, i;
812         edict_t *ent;
813         entity_state_t cs;
814         // send all entities that touch the pvs
815         numsendentities = 0;
816         sendentitiesindex[0] = NULL;
817         for (e = 1, ent = NEXT_EDICT(sv.edicts);e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
818         {
819                 sendentitiesindex[e] = NULL;
820                 if (ent->e->free)
821                         continue;
822
823                 ClearStateToDefault(&cs);
824                 cs.active = true;
825                 cs.number = e;
826                 VectorCopy(ent->v->origin, cs.origin);
827                 VectorCopy(ent->v->angles, cs.angles);
828                 cs.flags = 0;
829                 cs.effects = (int)ent->v->effects;
830                 cs.colormap = (qbyte)ent->v->colormap;
831                 cs.skin = (qbyte)ent->v->skin;
832                 cs.frame = (qbyte)ent->v->frame;
833                 cs.viewmodelforclient = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
834                 cs.exteriormodelforclient = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
835                 cs.nodrawtoclient = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
836                 cs.drawonlytoclient = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
837                 cs.tagentity = GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
838                 cs.tagindex = (qbyte)GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
839                 i = (int)(GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
840                 cs.glowsize = (qbyte)bound(0, i, 255);
841                 if (GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
842                         cs.flags |= RENDER_GLOWTRAIL;
843
844                 cs.modelindex = 0;
845                 i = (int)ent->v->modelindex;
846                 if (i >= 1 && i < MAX_MODELS && *PR_GetString(ent->v->model))
847                         cs.modelindex = i;
848
849
850                 cs.alpha = 255;
851                 i = (int)(GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
852                 if (i)
853                         cs.alpha = (qbyte)bound(0, i, 255);
854                 // halflife
855                 i = (int)(GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
856                 if (i)
857                         cs.alpha = (qbyte)bound(0, i, 255);
858
859                 cs.scale = 16;
860                 i = (int)(GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
861                 if (i)
862                         cs.scale = (qbyte)bound(0, i, 255);
863
864                 cs.glowcolor = 254;
865                 i = (int)(GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
866                 if (i)
867                         cs.glowcolor = i;
868
869                 if (GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
870                         cs.effects |= EF_FULLBRIGHT;
871
872                 if (ent->v->movetype == MOVETYPE_STEP)
873                         cs.flags |= RENDER_STEP;
874                 if ((cs.effects & EF_LOWPRECISION) && cs.origin[0] >= -32768 && cs.origin[1] >= -32768 && cs.origin[2] >= -32768 && cs.origin[0] <= 32767 && cs.origin[1] <= 32767 && cs.origin[2] <= 32767)
875                         cs.flags |= RENDER_LOWPRECISION;
876                 if (ent->v->colormap >= 1024)
877                         cs.flags |= RENDER_COLORMAPPED;
878                 if (cs.viewmodelforclient)
879                         cs.flags |= RENDER_VIEWMODEL; // show relative to the view
880
881                 cs.specialvisibilityradius = 0;
882                 if (cs.glowsize)
883                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, cs.glowsize * 4);
884                 if (cs.flags & RENDER_GLOWTRAIL)
885                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
886                 if (cs.effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
887                 {
888                         if (cs.effects & EF_BRIGHTFIELD)
889                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 80);
890                         if (cs.effects & EF_MUZZLEFLASH)
891                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
892                         if (cs.effects & EF_BRIGHTLIGHT)
893                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 400);
894                         if (cs.effects & EF_DIMLIGHT)
895                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
896                         if (cs.effects & EF_RED)
897                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
898                         if (cs.effects & EF_BLUE)
899                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
900                         if (cs.effects & EF_FLAME)
901                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 250);
902                         if (cs.effects & EF_STARDUST)
903                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
904                 }
905
906                 if (numsendentities >= MAX_EDICTS)
907                         continue;
908                 // we can omit invisible entities with no effects that are not clients
909                 // LordHavoc: this could kill tags attached to an invisible entity, I
910                 // just hope we never have to support that case
911                 if (cs.number > MAX_SCOREBOARD && ((cs.effects & EF_NODRAW) || (!cs.modelindex && !cs.specialvisibilityradius)))
912                         continue;
913                 sendentitiesindex[e] = sendentities + numsendentities;
914                 sendentities[numsendentities++] = cs;
915         }
916 }
917
918 static int sententitiesmark = 0;
919 static int sententities[MAX_EDICTS];
920 static int sententitiesconsideration[MAX_EDICTS];
921 static int sv_writeentitiestoclient_culled_pvs;
922 static int sv_writeentitiestoclient_culled_portal;
923 static int sv_writeentitiestoclient_culled_trace;
924 static int sv_writeentitiestoclient_visibleentities;
925 static int sv_writeentitiestoclient_totalentities;
926 //static entity_frame_t sv_writeentitiestoclient_entityframe;
927 static int sv_writeentitiestoclient_clentnum;
928 static qbyte *sv_writeentitiestoclient_pvs;
929 static vec3_t sv_writeentitiestoclient_testeye;
930 static client_t *sv_writeentitiestoclient_client;
931
932 void SV_MarkWriteEntityStateToClient(entity_state_t *s)
933 {
934         vec3_t entmins, entmaxs, lightmins, lightmaxs, testorigin;
935         model_t *model;
936         trace_t trace;
937         if (sententitiesconsideration[s->number] == sententitiesmark)
938                 return;
939         sententitiesconsideration[s->number] = sententitiesmark;
940         // viewmodels don't have visibility checking
941         if (s->viewmodelforclient)
942         {
943                 if (s->viewmodelforclient != sv_writeentitiestoclient_clentnum)
944                         return;
945         }
946         // never reject player
947         else if (s->number != sv_writeentitiestoclient_clentnum)
948         {
949                 // check various rejection conditions
950                 if (s->nodrawtoclient == sv_writeentitiestoclient_clentnum)
951                         return;
952                 if (s->drawonlytoclient && s->drawonlytoclient != sv_writeentitiestoclient_clentnum)
953                         return;
954                 if (s->effects & EF_NODRAW)
955                         return;
956                 // LordHavoc: only send entities with a model or important effects
957                 if (!s->modelindex && s->specialvisibilityradius == 0)
958                         return;
959                 if (s->tagentity)
960                 {
961                         // tag attached entities simply check their parent
962                         if (!sendentitiesindex[s->tagentity])
963                                 return;
964                         SV_MarkWriteEntityStateToClient(sendentitiesindex[s->tagentity]);
965                         if (sententities[s->tagentity] != sententitiesmark)
966                                 return;
967                 }
968                 // always send world submodels, they don't generate much traffic
969                 else if ((model = sv.models[s->modelindex]) == NULL || model->name[0] != '*')
970                 {
971                         Mod_CheckLoaded(model);
972                         // entity has survived every check so far, check if visible
973                         // enlarged box to account for prediction (not that there is
974                         // any currently, but still helps the 'run into a room and
975                         // watch items pop up' problem)
976                         entmins[0] = s->origin[0] - 32.0f;
977                         entmins[1] = s->origin[1] - 32.0f;
978                         entmins[2] = s->origin[2] - 32.0f;
979                         entmaxs[0] = s->origin[0] + 32.0f;
980                         entmaxs[1] = s->origin[1] + 32.0f;
981                         entmaxs[2] = s->origin[2] + 32.0f;
982                         // using the model's bounding box to ensure things are visible regardless of their physics box
983                         if (model)
984                         {
985                                 if (s->angles[0] || s->angles[2]) // pitch and roll
986                                 {
987                                         VectorAdd(entmins, model->rotatedmins, entmins);
988                                         VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
989                                 }
990                                 else if (s->angles[1])
991                                 {
992                                         VectorAdd(entmins, model->yawmins, entmins);
993                                         VectorAdd(entmaxs, model->yawmaxs, entmaxs);
994                                 }
995                                 else
996                                 {
997                                         VectorAdd(entmins, model->normalmins, entmins);
998                                         VectorAdd(entmaxs, model->normalmaxs, entmaxs);
999                                 }
1000                         }
1001                         lightmins[0] = min(entmins[0], s->origin[0] - s->specialvisibilityradius);
1002                         lightmins[1] = min(entmins[1], s->origin[1] - s->specialvisibilityradius);
1003                         lightmins[2] = min(entmins[2], s->origin[2] - s->specialvisibilityradius);
1004                         lightmaxs[0] = min(entmaxs[0], s->origin[0] + s->specialvisibilityradius);
1005                         lightmaxs[1] = min(entmaxs[1], s->origin[1] + s->specialvisibilityradius);
1006                         lightmaxs[2] = min(entmaxs[2], s->origin[2] + s->specialvisibilityradius);
1007                         sv_writeentitiestoclient_totalentities++;
1008                         // if not touching a visible leaf
1009                         if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(sv_writeentitiestoclient_pvs, lightmins, lightmaxs, sv.worldmodel->brushq1.nodes))
1010                         {
1011                                 sv_writeentitiestoclient_culled_pvs++;
1012                                 return;
1013                         }
1014                         // or not visible through the portals
1015                         if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, sv_writeentitiestoclient_testeye, lightmins, lightmaxs))
1016                         {
1017                                 sv_writeentitiestoclient_culled_portal++;
1018                                 return;
1019                         }
1020                         // or not seen by random tracelines
1021                         if (sv_cullentities_trace.integer)
1022                         {
1023                                 // LordHavoc: test center first
1024                                 testorigin[0] = (entmins[0] + entmaxs[0]) * 0.5f;
1025                                 testorigin[1] = (entmins[1] + entmaxs[1]) * 0.5f;
1026                                 testorigin[2] = (entmins[2] + entmaxs[2]) * 0.5f;
1027                                 trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
1028                                 if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
1029                                         sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
1030                                 else
1031                                 {
1032                                         // LordHavoc: test random offsets, to maximize chance of detection
1033                                         testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
1034                                         testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
1035                                         testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
1036                                         trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
1037                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
1038                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
1039                                         else
1040                                         {
1041                                                 if (s->specialvisibilityradius)
1042                                                 {
1043                                                         // LordHavoc: test random offsets, to maximize chance of detection
1044                                                         testorigin[0] = lhrandom(lightmins[0], lightmaxs[0]);
1045                                                         testorigin[1] = lhrandom(lightmins[1], lightmaxs[1]);
1046                                                         testorigin[2] = lhrandom(lightmins[2], lightmaxs[2]);
1047                                                         trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
1048                                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
1049                                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
1050                                                 }
1051                                         }
1052                                 }
1053                                 if (realtime > sv_writeentitiestoclient_client->visibletime[s->number])
1054                                 {
1055                                         sv_writeentitiestoclient_culled_trace++;
1056                                         return;
1057                                 }
1058                         }
1059                         sv_writeentitiestoclient_visibleentities++;
1060                 }
1061         }
1062         // this just marks it for sending
1063         // FIXME: it would be more efficient to send here, but the entity
1064         // compressor isn't that flexible
1065         sententities[s->number] = sententitiesmark;
1066 }
1067
1068 void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
1069 {
1070         int i;
1071         vec3_t testorigin;
1072         entity_state_t *s;
1073         entity_database4_t *d;
1074         int maxbytes, n, startnumber;
1075         entity_state_t *e, inactiveentitystate;
1076         sizebuf_t buf;
1077         qbyte data[128];
1078         // prepare the buffer
1079         memset(&buf, 0, sizeof(buf));
1080         buf.data = data;
1081         buf.maxsize = sizeof(data);
1082
1083         // this state's number gets played around with later
1084         ClearStateToDefault(&inactiveentitystate);
1085         //inactiveentitystate = defaultstate;
1086
1087         sv_writeentitiestoclient_client = client;
1088
1089         sv_writeentitiestoclient_culled_pvs = 0;
1090         sv_writeentitiestoclient_culled_portal = 0;
1091         sv_writeentitiestoclient_culled_trace = 0;
1092         sv_writeentitiestoclient_visibleentities = 0;
1093         sv_writeentitiestoclient_totalentities = 0;
1094
1095         Mod_CheckLoaded(sv.worldmodel);
1096
1097 // find the client's PVS
1098         // the real place being tested from
1099         VectorAdd(clent->v->origin, clent->v->view_ofs, sv_writeentitiestoclient_testeye);
1100         sv_writeentitiestoclient_pvs = SV_FatPVS(sv_writeentitiestoclient_testeye);
1101
1102         sv_writeentitiestoclient_clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
1103
1104         sententitiesmark++;
1105
1106         // the place being reported (to consider the fact the client still
1107         // applies the view_ofs[2], so we have to only send the fractional part
1108         // of view_ofs[2], undoing what the client will redo)
1109         VectorCopy(sv_writeentitiestoclient_testeye, testorigin);
1110         i = (int) clent->v->view_ofs[2] & 255;
1111         if (i >= 128)
1112                 i -= 256;
1113         testorigin[2] -= (float) i;
1114
1115         for (i = 0;i < numsendentities;i++)
1116                 SV_MarkWriteEntityStateToClient(sendentities + i);
1117
1118         d = client->entitydatabase4;
1119         // calculate maximum bytes to allow in this packet
1120         // deduct 4 to account for the end data
1121         maxbytes = min(msg->maxsize, MAX_PACKETFRAGMENT) - 4;
1122
1123         d->currentcommit = d->commit + EntityFrame4_SV_ChooseCommitToReplace(d);
1124         d->currentcommit->numentities = 0;
1125         d->currentcommit->framenum = ++client->entityframenumber;
1126         MSG_WriteByte(msg, svc_entities);
1127         MSG_WriteLong(msg, d->referenceframenum);
1128         MSG_WriteLong(msg, d->currentcommit->framenum);
1129         if (d->currententitynumber >= sv.max_edicts)
1130                 startnumber = 1;
1131         else
1132                 startnumber = bound(1, d->currententitynumber, sv.max_edicts - 1);
1133         MSG_WriteShort(msg, startnumber);
1134         // reset currententitynumber so if the loop does not break it we will
1135         // start at beginning next frame (if it does break, it will set it)
1136         d->currententitynumber = 1;
1137         for (i = 0, n = startnumber;n < sv.max_edicts;n++)
1138         {
1139                 // find the old state to delta from
1140                 e = EntityFrame4_GetReferenceEntity(d, n);
1141                 // prepare the buffer
1142                 SZ_Clear(&buf);
1143                 // make the message
1144                 if (sententities[n] == sententitiesmark)
1145                 {
1146                         // entity exists, build an update (if empty there is no change)
1147                         // find the state in the list
1148                         for (;i < numsendentities && sendentities[i].number < n;i++);
1149                         s = sendentities + i;
1150                         if (s->number != n)
1151                                 Sys_Error("SV_WriteEntitiesToClient: s->number != n\n");
1152                         // build the update
1153                         if (s->exteriormodelforclient && s->exteriormodelforclient == sv_writeentitiestoclient_clentnum)
1154                         {
1155                                 s->flags |= RENDER_EXTERIORMODEL;
1156                                 EntityState_Write(s, &buf, e);
1157                                 s->flags &= ~RENDER_EXTERIORMODEL;
1158                         }
1159                         else
1160                                 EntityState_Write(s, &buf, e);
1161                 }
1162                 else
1163                 {
1164                         s = &inactiveentitystate;
1165                         s->number = n;
1166                         if (e->active)
1167                         {
1168                                 // entity used to exist but doesn't anymore, send remove
1169                                 MSG_WriteShort(&buf, n | 0x8000);
1170                         }
1171                 }
1172                 // if the commit is full, we're done this frame
1173                 if (msg->cursize + buf.cursize > maxbytes)
1174                 {
1175                         // next frame we will continue where we left off
1176                         break;
1177                 }
1178                 // add the entity to the commit
1179                 EntityFrame4_AddCommitEntity(d, s);
1180                 // if the message is empty, skip out now
1181                 if (buf.cursize)
1182                 {
1183                         // write the message to the packet
1184                         SZ_Write(msg, buf.data, buf.cursize);
1185                 }
1186         }
1187         d->currententitynumber = n;
1188
1189         // remove world message (invalid, and thus a good terminator)
1190         MSG_WriteShort(msg, 0x8000);
1191         // write the number of the end entity
1192         MSG_WriteShort(msg, d->currententitynumber);
1193         // just to be sure
1194         d->currentcommit = NULL;
1195
1196         if (sv_cullentities_stats.integer)
1197                 Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_portal + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_portal, sv_writeentitiestoclient_culled_trace);
1198 }
1199 #endif
1200
1201 /*
1202 =============
1203 SV_CleanupEnts
1204
1205 =============
1206 */
1207 void SV_CleanupEnts (void)
1208 {
1209         int             e;
1210         edict_t *ent;
1211
1212         ent = NEXT_EDICT(sv.edicts);
1213         for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
1214                 ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH;
1215 }
1216
1217 /*
1218 ==================
1219 SV_WriteClientdataToMessage
1220
1221 ==================
1222 */
1223 void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
1224 {
1225         int             bits;
1226         int             i;
1227         edict_t *other;
1228         int             items;
1229         eval_t  *val;
1230         vec3_t  punchvector;
1231         qbyte   viewzoom;
1232
1233 //
1234 // send a damage message
1235 //
1236         if (ent->v->dmg_take || ent->v->dmg_save)
1237         {
1238                 other = PROG_TO_EDICT(ent->v->dmg_inflictor);
1239                 MSG_WriteByte (msg, svc_damage);
1240                 MSG_WriteByte (msg, ent->v->dmg_save);
1241                 MSG_WriteByte (msg, ent->v->dmg_take);
1242                 for (i=0 ; i<3 ; i++)
1243                         MSG_WriteDPCoord (msg, other->v->origin[i] + 0.5*(other->v->mins[i] + other->v->maxs[i]));
1244
1245                 ent->v->dmg_take = 0;
1246                 ent->v->dmg_save = 0;
1247         }
1248
1249 //
1250 // send the current viewpos offset from the view entity
1251 //
1252         SV_SetIdealPitch ();            // how much to look up / down ideally
1253
1254 // a fixangle might get lost in a dropped packet.  Oh well.
1255         if ( ent->v->fixangle )
1256         {
1257                 MSG_WriteByte (msg, svc_setangle);
1258                 for (i=0 ; i < 3 ; i++)
1259                         MSG_WriteAngle (msg, ent->v->angles[i] );
1260                 ent->v->fixangle = 0;
1261         }
1262
1263         bits = 0;
1264
1265         if (ent->v->view_ofs[2] != DEFAULT_VIEWHEIGHT)
1266                 bits |= SU_VIEWHEIGHT;
1267
1268         if (ent->v->idealpitch)
1269                 bits |= SU_IDEALPITCH;
1270
1271 // stuff the sigil bits into the high bits of items for sbar, or else
1272 // mix in items2
1273         val = GETEDICTFIELDVALUE(ent, eval_items2);
1274
1275         if (val)
1276                 items = (int)ent->v->items | ((int)val->_float << 23);
1277         else
1278                 items = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
1279
1280         bits |= SU_ITEMS;
1281
1282         if ( (int)ent->v->flags & FL_ONGROUND)
1283                 bits |= SU_ONGROUND;
1284
1285         if ( ent->v->waterlevel >= 2)
1286                 bits |= SU_INWATER;
1287
1288         // dpprotocol
1289         VectorClear(punchvector);
1290         if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
1291                 VectorCopy(val->vector, punchvector);
1292
1293         i = 255;
1294         if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
1295         {
1296                 i = val->_float * 255.0f;
1297                 if (i == 0)
1298                         i = 255;
1299                 else
1300                         i = bound(0, i, 255);
1301         }
1302         viewzoom = i;
1303
1304         if (viewzoom != 255)
1305                 bits |= SU_VIEWZOOM;
1306
1307         for (i=0 ; i<3 ; i++)
1308         {
1309                 if (ent->v->punchangle[i])
1310                         bits |= (SU_PUNCH1<<i);
1311                 if (punchvector[i]) // dpprotocol
1312                         bits |= (SU_PUNCHVEC1<<i); // dpprotocol
1313                 if (ent->v->velocity[i])
1314                         bits |= (SU_VELOCITY1<<i);
1315         }
1316
1317         if (ent->v->weaponframe)
1318                 bits |= SU_WEAPONFRAME;
1319
1320         if (ent->v->armorvalue)
1321                 bits |= SU_ARMOR;
1322
1323         bits |= SU_WEAPON;
1324
1325         if (bits >= 65536)
1326                 bits |= SU_EXTEND1;
1327         if (bits >= 16777216)
1328                 bits |= SU_EXTEND2;
1329
1330 // send the data
1331
1332         MSG_WriteByte (msg, svc_clientdata);
1333         MSG_WriteShort (msg, bits);
1334         if (bits & SU_EXTEND1)
1335                 MSG_WriteByte(msg, bits >> 16);
1336         if (bits & SU_EXTEND2)
1337                 MSG_WriteByte(msg, bits >> 24);
1338
1339         if (bits & SU_VIEWHEIGHT)
1340                 MSG_WriteChar (msg, ent->v->view_ofs[2]);
1341
1342         if (bits & SU_IDEALPITCH)
1343                 MSG_WriteChar (msg, ent->v->idealpitch);
1344
1345         for (i=0 ; i<3 ; i++)
1346         {
1347                 if (bits & (SU_PUNCH1<<i))
1348                         MSG_WritePreciseAngle(msg, ent->v->punchangle[i]); // dpprotocol
1349                 if (bits & (SU_PUNCHVEC1<<i)) // dpprotocol
1350                         MSG_WriteDPCoord(msg, punchvector[i]); // dpprotocol
1351                 if (bits & (SU_VELOCITY1<<i))
1352                         MSG_WriteChar (msg, ent->v->velocity[i]/16);
1353         }
1354
1355 // [always sent]        if (bits & SU_ITEMS)
1356         MSG_WriteLong (msg, items);
1357
1358         if (bits & SU_WEAPONFRAME)
1359                 MSG_WriteByte (msg, ent->v->weaponframe);
1360         if (bits & SU_ARMOR)
1361                 MSG_WriteByte (msg, ent->v->armorvalue);
1362         if (bits & SU_WEAPON)
1363                 MSG_WriteByte (msg, SV_ModelIndex(PR_GetString(ent->v->weaponmodel)));
1364
1365         MSG_WriteShort (msg, ent->v->health);
1366         MSG_WriteByte (msg, ent->v->currentammo);
1367         MSG_WriteByte (msg, ent->v->ammo_shells);
1368         MSG_WriteByte (msg, ent->v->ammo_nails);
1369         MSG_WriteByte (msg, ent->v->ammo_rockets);
1370         MSG_WriteByte (msg, ent->v->ammo_cells);
1371
1372         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1373         {
1374                 for(i=0;i<32;i++)
1375                 {
1376                         if ( ((int)ent->v->weapon) & (1<<i) )
1377                         {
1378                                 MSG_WriteByte (msg, i);
1379                                 break;
1380                         }
1381                 }
1382         }
1383         else
1384         {
1385                 MSG_WriteByte (msg, ent->v->weapon);
1386         }
1387
1388         if (bits & SU_VIEWZOOM)
1389                 MSG_WriteByte (msg, viewzoom);
1390 }
1391
1392 /*
1393 =======================
1394 SV_SendClientDatagram
1395 =======================
1396 */
1397 static qbyte sv_sendclientdatagram_buf[MAX_DATAGRAM]; // FIXME?
1398 qboolean SV_SendClientDatagram (client_t *client)
1399 {
1400         sizebuf_t       msg;
1401
1402         msg.data = sv_sendclientdatagram_buf;
1403         msg.maxsize = sizeof(sv_sendclientdatagram_buf);
1404         msg.cursize = 0;
1405
1406         MSG_WriteByte (&msg, svc_time);
1407         MSG_WriteFloat (&msg, sv.time);
1408
1409         // add the client specific data to the datagram
1410         SV_WriteClientdataToMessage (client->edict, &msg);
1411
1412         SV_WriteEntitiesToClient (client, client->edict, &msg);
1413
1414         // copy the server datagram if there is space
1415         if (msg.cursize + sv.datagram.cursize < msg.maxsize)
1416                 SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
1417
1418 // send the datagram
1419         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1420         {
1421                 SV_DropClient (true);// if the message couldn't send, kick off
1422                 return false;
1423         }
1424
1425         return true;
1426 }
1427
1428 /*
1429 =======================
1430 SV_UpdateToReliableMessages
1431 =======================
1432 */
1433 void SV_UpdateToReliableMessages (void)
1434 {
1435         int i, j;
1436         client_t *client;
1437         eval_t *val;
1438         char *s;
1439
1440 // check for changes to be sent over the reliable streams
1441         for (i = 0;i < MAX_SCOREBOARD;i++)
1442         {
1443                 // only update the client fields if they've spawned in
1444                 if ((host_client = svs.connectedclients[i]) && host_client->spawned)
1445                 {
1446                         // update the host_client fields we care about according to the entity fields
1447                         sv_player = host_client->edict;
1448                         s = PR_GetString(sv_player->v->netname);
1449                         if (s != host_client->name)
1450                         {
1451                                 if (s == NULL)
1452                                         s = "";
1453                                 // point the string back at host_client->name to keep it safe
1454                                 strncpy(host_client->name, s, sizeof(host_client->name) - 1);
1455                                 sv_player->v->netname = PR_SetString(host_client->name);
1456                         }
1457                         if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors)) && host_client->colors != val->_float)
1458                                 host_client->colors = val->_float;
1459                         host_client->frags = sv_player->v->frags;
1460                         if (gamemode == GAME_NEHAHRA)
1461                                 if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)) && host_client->pmodel != val->_float)
1462                                         host_client->pmodel = val->_float;
1463
1464                         // if the fields changed, send messages about the changes
1465                         if (strcmp(host_client->old_name, host_client->name))
1466                         {
1467                                 strcpy(host_client->old_name, host_client->name);
1468                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1469                                 {
1470                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1471                                                 continue;
1472                                         MSG_WriteByte (&client->message, svc_updatename);
1473                                         MSG_WriteByte (&client->message, i);
1474                                         MSG_WriteString (&client->message, host_client->name);
1475                                 }
1476                         }
1477                         if (host_client->old_colors != host_client->colors)
1478                         {
1479                                 host_client->old_colors = host_client->colors;
1480                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1481                                 {
1482                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1483                                                 continue;
1484                                         MSG_WriteByte (&client->message, svc_updatecolors);
1485                                         MSG_WriteByte (&client->message, i);
1486                                         MSG_WriteByte (&client->message, host_client->colors);
1487                                 }
1488                         }
1489                         if (host_client->old_frags != host_client->frags)
1490                         {
1491                                 host_client->old_frags = host_client->frags;
1492                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1493                                 {
1494                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1495                                                 continue;
1496                                         MSG_WriteByte (&client->message, svc_updatefrags);
1497                                         MSG_WriteByte (&client->message, i);
1498                                         MSG_WriteShort (&client->message, host_client->frags);
1499                                 }
1500                         }
1501                 }
1502         }
1503
1504         for (j = 0;j < MAX_SCOREBOARD;j++)
1505                 if ((client = svs.connectedclients[j]))
1506                         SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
1507
1508         SZ_Clear (&sv.reliable_datagram);
1509 }
1510
1511
1512 /*
1513 =======================
1514 SV_SendNop
1515
1516 Send a nop message without trashing or sending the accumulated client
1517 message buffer
1518 =======================
1519 */
1520 void SV_SendNop (client_t *client)
1521 {
1522         sizebuf_t       msg;
1523         qbyte           buf[4];
1524
1525         msg.data = buf;
1526         msg.maxsize = sizeof(buf);
1527         msg.cursize = 0;
1528
1529         MSG_WriteChar (&msg, svc_nop);
1530
1531         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1532                 SV_DropClient (true);   // if the message couldn't send, kick off
1533         client->last_message = realtime;
1534 }
1535
1536 /*
1537 =======================
1538 SV_SendClientMessages
1539 =======================
1540 */
1541 void SV_SendClientMessages (void)
1542 {
1543         int i, prepared = false;
1544
1545 // update frags, names, etc
1546         SV_UpdateToReliableMessages();
1547
1548 // build individual updates
1549         for (i = 0;i < MAX_SCOREBOARD;i++)
1550         {
1551                 if (!(host_client = svs.connectedclients[i]))
1552                         continue;
1553
1554                 if (host_client->deadsocket || !host_client->netconnection || host_client->message.overflowed)
1555                 {
1556                         SV_DropClient (true);   // if the message couldn't send, kick off
1557                         continue;
1558                 }
1559
1560                 if (host_client->spawned)
1561                 {
1562                         if (!prepared)
1563                         {
1564                                 prepared = true;
1565                                 // only prepare entities once per frame
1566                                 SV_PrepareEntitiesForSending();
1567                         }
1568                         if (!SV_SendClientDatagram (host_client))
1569                                 continue;
1570                 }
1571                 else
1572                 {
1573                 // the player isn't totally in the game yet
1574                 // send small keepalive messages if too much time has passed
1575                 // send a full message when the next signon stage has been requested
1576                 // some other message data (name changes, etc) may accumulate
1577                 // between signon stages
1578                         if (!host_client->sendsignon)
1579                         {
1580                                 if (realtime - host_client->last_message > 5)
1581                                         SV_SendNop (host_client);
1582                                 continue;       // don't send out non-signon messages
1583                         }
1584                 }
1585
1586                 if (host_client->message.cursize || host_client->dropasap)
1587                 {
1588                         if (!NetConn_CanSendMessage (host_client->netconnection))
1589                                 continue;
1590
1591                         if (host_client->dropasap)
1592                                 SV_DropClient (false);  // went to another level
1593                         else
1594                         {
1595                                 if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1)
1596                                         SV_DropClient (true);   // if the message couldn't send, kick off
1597                                 SZ_Clear (&host_client->message);
1598                                 host_client->last_message = realtime;
1599                                 host_client->sendsignon = false;
1600                         }
1601                 }
1602         }
1603
1604 // clear muzzle flashes
1605         SV_CleanupEnts();
1606 }
1607
1608
1609 /*
1610 ==============================================================================
1611
1612 SERVER SPAWNING
1613
1614 ==============================================================================
1615 */
1616
1617 /*
1618 ================
1619 SV_ModelIndex
1620
1621 ================
1622 */
1623 int SV_ModelIndex (const char *name)
1624 {
1625         int i;
1626
1627         if (!name || !name[0])
1628                 return 0;
1629
1630         for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
1631                 if (!strcmp(sv.model_precache[i], name))
1632                         return i;
1633         if (i==MAX_MODELS || !sv.model_precache[i])
1634                 Host_Error ("SV_ModelIndex: model %s not precached", name);
1635         return i;
1636 }
1637
1638 #ifdef SV_QUAKEENTITIES
1639 /*
1640 ================
1641 SV_CreateBaseline
1642
1643 ================
1644 */
1645 void SV_CreateBaseline (void)
1646 {
1647         int i, entnum, large;
1648         edict_t *svent;
1649
1650         // LordHavoc: clear *all* states (note just active ones)
1651         for (entnum = 0;entnum < sv.max_edicts;entnum++)
1652         {
1653                 // get the current server version
1654                 svent = EDICT_NUM(entnum);
1655
1656                 // LordHavoc: always clear state values, whether the entity is in use or not
1657                 ClearStateToDefault(&svent->e->baseline);
1658
1659                 if (svent->e->free)
1660                         continue;
1661                 if (entnum > MAX_SCOREBOARD && !svent->v->modelindex)
1662                         continue;
1663
1664                 // create entity baseline
1665                 VectorCopy (svent->v->origin, svent->e->baseline.origin);
1666                 VectorCopy (svent->v->angles, svent->e->baseline.angles);
1667                 svent->e->baseline.frame = svent->v->frame;
1668                 svent->e->baseline.skin = svent->v->skin;
1669                 if (entnum > 0 && entnum <= MAX_SCOREBOARD)
1670                 {
1671                         svent->e->baseline.colormap = entnum;
1672                         svent->e->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
1673                 }
1674                 else
1675                 {
1676                         svent->e->baseline.colormap = 0;
1677                         svent->e->baseline.modelindex = svent->v->modelindex;
1678                 }
1679
1680                 large = false;
1681                 if (svent->e->baseline.modelindex & 0xFF00 || svent->e->baseline.frame & 0xFF00)
1682                         large = true;
1683
1684                 // add to the message
1685                 if (large)
1686                         MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
1687                 else
1688                         MSG_WriteByte (&sv.signon, svc_spawnbaseline);
1689                 MSG_WriteShort (&sv.signon, entnum);
1690
1691                 if (large)
1692                 {
1693                         MSG_WriteShort (&sv.signon, svent->e->baseline.modelindex);
1694                         MSG_WriteShort (&sv.signon, svent->e->baseline.frame);
1695                 }
1696                 else
1697                 {
1698                         MSG_WriteByte (&sv.signon, svent->e->baseline.modelindex);
1699                         MSG_WriteByte (&sv.signon, svent->e->baseline.frame);
1700                 }
1701                 MSG_WriteByte (&sv.signon, svent->e->baseline.colormap);
1702                 MSG_WriteByte (&sv.signon, svent->e->baseline.skin);
1703                 for (i=0 ; i<3 ; i++)
1704                 {
1705                         MSG_WriteDPCoord(&sv.signon, svent->e->baseline.origin[i]);
1706                         MSG_WriteAngle(&sv.signon, svent->e->baseline.angles[i]);
1707                 }
1708         }
1709 }
1710 #endif
1711
1712
1713 /*
1714 ================
1715 SV_SendReconnect
1716
1717 Tell all the clients that the server is changing levels
1718 ================
1719 */
1720 void SV_SendReconnect (void)
1721 {
1722         char    data[128];
1723         sizebuf_t       msg;
1724
1725         msg.data = data;
1726         msg.cursize = 0;
1727         msg.maxsize = sizeof(data);
1728
1729         MSG_WriteChar (&msg, svc_stufftext);
1730         MSG_WriteString (&msg, "reconnect\n");
1731         NetConn_SendToAll (&msg, 5);
1732
1733         if (cls.state != ca_dedicated)
1734                 Cmd_ExecuteString ("reconnect\n", src_command);
1735 }
1736
1737
1738 /*
1739 ================
1740 SV_SaveSpawnparms
1741
1742 Grabs the current state of each client for saving across the
1743 transition to another level
1744 ================
1745 */
1746 void SV_SaveSpawnparms (void)
1747 {
1748         int             i, j;
1749
1750         svs.serverflags = pr_global_struct->serverflags;
1751
1752         for (i = 0;i < MAX_SCOREBOARD;i++)
1753         {
1754                 if (!(host_client = svs.connectedclients[i]))
1755                         continue;
1756
1757         // call the progs to get default spawn parms for the new client
1758                 pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
1759                 PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing");
1760                 for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
1761                         host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
1762         }
1763 }
1764
1765 void SV_IncreaseEdicts(void)
1766 {
1767         int i;
1768         edict_t *ent;
1769         int oldmax_edicts = sv.max_edicts;
1770         void *oldedictsengineprivate = sv.edictsengineprivate;
1771         void *oldedictsfields = sv.edictsfields;
1772         void *oldmoved_edicts = sv.moved_edicts;
1773
1774         if (sv.max_edicts >= MAX_EDICTS)
1775                 return;
1776
1777         // links don't survive the transition, so unlink everything
1778         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1779         {
1780                 if (!ent->e->free)
1781                         SV_UnlinkEdict(sv.edicts + i);
1782                 memset(&ent->e->areagrid, 0, sizeof(ent->e->areagrid));
1783         }
1784         SV_ClearWorld();
1785
1786         sv.max_edicts   = min(sv.max_edicts + 256, MAX_EDICTS);
1787         sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t));
1788         sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size);
1789         sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *));
1790
1791         memcpy(sv.edictsengineprivate, oldedictsengineprivate, oldmax_edicts * sizeof(edict_engineprivate_t));
1792         memcpy(sv.edictsfields, oldedictsfields, oldmax_edicts * pr_edict_size);
1793
1794         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1795         {
1796                 ent->e = sv.edictsengineprivate + i;
1797                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1798                 // link every entity except world
1799                 if (!ent->e->free)
1800                         SV_LinkEdict(ent, false);
1801         }
1802
1803         Mem_Free(oldedictsengineprivate);
1804         Mem_Free(oldedictsfields);
1805         Mem_Free(oldmoved_edicts);
1806 }
1807
1808 /*
1809 ================
1810 SV_SpawnServer
1811
1812 This is called at the start of each level
1813 ================
1814 */
1815 extern float            scr_centertime_off;
1816
1817 void SV_SpawnServer (const char *server)
1818 {
1819         edict_t *ent;
1820         int i;
1821         qbyte *entities;
1822
1823         // let's not have any servers with no name
1824         if (hostname.string[0] == 0)
1825                 Cvar_Set ("hostname", "UNNAMED");
1826         scr_centertime_off = 0;
1827
1828         Con_DPrintf ("SpawnServer: %s\n",server);
1829         svs.changelevel_issued = false;         // now safe to issue another
1830
1831 //
1832 // tell all connected clients that we are going to a new level
1833 //
1834         if (sv.active)
1835                 SV_SendReconnect();
1836         else
1837                 NetConn_OpenServerPorts(true);
1838
1839 //
1840 // make cvars consistant
1841 //
1842         if (coop.integer)
1843                 Cvar_SetValue ("deathmatch", 0);
1844         current_skill = bound(0, (int)(skill.value + 0.5), 3);
1845
1846         Cvar_SetValue ("skill", (float)current_skill);
1847
1848 //
1849 // set up the new server
1850 //
1851         Host_ClearMemory ();
1852
1853         memset (&sv, 0, sizeof(sv));
1854
1855         strcpy (sv.name, server);
1856
1857 // load progs to get entity field count
1858         PR_LoadProgs ();
1859
1860 // allocate server memory
1861         // start out with just enough room for clients and a reasonable estimate of entities
1862         sv.max_edicts = max(MAX_SCOREBOARD + 1, 512);
1863         sv.max_edicts = min(sv.max_edicts, MAX_EDICTS);
1864
1865         // clear the edict memory pool
1866         Mem_EmptyPool(sv_edicts_mempool);
1867         // edict_t structures (hidden from progs)
1868         sv.edicts = Mem_Alloc(sv_edicts_mempool, MAX_EDICTS * sizeof(edict_t));
1869         // engine private structures (hidden from progs)
1870         sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t));
1871         // progs fields, often accessed by server
1872         sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size);
1873         // used by PushMove to move back pushed entities
1874         sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *));
1875         for (i = 0;i < sv.max_edicts;i++)
1876         {
1877                 ent = sv.edicts + i;
1878                 ent->e = sv.edictsengineprivate + i;
1879                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1880         }
1881
1882         sv.datagram.maxsize = sizeof(sv.datagram_buf);
1883         sv.datagram.cursize = 0;
1884         sv.datagram.data = sv.datagram_buf;
1885
1886         sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
1887         sv.reliable_datagram.cursize = 0;
1888         sv.reliable_datagram.data = sv.reliable_datagram_buf;
1889
1890         sv.signon.maxsize = sizeof(sv.signon_buf);
1891         sv.signon.cursize = 0;
1892         sv.signon.data = sv.signon_buf;
1893
1894 // leave slots at start for clients only
1895         sv.num_edicts = MAX_SCOREBOARD+1;
1896
1897         sv.state = ss_loading;
1898         sv.paused = false;
1899
1900         sv.time = 1.0;
1901
1902         Mod_ClearUsed();
1903
1904         strcpy (sv.name, server);
1905         sprintf (sv.modelname,"maps/%s.bsp", server);
1906         sv.worldmodel = Mod_ForName(sv.modelname, false, true, true);
1907         if (!sv.worldmodel)
1908         {
1909                 Con_Printf ("Couldn't spawn server %s\n", sv.modelname);
1910                 sv.active = false;
1911                 return;
1912         }
1913         sv.models[1] = sv.worldmodel;
1914
1915 //
1916 // clear world interaction links
1917 //
1918         SV_ClearWorld ();
1919
1920         sv.sound_precache[0] = "";
1921
1922         sv.model_precache[0] = "";
1923         sv.model_precache[1] = sv.modelname;
1924         for (i = 1;i < sv.worldmodel->brushq1.numsubmodels;i++)
1925         {
1926                 sv.model_precache[i+1] = localmodels[i];
1927                 sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);
1928         }
1929
1930 //
1931 // load the rest of the entities
1932 //
1933         ent = EDICT_NUM(0);
1934         memset (ent->v, 0, progs->entityfields * 4);
1935         ent->e->free = false;
1936         ent->v->model = PR_SetString(sv.modelname);
1937         ent->v->modelindex = 1;         // world model
1938         ent->v->solid = SOLID_BSP;
1939         ent->v->movetype = MOVETYPE_PUSH;
1940
1941         if (coop.value)
1942                 pr_global_struct->coop = coop.integer;
1943         else
1944                 pr_global_struct->deathmatch = deathmatch.integer;
1945
1946         pr_global_struct->mapname = PR_SetString(sv.name);
1947
1948 // serverflags are for cross level information (sigils)
1949         pr_global_struct->serverflags = svs.serverflags;
1950
1951         // load replacement entity file if found
1952         entities = NULL;
1953         if (sv_entpatch.integer)
1954                 entities = FS_LoadFile(va("maps/%s.ent", sv.name), true);
1955         if (entities)
1956         {
1957                 Con_Printf("Loaded maps/%s.ent\n", sv.name);
1958                 ED_LoadFromFile (entities);
1959                 Mem_Free(entities);
1960         }
1961         else
1962                 ED_LoadFromFile (sv.worldmodel->brush.entities);
1963
1964
1965         // LordHavoc: clear world angles (to fix e3m3.bsp)
1966         VectorClear(sv.edicts->v->angles);
1967
1968         sv.active = true;
1969
1970 // all setup is completed, any further precache statements are errors
1971         sv.state = ss_active;
1972
1973 // run two frames to allow everything to settle
1974         for (i = 0;i < 2;i++)
1975         {
1976                 sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
1977                 SV_Physics ();
1978         }
1979
1980         Mod_PurgeUnused();
1981
1982 #ifdef QUAKEENTITIES
1983 // create a baseline for more efficient communications
1984         SV_CreateBaseline ();
1985 #endif
1986
1987 // send serverinfo to all connected clients
1988         for (i = 0;i < MAX_SCOREBOARD;i++)
1989                 if ((host_client = svs.connectedclients[i]))
1990                         SV_SendServerinfo(host_client);
1991
1992         Con_DPrintf ("Server spawned.\n");
1993         NetConn_Heartbeat (2);
1994 }
1995