]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_main.c
moved SV_FatPVS to model code
[xonotic/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 sv_writeentitiestoclient_pvsbytes;
378 qbyte sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
379
380 /*
381 =============
382 SV_WriteEntitiesToClient
383
384 =============
385 */
386 #ifdef QUAKEENTITIES
387 void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
388 {
389         int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects, lightsize;
390         int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
391         qbyte *pvs;
392         vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
393         float nextfullupdate, alphaf;
394         edict_t *ent;
395         eval_t *val;
396         entity_state_t *baseline; // LordHavoc: delta or startup baseline
397         model_t *model;
398
399         Mod_CheckLoaded(sv.worldmodel);
400
401 // find the client's PVS
402         VectorAdd (clent->v->origin, clent->v->view_ofs, testeye);
403         fatbytes = 0;
404         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
405                 fatbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
406
407         culled_pvs = 0;
408         culled_portal = 0;
409         culled_trace = 0;
410         visibleentities = 0;
411         totalentities = 0;
412
413         clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
414         // send all entities that touch the pvs
415         ent = NEXT_EDICT(sv.edicts);
416         for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
417         {
418                 bits = 0;
419
420                 // prevent delta compression against this frame (unless actually sent, which will restore this later)
421                 nextfullupdate = client->nextfullupdate[e];
422                 client->nextfullupdate[e] = -1;
423
424                 if (ent != clent) // LordHavoc: always send player
425                 {
426                         if ((val = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
427                         {
428                                 if (val->edict != clentnum)
429                                 {
430                                         // don't show to anyone else
431                                         continue;
432                                 }
433                                 else
434                                         bits |= U_VIEWMODEL; // show relative to the view
435                         }
436                         else
437                         {
438                                 // LordHavoc: never draw something told not to display to this client
439                                 if ((val = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)) && val->edict == clentnum)
440                                         continue;
441                                 if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum)
442                                         continue;
443                         }
444                 }
445
446                 glowsize = 0;
447
448                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size)))
449                         glowsize = (int) val->_float >> 2;
450                 if (glowsize > 255) glowsize = 255;
451                 if (glowsize < 0) glowsize = 0;
452
453                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail)))
454                 if (val->_float != 0)
455                         bits |= U_GLOWTRAIL;
456
457                 if (ent->v->modelindex >= 0 && ent->v->modelindex < MAX_MODELS && *PR_GetString(ent->v->model))
458                 {
459                         model = sv.models[(int)ent->v->modelindex];
460                         Mod_CheckLoaded(model);
461                 }
462                 else
463                 {
464                         model = NULL;
465                         if (ent != clent) // LordHavoc: always send player
466                                 if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
467                                         continue;
468                 }
469
470                 VectorCopy(ent->v->angles, angles);
471                 VectorCopy(ent->v->origin, origin);
472
473                 // ent has survived every check so far, check if it is visible
474                 if (ent != clent && ((bits & U_VIEWMODEL) == 0))
475                 {
476                         // use the predicted origin
477                         entmins[0] = origin[0] - 1.0f;
478                         entmins[1] = origin[1] - 1.0f;
479                         entmins[2] = origin[2] - 1.0f;
480                         entmaxs[0] = origin[0] + 1.0f;
481                         entmaxs[1] = origin[1] + 1.0f;
482                         entmaxs[2] = origin[2] + 1.0f;
483                         // using the model's bounding box to ensure things are visible regardless of their physics box
484                         if (model)
485                         {
486                                 if (ent->v->angles[0] || ent->v->angles[2]) // pitch and roll
487                                 {
488                                         VectorAdd(entmins, model->rotatedmins, entmins);
489                                         VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
490                                 }
491                                 else if (ent->v->angles[1])
492                                 {
493                                         VectorAdd(entmins, model->yawmins, entmins);
494                                         VectorAdd(entmaxs, model->yawmaxs, entmaxs);
495                                 }
496                                 else
497                                 {
498                                         VectorAdd(entmins, model->normalmins, entmins);
499                                         VectorAdd(entmaxs, model->normalmaxs, entmaxs);
500                                 }
501                         }
502
503                         totalentities++;
504
505                         // if not touching a visible leaf
506                         if (sv_cullentities_pvs.integer && fatbytes && sv.worldmodel && sv.worldmodel->brush.BoxTouchingPVS && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, sv_writeentitiestoclient_pvs, entmins, entmaxs))
507                         {
508                                 culled_pvs++;
509                                 continue;
510                         }
511
512                         // or not visible through the portals
513                         if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
514                         {
515                                 culled_portal++;
516                                 continue;
517                         }
518
519                         // don't try to cull embedded brush models with this, they're sometimes huge (spanning several rooms)
520                         if (sv_cullentities_trace.integer && (model == NULL || model->type != mod_brush || model->name[0] != '*'))
521                         {
522                                 // LordHavoc: test random offsets, to maximize chance of detection
523                                 testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
524                                 testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
525                                 testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
526
527                                 if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL).fraction == 1)
528                                         client->visibletime[e] = realtime + 1;
529                                 else
530                                 {
531                                         //test nearest point on bbox
532                                         testorigin[0] = bound(entmins[0], testeye[0], entmaxs[0]);
533                                         testorigin[1] = bound(entmins[1], testeye[1], entmaxs[1]);
534                                         testorigin[2] = bound(entmins[2], testeye[2], entmaxs[2]);
535
536                                         if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL).fraction == 1)
537                                                 client->visibletime[e] = realtime + 1;
538                                         else if (realtime > client->visibletime[e])
539                                         {
540                                                 culled_trace++;
541                                                 continue;
542                                         }
543                                 }
544                         }
545                         visibleentities++;
546                 }
547
548                 alphaf = 255.0f;
549                 scale = 16;
550                 glowcolor = 254;
551                 effects = ent->v->effects;
552
553                 if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
554                 if (val->_float != 0)
555                         alphaf = val->_float * 255.0f;
556
557                 // HalfLife support
558                 if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)))
559                 if (val->_float != 0)
560                         alphaf = val->_float;
561
562                 if (alphaf == 0.0f)
563                         alphaf = 255.0f;
564                 alpha = bound(0, alphaf, 255);
565
566                 if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
567                 if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
568                 if (scale < 0) scale = 0;
569                 if (scale > 255) scale = 255;
570
571                 if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color)))
572                 if (val->_float != 0)
573                         glowcolor = (int) val->_float;
574
575                 if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright)))
576                 if (val->_float != 0)
577                         effects |= EF_FULLBRIGHT;
578
579                 if (ent != clent)
580                 {
581                         if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
582                         {
583                                 if (model) // model
584                                 {
585                                         // don't send if flagged for NODRAW and there are no effects
586                                         if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
587                                                 continue;
588                                 }
589                                 else // no model and no effects
590                                         continue;
591                         }
592                 }
593
594                 if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32
595                 {
596                         Con_Printf ("packet overflow\n");
597                         // mark the rest of the entities so they can't be delta compressed against this frame
598                         for (;e < sv.num_edicts;e++)
599                         {
600                                 client->nextfullupdate[e] = -1;
601                                 client->visibletime[e] = -1;
602                         }
603                         return;
604                 }
605
606                 if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum)
607                         bits = bits | U_EXTERIORMODEL;
608
609 // send an update
610                 baseline = &ent->e->baseline;
611
612                 if (((int)ent->v->effects & EF_DELTA) && sv_deltacompress.integer)
613                 {
614                         // every half second a full update is forced
615                         if (realtime < client->nextfullupdate[e])
616                         {
617                                 bits |= U_DELTA;
618                                 baseline = &ent->e->deltabaseline;
619                         }
620                         else
621                                 nextfullupdate = realtime + 0.5f;
622                 }
623                 else
624                         nextfullupdate = realtime + 0.5f;
625
626                 // restore nextfullupdate since this is being sent for real
627                 client->nextfullupdate[e] = nextfullupdate;
628
629                 if (e >= 256)
630                         bits |= U_LONGENTITY;
631
632                 if (ent->v->movetype == MOVETYPE_STEP)
633                         bits |= U_STEP;
634
635                 // LordHavoc: old stuff, but rewritten to have more exact tolerances
636                 if (origin[0] != baseline->origin[0])                                                                                   bits |= U_ORIGIN1;
637                 if (origin[1] != baseline->origin[1])                                                                                   bits |= U_ORIGIN2;
638                 if (origin[2] != baseline->origin[2])                                                                                   bits |= U_ORIGIN3;
639                 if (((int)(angles[0]*(256.0/360.0)) & 255) != ((int)(baseline->angles[0]*(256.0/360.0)) & 255)) bits |= U_ANGLE1;
640                 if (((int)(angles[1]*(256.0/360.0)) & 255) != ((int)(baseline->angles[1]*(256.0/360.0)) & 255)) bits |= U_ANGLE2;
641                 if (((int)(angles[2]*(256.0/360.0)) & 255) != ((int)(baseline->angles[2]*(256.0/360.0)) & 255)) bits |= U_ANGLE3;
642                 if (baseline->colormap != (qbyte) ent->v->colormap)                                                             bits |= U_COLORMAP;
643                 if (baseline->skin != (qbyte) ent->v->skin)                                                                             bits |= U_SKIN;
644                 if ((baseline->frame & 0x00FF) != ((int) ent->v->frame & 0x00FF))                               bits |= U_FRAME;
645                 if ((baseline->effects & 0x00FF) != ((int) ent->v->effects & 0x00FF))                   bits |= U_EFFECTS;
646                 if ((baseline->modelindex & 0x00FF) != ((int) ent->v->modelindex & 0x00FF))             bits |= U_MODEL;
647
648                 // LordHavoc: new stuff
649                 if (baseline->alpha != alpha)                                                                                                   bits |= U_ALPHA;
650                 if (baseline->scale != scale)                                                                                                   bits |= U_SCALE;
651                 if (((int) baseline->effects & 0xFF00) != ((int) ent->v->effects & 0xFF00))             bits |= U_EFFECTS2;
652                 if (baseline->glowsize != glowsize)                                                                                             bits |= U_GLOWSIZE;
653                 if (baseline->glowcolor != glowcolor)                                                                                   bits |= U_GLOWCOLOR;
654                 if (((int) baseline->frame & 0xFF00) != ((int) ent->v->frame & 0xFF00))                 bits |= U_FRAME2;
655                 if (((int) baseline->frame & 0xFF00) != ((int) ent->v->modelindex & 0xFF00))            bits |= U_MODEL2;
656
657                 // update delta baseline
658                 VectorCopy(ent->v->origin, ent->e->deltabaseline.origin);
659                 VectorCopy(ent->v->angles, ent->e->deltabaseline.angles);
660                 ent->e->deltabaseline.colormap = ent->v->colormap;
661                 ent->e->deltabaseline.skin = ent->v->skin;
662                 ent->e->deltabaseline.frame = ent->v->frame;
663                 ent->e->deltabaseline.effects = ent->v->effects;
664                 ent->e->deltabaseline.modelindex = ent->v->modelindex;
665                 ent->e->deltabaseline.alpha = alpha;
666                 ent->e->deltabaseline.scale = scale;
667                 ent->e->deltabaseline.glowsize = glowsize;
668                 ent->e->deltabaseline.glowcolor = glowcolor;
669
670                 // write the message
671                 if (bits >= 16777216)
672                         bits |= U_EXTEND2;
673                 if (bits >= 65536)
674                         bits |= U_EXTEND1;
675                 if (bits >= 256)
676                         bits |= U_MOREBITS;
677                 bits |= U_SIGNAL;
678
679                 MSG_WriteByte (msg, bits);
680                 if (bits & U_MOREBITS)
681                         MSG_WriteByte (msg, bits>>8);
682                 // LordHavoc: extend bytes have to be written here due to delta compression
683                 if (bits & U_EXTEND1)
684                         MSG_WriteByte (msg, bits>>16);
685                 if (bits & U_EXTEND2)
686                         MSG_WriteByte (msg, bits>>24);
687
688                 // LordHavoc: old stuff
689                 if (bits & U_LONGENTITY)
690                         MSG_WriteShort (msg,e);
691                 else
692                         MSG_WriteByte (msg,e);
693                 if (bits & U_MODEL)             MSG_WriteByte (msg,     ent->v->modelindex);
694                 if (bits & U_FRAME)             MSG_WriteByte (msg, ent->v->frame);
695                 if (bits & U_COLORMAP)  MSG_WriteByte (msg, ent->v->colormap);
696                 if (bits & U_SKIN)              MSG_WriteByte (msg, ent->v->skin);
697                 if (bits & U_EFFECTS)   MSG_WriteByte (msg, ent->v->effects);
698                 if (bits & U_ORIGIN1)   MSG_WriteDPCoord (msg, origin[0]);
699                 if (bits & U_ANGLE1)    MSG_WriteAngle(msg, angles[0]);
700                 if (bits & U_ORIGIN2)   MSG_WriteDPCoord (msg, origin[1]);
701                 if (bits & U_ANGLE2)    MSG_WriteAngle(msg, angles[1]);
702                 if (bits & U_ORIGIN3)   MSG_WriteDPCoord (msg, origin[2]);
703                 if (bits & U_ANGLE3)    MSG_WriteAngle(msg, angles[2]);
704
705                 // LordHavoc: new stuff
706                 if (bits & U_ALPHA)             MSG_WriteByte(msg, alpha);
707                 if (bits & U_SCALE)             MSG_WriteByte(msg, scale);
708                 if (bits & U_EFFECTS2)  MSG_WriteByte(msg, (int)ent->v->effects >> 8);
709                 if (bits & U_GLOWSIZE)  MSG_WriteByte(msg, glowsize);
710                 if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
711                 if (bits & U_FRAME2)    MSG_WriteByte(msg, (int)ent->v->frame >> 8);
712                 if (bits & U_MODEL2)    MSG_WriteByte(msg, (int)ent->v->modelindex >> 8);
713         }
714
715         if (sv_cullentities_stats.integer)
716                 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);
717 }
718 #else
719 static int numsendentities;
720 static entity_state_t sendentities[MAX_EDICTS];
721 static entity_state_t *sendentitiesindex[MAX_EDICTS];
722
723 void SV_PrepareEntitiesForSending(void)
724 {
725         int e, i;
726         edict_t *ent;
727         entity_state_t cs;
728         // send all entities that touch the pvs
729         numsendentities = 0;
730         sendentitiesindex[0] = NULL;
731         for (e = 1, ent = NEXT_EDICT(sv.edicts);e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
732         {
733                 sendentitiesindex[e] = NULL;
734                 if (ent->e->free)
735                         continue;
736
737                 ClearStateToDefault(&cs);
738                 cs.active = true;
739                 cs.number = e;
740                 VectorCopy(ent->v->origin, cs.origin);
741                 VectorCopy(ent->v->angles, cs.angles);
742                 cs.flags = 0;
743                 cs.effects = (int)ent->v->effects;
744                 cs.colormap = (qbyte)ent->v->colormap;
745                 cs.skin = (qbyte)ent->v->skin;
746                 cs.frame = (qbyte)ent->v->frame;
747                 cs.viewmodelforclient = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
748                 cs.exteriormodelforclient = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
749                 cs.nodrawtoclient = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
750                 cs.drawonlytoclient = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
751                 cs.tagentity = GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
752                 cs.tagindex = (qbyte)GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
753                 i = (int)(GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
754                 cs.glowsize = (qbyte)bound(0, i, 255);
755                 if (GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
756                         cs.flags |= RENDER_GLOWTRAIL;
757
758                 cs.modelindex = 0;
759                 i = (int)ent->v->modelindex;
760                 if (i >= 1 && i < MAX_MODELS && *PR_GetString(ent->v->model))
761                         cs.modelindex = i;
762
763
764                 cs.alpha = 255;
765                 i = (int)(GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
766                 if (i)
767                         cs.alpha = (qbyte)bound(0, i, 255);
768                 // halflife
769                 i = (int)(GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
770                 if (i)
771                         cs.alpha = (qbyte)bound(0, i, 255);
772
773                 cs.scale = 16;
774                 i = (int)(GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
775                 if (i)
776                         cs.scale = (qbyte)bound(0, i, 255);
777
778                 cs.glowcolor = 254;
779                 i = (int)(GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
780                 if (i)
781                         cs.glowcolor = i;
782
783                 if (GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
784                         cs.effects |= EF_FULLBRIGHT;
785
786                 if (ent->v->movetype == MOVETYPE_STEP)
787                         cs.flags |= RENDER_STEP;
788                 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)
789                         cs.flags |= RENDER_LOWPRECISION;
790                 if (ent->v->colormap >= 1024)
791                         cs.flags |= RENDER_COLORMAPPED;
792                 if (cs.viewmodelforclient)
793                         cs.flags |= RENDER_VIEWMODEL; // show relative to the view
794
795                 cs.specialvisibilityradius = 0;
796                 if (cs.glowsize)
797                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, cs.glowsize * 4);
798                 if (cs.flags & RENDER_GLOWTRAIL)
799                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
800                 if (cs.effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
801                 {
802                         if (cs.effects & EF_BRIGHTFIELD)
803                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 80);
804                         if (cs.effects & EF_MUZZLEFLASH)
805                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
806                         if (cs.effects & EF_BRIGHTLIGHT)
807                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 400);
808                         if (cs.effects & EF_DIMLIGHT)
809                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
810                         if (cs.effects & EF_RED)
811                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
812                         if (cs.effects & EF_BLUE)
813                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
814                         if (cs.effects & EF_FLAME)
815                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 250);
816                         if (cs.effects & EF_STARDUST)
817                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
818                 }
819
820                 if (numsendentities >= MAX_EDICTS)
821                         continue;
822                 // we can omit invisible entities with no effects that are not clients
823                 // LordHavoc: this could kill tags attached to an invisible entity, I
824                 // just hope we never have to support that case
825                 if (cs.number > MAX_SCOREBOARD && ((cs.effects & EF_NODRAW) || (!cs.modelindex && !cs.specialvisibilityradius)))
826                         continue;
827                 sendentitiesindex[e] = sendentities + numsendentities;
828                 sendentities[numsendentities++] = cs;
829         }
830 }
831
832 static int sententitiesmark = 0;
833 static int sententities[MAX_EDICTS];
834 static int sententitiesconsideration[MAX_EDICTS];
835 static int sv_writeentitiestoclient_culled_pvs;
836 static int sv_writeentitiestoclient_culled_portal;
837 static int sv_writeentitiestoclient_culled_trace;
838 static int sv_writeentitiestoclient_visibleentities;
839 static int sv_writeentitiestoclient_totalentities;
840 //static entity_frame_t sv_writeentitiestoclient_entityframe;
841 static int sv_writeentitiestoclient_clentnum;
842 static vec3_t sv_writeentitiestoclient_testeye;
843 static client_t *sv_writeentitiestoclient_client;
844
845 void SV_MarkWriteEntityStateToClient(entity_state_t *s)
846 {
847         vec3_t entmins, entmaxs, lightmins, lightmaxs, testorigin;
848         model_t *model;
849         trace_t trace;
850         if (sententitiesconsideration[s->number] == sententitiesmark)
851                 return;
852         sententitiesconsideration[s->number] = sententitiesmark;
853         // viewmodels don't have visibility checking
854         if (s->viewmodelforclient)
855         {
856                 if (s->viewmodelforclient != sv_writeentitiestoclient_clentnum)
857                         return;
858         }
859         // never reject player
860         else if (s->number != sv_writeentitiestoclient_clentnum)
861         {
862                 // check various rejection conditions
863                 if (s->nodrawtoclient == sv_writeentitiestoclient_clentnum)
864                         return;
865                 if (s->drawonlytoclient && s->drawonlytoclient != sv_writeentitiestoclient_clentnum)
866                         return;
867                 if (s->effects & EF_NODRAW)
868                         return;
869                 // LordHavoc: only send entities with a model or important effects
870                 if (!s->modelindex && s->specialvisibilityradius == 0)
871                         return;
872                 if (s->tagentity)
873                 {
874                         // tag attached entities simply check their parent
875                         if (!sendentitiesindex[s->tagentity])
876                                 return;
877                         SV_MarkWriteEntityStateToClient(sendentitiesindex[s->tagentity]);
878                         if (sententities[s->tagentity] != sententitiesmark)
879                                 return;
880                 }
881                 // always send world submodels, they don't generate much traffic
882                 else if ((model = sv.models[s->modelindex]) == NULL || model->name[0] != '*')
883                 {
884                         Mod_CheckLoaded(model);
885                         // entity has survived every check so far, check if visible
886                         // enlarged box to account for prediction (not that there is
887                         // any currently, but still helps the 'run into a room and
888                         // watch items pop up' problem)
889                         entmins[0] = s->origin[0] - 32.0f;
890                         entmins[1] = s->origin[1] - 32.0f;
891                         entmins[2] = s->origin[2] - 32.0f;
892                         entmaxs[0] = s->origin[0] + 32.0f;
893                         entmaxs[1] = s->origin[1] + 32.0f;
894                         entmaxs[2] = s->origin[2] + 32.0f;
895                         // using the model's bounding box to ensure things are visible regardless of their physics box
896                         if (model)
897                         {
898                                 if (s->angles[0] || s->angles[2]) // pitch and roll
899                                 {
900                                         VectorAdd(entmins, model->rotatedmins, entmins);
901                                         VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
902                                 }
903                                 else if (s->angles[1])
904                                 {
905                                         VectorAdd(entmins, model->yawmins, entmins);
906                                         VectorAdd(entmaxs, model->yawmaxs, entmaxs);
907                                 }
908                                 else
909                                 {
910                                         VectorAdd(entmins, model->normalmins, entmins);
911                                         VectorAdd(entmaxs, model->normalmaxs, entmaxs);
912                                 }
913                         }
914                         lightmins[0] = min(entmins[0], s->origin[0] - s->specialvisibilityradius);
915                         lightmins[1] = min(entmins[1], s->origin[1] - s->specialvisibilityradius);
916                         lightmins[2] = min(entmins[2], s->origin[2] - s->specialvisibilityradius);
917                         lightmaxs[0] = min(entmaxs[0], s->origin[0] + s->specialvisibilityradius);
918                         lightmaxs[1] = min(entmaxs[1], s->origin[1] + s->specialvisibilityradius);
919                         lightmaxs[2] = min(entmaxs[2], s->origin[2] + s->specialvisibilityradius);
920                         sv_writeentitiestoclient_totalentities++;
921                         // if not touching a visible leaf
922                         if (sv_cullentities_pvs.integer && sv_writeentitiestoclient_pvsbytes && sv.worldmodel && sv.worldmodel->brush.BoxTouchingPVS && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, sv_writeentitiestoclient_pvs, lightmins, lightmaxs))
923                         {
924                                 sv_writeentitiestoclient_culled_pvs++;
925                                 return;
926                         }
927                         // or not visible through the portals
928                         if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, sv_writeentitiestoclient_testeye, lightmins, lightmaxs))
929                         {
930                                 sv_writeentitiestoclient_culled_portal++;
931                                 return;
932                         }
933                         // or not seen by random tracelines
934                         if (sv_cullentities_trace.integer)
935                         {
936                                 // LordHavoc: test center first
937                                 testorigin[0] = (entmins[0] + entmaxs[0]) * 0.5f;
938                                 testorigin[1] = (entmins[1] + entmaxs[1]) * 0.5f;
939                                 testorigin[2] = (entmins[2] + entmaxs[2]) * 0.5f;
940                                 trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
941                                 if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
942                                         sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
943                                 else
944                                 {
945                                         // LordHavoc: test random offsets, to maximize chance of detection
946                                         testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
947                                         testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
948                                         testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
949                                         trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
950                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
951                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
952                                         else
953                                         {
954                                                 if (s->specialvisibilityradius)
955                                                 {
956                                                         // LordHavoc: test random offsets, to maximize chance of detection
957                                                         testorigin[0] = lhrandom(lightmins[0], lightmaxs[0]);
958                                                         testorigin[1] = lhrandom(lightmins[1], lightmaxs[1]);
959                                                         testorigin[2] = lhrandom(lightmins[2], lightmaxs[2]);
960                                                         trace = SV_Move(sv_writeentitiestoclient_testeye, vec3_origin, vec3_origin, testorigin, MOVE_WORLDONLY, NULL);
961                                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
962                                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
963                                                 }
964                                         }
965                                 }
966                                 if (realtime > sv_writeentitiestoclient_client->visibletime[s->number])
967                                 {
968                                         sv_writeentitiestoclient_culled_trace++;
969                                         return;
970                                 }
971                         }
972                         sv_writeentitiestoclient_visibleentities++;
973                 }
974         }
975         // this just marks it for sending
976         // FIXME: it would be more efficient to send here, but the entity
977         // compressor isn't that flexible
978         sententities[s->number] = sententitiesmark;
979 }
980
981 void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg)
982 {
983         int i;
984         vec3_t testorigin;
985         entity_state_t *s;
986         entity_database4_t *d;
987         int maxbytes, n, startnumber;
988         entity_state_t *e, inactiveentitystate;
989         sizebuf_t buf;
990         qbyte data[128];
991         // prepare the buffer
992         memset(&buf, 0, sizeof(buf));
993         buf.data = data;
994         buf.maxsize = sizeof(data);
995
996         // this state's number gets played around with later
997         ClearStateToDefault(&inactiveentitystate);
998         //inactiveentitystate = defaultstate;
999
1000         sv_writeentitiestoclient_client = client;
1001
1002         sv_writeentitiestoclient_culled_pvs = 0;
1003         sv_writeentitiestoclient_culled_portal = 0;
1004         sv_writeentitiestoclient_culled_trace = 0;
1005         sv_writeentitiestoclient_visibleentities = 0;
1006         sv_writeentitiestoclient_totalentities = 0;
1007
1008         Mod_CheckLoaded(sv.worldmodel);
1009
1010 // find the client's PVS
1011         // the real place being tested from
1012         VectorAdd(clent->v->origin, clent->v->view_ofs, sv_writeentitiestoclient_testeye);
1013         sv_writeentitiestoclient_pvsbytes = 0;
1014         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
1015                 sv_writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv_writeentitiestoclient_testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
1016
1017         sv_writeentitiestoclient_clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
1018
1019         sententitiesmark++;
1020
1021         // the place being reported (to consider the fact the client still
1022         // applies the view_ofs[2], so we have to only send the fractional part
1023         // of view_ofs[2], undoing what the client will redo)
1024         VectorCopy(sv_writeentitiestoclient_testeye, testorigin);
1025         i = (int) clent->v->view_ofs[2] & 255;
1026         if (i >= 128)
1027                 i -= 256;
1028         testorigin[2] -= (float) i;
1029
1030         for (i = 0;i < numsendentities;i++)
1031                 SV_MarkWriteEntityStateToClient(sendentities + i);
1032
1033         d = client->entitydatabase4;
1034         // calculate maximum bytes to allow in this packet
1035         // deduct 4 to account for the end data
1036         maxbytes = min(msg->maxsize, MAX_PACKETFRAGMENT) - 4;
1037
1038         d->currentcommit = d->commit + EntityFrame4_SV_ChooseCommitToReplace(d);
1039         d->currentcommit->numentities = 0;
1040         d->currentcommit->framenum = ++client->entityframenumber;
1041         MSG_WriteByte(msg, svc_entities);
1042         MSG_WriteLong(msg, d->referenceframenum);
1043         MSG_WriteLong(msg, d->currentcommit->framenum);
1044         if (d->currententitynumber >= sv.max_edicts)
1045                 startnumber = 1;
1046         else
1047                 startnumber = bound(1, d->currententitynumber, sv.max_edicts - 1);
1048         MSG_WriteShort(msg, startnumber);
1049         // reset currententitynumber so if the loop does not break it we will
1050         // start at beginning next frame (if it does break, it will set it)
1051         d->currententitynumber = 1;
1052         for (i = 0, n = startnumber;n < sv.max_edicts;n++)
1053         {
1054                 // find the old state to delta from
1055                 e = EntityFrame4_GetReferenceEntity(d, n);
1056                 // prepare the buffer
1057                 SZ_Clear(&buf);
1058                 // make the message
1059                 if (sententities[n] == sententitiesmark)
1060                 {
1061                         // entity exists, build an update (if empty there is no change)
1062                         // find the state in the list
1063                         for (;i < numsendentities && sendentities[i].number < n;i++);
1064                         s = sendentities + i;
1065                         if (s->number != n)
1066                                 Sys_Error("SV_WriteEntitiesToClient: s->number != n\n");
1067                         // build the update
1068                         if (s->exteriormodelforclient && s->exteriormodelforclient == sv_writeentitiestoclient_clentnum)
1069                         {
1070                                 s->flags |= RENDER_EXTERIORMODEL;
1071                                 EntityState_Write(s, &buf, e);
1072                                 s->flags &= ~RENDER_EXTERIORMODEL;
1073                         }
1074                         else
1075                                 EntityState_Write(s, &buf, e);
1076                 }
1077                 else
1078                 {
1079                         s = &inactiveentitystate;
1080                         s->number = n;
1081                         if (e->active)
1082                         {
1083                                 // entity used to exist but doesn't anymore, send remove
1084                                 MSG_WriteShort(&buf, n | 0x8000);
1085                         }
1086                 }
1087                 // if the commit is full, we're done this frame
1088                 if (msg->cursize + buf.cursize > maxbytes)
1089                 {
1090                         // next frame we will continue where we left off
1091                         break;
1092                 }
1093                 // add the entity to the commit
1094                 EntityFrame4_AddCommitEntity(d, s);
1095                 // if the message is empty, skip out now
1096                 if (buf.cursize)
1097                 {
1098                         // write the message to the packet
1099                         SZ_Write(msg, buf.data, buf.cursize);
1100                 }
1101         }
1102         d->currententitynumber = n;
1103
1104         // remove world message (invalid, and thus a good terminator)
1105         MSG_WriteShort(msg, 0x8000);
1106         // write the number of the end entity
1107         MSG_WriteShort(msg, d->currententitynumber);
1108         // just to be sure
1109         d->currentcommit = NULL;
1110
1111         if (sv_cullentities_stats.integer)
1112                 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);
1113 }
1114 #endif
1115
1116 /*
1117 =============
1118 SV_CleanupEnts
1119
1120 =============
1121 */
1122 void SV_CleanupEnts (void)
1123 {
1124         int             e;
1125         edict_t *ent;
1126
1127         ent = NEXT_EDICT(sv.edicts);
1128         for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
1129                 ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH;
1130 }
1131
1132 /*
1133 ==================
1134 SV_WriteClientdataToMessage
1135
1136 ==================
1137 */
1138 void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
1139 {
1140         int             bits;
1141         int             i;
1142         edict_t *other;
1143         int             items;
1144         eval_t  *val;
1145         vec3_t  punchvector;
1146         qbyte   viewzoom;
1147
1148 //
1149 // send a damage message
1150 //
1151         if (ent->v->dmg_take || ent->v->dmg_save)
1152         {
1153                 other = PROG_TO_EDICT(ent->v->dmg_inflictor);
1154                 MSG_WriteByte (msg, svc_damage);
1155                 MSG_WriteByte (msg, ent->v->dmg_save);
1156                 MSG_WriteByte (msg, ent->v->dmg_take);
1157                 for (i=0 ; i<3 ; i++)
1158                         MSG_WriteDPCoord (msg, other->v->origin[i] + 0.5*(other->v->mins[i] + other->v->maxs[i]));
1159
1160                 ent->v->dmg_take = 0;
1161                 ent->v->dmg_save = 0;
1162         }
1163
1164 //
1165 // send the current viewpos offset from the view entity
1166 //
1167         SV_SetIdealPitch ();            // how much to look up / down ideally
1168
1169 // a fixangle might get lost in a dropped packet.  Oh well.
1170         if ( ent->v->fixangle )
1171         {
1172                 MSG_WriteByte (msg, svc_setangle);
1173                 for (i=0 ; i < 3 ; i++)
1174                         MSG_WriteAngle (msg, ent->v->angles[i] );
1175                 ent->v->fixangle = 0;
1176         }
1177
1178         bits = 0;
1179
1180         if (ent->v->view_ofs[2] != DEFAULT_VIEWHEIGHT)
1181                 bits |= SU_VIEWHEIGHT;
1182
1183         if (ent->v->idealpitch)
1184                 bits |= SU_IDEALPITCH;
1185
1186 // stuff the sigil bits into the high bits of items for sbar, or else
1187 // mix in items2
1188         val = GETEDICTFIELDVALUE(ent, eval_items2);
1189
1190         if (val)
1191                 items = (int)ent->v->items | ((int)val->_float << 23);
1192         else
1193                 items = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
1194
1195         bits |= SU_ITEMS;
1196
1197         if ( (int)ent->v->flags & FL_ONGROUND)
1198                 bits |= SU_ONGROUND;
1199
1200         if ( ent->v->waterlevel >= 2)
1201                 bits |= SU_INWATER;
1202
1203         // dpprotocol
1204         VectorClear(punchvector);
1205         if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
1206                 VectorCopy(val->vector, punchvector);
1207
1208         i = 255;
1209         if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
1210         {
1211                 i = val->_float * 255.0f;
1212                 if (i == 0)
1213                         i = 255;
1214                 else
1215                         i = bound(0, i, 255);
1216         }
1217         viewzoom = i;
1218
1219         if (viewzoom != 255)
1220                 bits |= SU_VIEWZOOM;
1221
1222         for (i=0 ; i<3 ; i++)
1223         {
1224                 if (ent->v->punchangle[i])
1225                         bits |= (SU_PUNCH1<<i);
1226                 if (punchvector[i]) // dpprotocol
1227                         bits |= (SU_PUNCHVEC1<<i); // dpprotocol
1228                 if (ent->v->velocity[i])
1229                         bits |= (SU_VELOCITY1<<i);
1230         }
1231
1232         if (ent->v->weaponframe)
1233                 bits |= SU_WEAPONFRAME;
1234
1235         if (ent->v->armorvalue)
1236                 bits |= SU_ARMOR;
1237
1238         bits |= SU_WEAPON;
1239
1240         if (bits >= 65536)
1241                 bits |= SU_EXTEND1;
1242         if (bits >= 16777216)
1243                 bits |= SU_EXTEND2;
1244
1245 // send the data
1246
1247         MSG_WriteByte (msg, svc_clientdata);
1248         MSG_WriteShort (msg, bits);
1249         if (bits & SU_EXTEND1)
1250                 MSG_WriteByte(msg, bits >> 16);
1251         if (bits & SU_EXTEND2)
1252                 MSG_WriteByte(msg, bits >> 24);
1253
1254         if (bits & SU_VIEWHEIGHT)
1255                 MSG_WriteChar (msg, ent->v->view_ofs[2]);
1256
1257         if (bits & SU_IDEALPITCH)
1258                 MSG_WriteChar (msg, ent->v->idealpitch);
1259
1260         for (i=0 ; i<3 ; i++)
1261         {
1262                 if (bits & (SU_PUNCH1<<i))
1263                         MSG_WritePreciseAngle(msg, ent->v->punchangle[i]); // dpprotocol
1264                 if (bits & (SU_PUNCHVEC1<<i)) // dpprotocol
1265                         MSG_WriteDPCoord(msg, punchvector[i]); // dpprotocol
1266                 if (bits & (SU_VELOCITY1<<i))
1267                         MSG_WriteChar (msg, ent->v->velocity[i]/16);
1268         }
1269
1270 // [always sent]        if (bits & SU_ITEMS)
1271         MSG_WriteLong (msg, items);
1272
1273         if (bits & SU_WEAPONFRAME)
1274                 MSG_WriteByte (msg, ent->v->weaponframe);
1275         if (bits & SU_ARMOR)
1276                 MSG_WriteByte (msg, ent->v->armorvalue);
1277         if (bits & SU_WEAPON)
1278                 MSG_WriteByte (msg, SV_ModelIndex(PR_GetString(ent->v->weaponmodel)));
1279
1280         MSG_WriteShort (msg, ent->v->health);
1281         MSG_WriteByte (msg, ent->v->currentammo);
1282         MSG_WriteByte (msg, ent->v->ammo_shells);
1283         MSG_WriteByte (msg, ent->v->ammo_nails);
1284         MSG_WriteByte (msg, ent->v->ammo_rockets);
1285         MSG_WriteByte (msg, ent->v->ammo_cells);
1286
1287         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1288         {
1289                 for(i=0;i<32;i++)
1290                 {
1291                         if ( ((int)ent->v->weapon) & (1<<i) )
1292                         {
1293                                 MSG_WriteByte (msg, i);
1294                                 break;
1295                         }
1296                 }
1297         }
1298         else
1299         {
1300                 MSG_WriteByte (msg, ent->v->weapon);
1301         }
1302
1303         if (bits & SU_VIEWZOOM)
1304                 MSG_WriteByte (msg, viewzoom);
1305 }
1306
1307 /*
1308 =======================
1309 SV_SendClientDatagram
1310 =======================
1311 */
1312 static qbyte sv_sendclientdatagram_buf[MAX_DATAGRAM]; // FIXME?
1313 qboolean SV_SendClientDatagram (client_t *client)
1314 {
1315         sizebuf_t       msg;
1316
1317         msg.data = sv_sendclientdatagram_buf;
1318         msg.maxsize = sizeof(sv_sendclientdatagram_buf);
1319         msg.cursize = 0;
1320
1321         MSG_WriteByte (&msg, svc_time);
1322         MSG_WriteFloat (&msg, sv.time);
1323
1324         // add the client specific data to the datagram
1325         SV_WriteClientdataToMessage (client->edict, &msg);
1326
1327         SV_WriteEntitiesToClient (client, client->edict, &msg);
1328
1329         // copy the server datagram if there is space
1330         if (msg.cursize + sv.datagram.cursize < msg.maxsize)
1331                 SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
1332
1333 // send the datagram
1334         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1335         {
1336                 SV_DropClient (true);// if the message couldn't send, kick off
1337                 return false;
1338         }
1339
1340         return true;
1341 }
1342
1343 /*
1344 =======================
1345 SV_UpdateToReliableMessages
1346 =======================
1347 */
1348 void SV_UpdateToReliableMessages (void)
1349 {
1350         int i, j;
1351         client_t *client;
1352         eval_t *val;
1353         char *s;
1354
1355 // check for changes to be sent over the reliable streams
1356         for (i = 0;i < MAX_SCOREBOARD;i++)
1357         {
1358                 // only update the client fields if they've spawned in
1359                 if ((host_client = svs.connectedclients[i]) && host_client->spawned)
1360                 {
1361                         // update the host_client fields we care about according to the entity fields
1362                         sv_player = host_client->edict;
1363                         s = PR_GetString(sv_player->v->netname);
1364                         if (s != host_client->name)
1365                         {
1366                                 if (s == NULL)
1367                                         s = "";
1368                                 // point the string back at host_client->name to keep it safe
1369                                 strncpy(host_client->name, s, sizeof(host_client->name) - 1);
1370                                 sv_player->v->netname = PR_SetString(host_client->name);
1371                         }
1372                         if ((val = GETEDICTFIELDVALUE(sv_player, eval_clientcolors)) && host_client->colors != val->_float)
1373                                 host_client->colors = val->_float;
1374                         host_client->frags = sv_player->v->frags;
1375                         if (gamemode == GAME_NEHAHRA)
1376                                 if ((val = GETEDICTFIELDVALUE(sv_player, eval_pmodel)) && host_client->pmodel != val->_float)
1377                                         host_client->pmodel = val->_float;
1378
1379                         // if the fields changed, send messages about the changes
1380                         if (strcmp(host_client->old_name, host_client->name))
1381                         {
1382                                 strcpy(host_client->old_name, host_client->name);
1383                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1384                                 {
1385                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1386                                                 continue;
1387                                         MSG_WriteByte (&client->message, svc_updatename);
1388                                         MSG_WriteByte (&client->message, i);
1389                                         MSG_WriteString (&client->message, host_client->name);
1390                                 }
1391                         }
1392                         if (host_client->old_colors != host_client->colors)
1393                         {
1394                                 host_client->old_colors = host_client->colors;
1395                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1396                                 {
1397                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1398                                                 continue;
1399                                         MSG_WriteByte (&client->message, svc_updatecolors);
1400                                         MSG_WriteByte (&client->message, i);
1401                                         MSG_WriteByte (&client->message, host_client->colors);
1402                                 }
1403                         }
1404                         if (host_client->old_frags != host_client->frags)
1405                         {
1406                                 host_client->old_frags = host_client->frags;
1407                                 for (j = 0;j < MAX_SCOREBOARD;j++)
1408                                 {
1409                                         if (!(client = svs.connectedclients[j]) || !client->spawned)
1410                                                 continue;
1411                                         MSG_WriteByte (&client->message, svc_updatefrags);
1412                                         MSG_WriteByte (&client->message, i);
1413                                         MSG_WriteShort (&client->message, host_client->frags);
1414                                 }
1415                         }
1416                 }
1417         }
1418
1419         for (j = 0;j < MAX_SCOREBOARD;j++)
1420                 if ((client = svs.connectedclients[j]))
1421                         SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
1422
1423         SZ_Clear (&sv.reliable_datagram);
1424 }
1425
1426
1427 /*
1428 =======================
1429 SV_SendNop
1430
1431 Send a nop message without trashing or sending the accumulated client
1432 message buffer
1433 =======================
1434 */
1435 void SV_SendNop (client_t *client)
1436 {
1437         sizebuf_t       msg;
1438         qbyte           buf[4];
1439
1440         msg.data = buf;
1441         msg.maxsize = sizeof(buf);
1442         msg.cursize = 0;
1443
1444         MSG_WriteChar (&msg, svc_nop);
1445
1446         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1447                 SV_DropClient (true);   // if the message couldn't send, kick off
1448         client->last_message = realtime;
1449 }
1450
1451 /*
1452 =======================
1453 SV_SendClientMessages
1454 =======================
1455 */
1456 void SV_SendClientMessages (void)
1457 {
1458         int i, prepared = false;
1459
1460 // update frags, names, etc
1461         SV_UpdateToReliableMessages();
1462
1463 // build individual updates
1464         for (i = 0;i < MAX_SCOREBOARD;i++)
1465         {
1466                 if (!(host_client = svs.connectedclients[i]))
1467                         continue;
1468
1469                 if (host_client->deadsocket || !host_client->netconnection || host_client->message.overflowed)
1470                 {
1471                         SV_DropClient (true);   // if the message couldn't send, kick off
1472                         continue;
1473                 }
1474
1475                 if (host_client->spawned)
1476                 {
1477                         if (!prepared)
1478                         {
1479                                 prepared = true;
1480                                 // only prepare entities once per frame
1481                                 SV_PrepareEntitiesForSending();
1482                         }
1483                         if (!SV_SendClientDatagram (host_client))
1484                                 continue;
1485                 }
1486                 else
1487                 {
1488                 // the player isn't totally in the game yet
1489                 // send small keepalive messages if too much time has passed
1490                 // send a full message when the next signon stage has been requested
1491                 // some other message data (name changes, etc) may accumulate
1492                 // between signon stages
1493                         if (!host_client->sendsignon)
1494                         {
1495                                 if (realtime - host_client->last_message > 5)
1496                                         SV_SendNop (host_client);
1497                                 continue;       // don't send out non-signon messages
1498                         }
1499                 }
1500
1501                 if (host_client->message.cursize || host_client->dropasap)
1502                 {
1503                         if (!NetConn_CanSendMessage (host_client->netconnection))
1504                                 continue;
1505
1506                         if (host_client->dropasap)
1507                                 SV_DropClient (false);  // went to another level
1508                         else
1509                         {
1510                                 if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1)
1511                                         SV_DropClient (true);   // if the message couldn't send, kick off
1512                                 SZ_Clear (&host_client->message);
1513                                 host_client->last_message = realtime;
1514                                 host_client->sendsignon = false;
1515                         }
1516                 }
1517         }
1518
1519 // clear muzzle flashes
1520         SV_CleanupEnts();
1521 }
1522
1523
1524 /*
1525 ==============================================================================
1526
1527 SERVER SPAWNING
1528
1529 ==============================================================================
1530 */
1531
1532 /*
1533 ================
1534 SV_ModelIndex
1535
1536 ================
1537 */
1538 int SV_ModelIndex (const char *name)
1539 {
1540         int i;
1541
1542         if (!name || !name[0])
1543                 return 0;
1544
1545         for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
1546                 if (!strcmp(sv.model_precache[i], name))
1547                         return i;
1548         if (i==MAX_MODELS || !sv.model_precache[i])
1549                 Host_Error ("SV_ModelIndex: model %s not precached", name);
1550         return i;
1551 }
1552
1553 #ifdef SV_QUAKEENTITIES
1554 /*
1555 ================
1556 SV_CreateBaseline
1557
1558 ================
1559 */
1560 void SV_CreateBaseline (void)
1561 {
1562         int i, entnum, large;
1563         edict_t *svent;
1564
1565         // LordHavoc: clear *all* states (note just active ones)
1566         for (entnum = 0;entnum < sv.max_edicts;entnum++)
1567         {
1568                 // get the current server version
1569                 svent = EDICT_NUM(entnum);
1570
1571                 // LordHavoc: always clear state values, whether the entity is in use or not
1572                 ClearStateToDefault(&svent->e->baseline);
1573
1574                 if (svent->e->free)
1575                         continue;
1576                 if (entnum > MAX_SCOREBOARD && !svent->v->modelindex)
1577                         continue;
1578
1579                 // create entity baseline
1580                 VectorCopy (svent->v->origin, svent->e->baseline.origin);
1581                 VectorCopy (svent->v->angles, svent->e->baseline.angles);
1582                 svent->e->baseline.frame = svent->v->frame;
1583                 svent->e->baseline.skin = svent->v->skin;
1584                 if (entnum > 0 && entnum <= MAX_SCOREBOARD)
1585                 {
1586                         svent->e->baseline.colormap = entnum;
1587                         svent->e->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
1588                 }
1589                 else
1590                 {
1591                         svent->e->baseline.colormap = 0;
1592                         svent->e->baseline.modelindex = svent->v->modelindex;
1593                 }
1594
1595                 large = false;
1596                 if (svent->e->baseline.modelindex & 0xFF00 || svent->e->baseline.frame & 0xFF00)
1597                         large = true;
1598
1599                 // add to the message
1600                 if (large)
1601                         MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
1602                 else
1603                         MSG_WriteByte (&sv.signon, svc_spawnbaseline);
1604                 MSG_WriteShort (&sv.signon, entnum);
1605
1606                 if (large)
1607                 {
1608                         MSG_WriteShort (&sv.signon, svent->e->baseline.modelindex);
1609                         MSG_WriteShort (&sv.signon, svent->e->baseline.frame);
1610                 }
1611                 else
1612                 {
1613                         MSG_WriteByte (&sv.signon, svent->e->baseline.modelindex);
1614                         MSG_WriteByte (&sv.signon, svent->e->baseline.frame);
1615                 }
1616                 MSG_WriteByte (&sv.signon, svent->e->baseline.colormap);
1617                 MSG_WriteByte (&sv.signon, svent->e->baseline.skin);
1618                 for (i=0 ; i<3 ; i++)
1619                 {
1620                         MSG_WriteDPCoord(&sv.signon, svent->e->baseline.origin[i]);
1621                         MSG_WriteAngle(&sv.signon, svent->e->baseline.angles[i]);
1622                 }
1623         }
1624 }
1625 #endif
1626
1627
1628 /*
1629 ================
1630 SV_SendReconnect
1631
1632 Tell all the clients that the server is changing levels
1633 ================
1634 */
1635 void SV_SendReconnect (void)
1636 {
1637         char    data[128];
1638         sizebuf_t       msg;
1639
1640         msg.data = data;
1641         msg.cursize = 0;
1642         msg.maxsize = sizeof(data);
1643
1644         MSG_WriteChar (&msg, svc_stufftext);
1645         MSG_WriteString (&msg, "reconnect\n");
1646         NetConn_SendToAll (&msg, 5);
1647
1648         if (cls.state != ca_dedicated)
1649                 Cmd_ExecuteString ("reconnect\n", src_command);
1650 }
1651
1652
1653 /*
1654 ================
1655 SV_SaveSpawnparms
1656
1657 Grabs the current state of each client for saving across the
1658 transition to another level
1659 ================
1660 */
1661 void SV_SaveSpawnparms (void)
1662 {
1663         int             i, j;
1664
1665         svs.serverflags = pr_global_struct->serverflags;
1666
1667         for (i = 0;i < MAX_SCOREBOARD;i++)
1668         {
1669                 if (!(host_client = svs.connectedclients[i]))
1670                         continue;
1671
1672         // call the progs to get default spawn parms for the new client
1673                 pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
1674                 PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing");
1675                 for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
1676                         host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
1677         }
1678 }
1679
1680 void SV_IncreaseEdicts(void)
1681 {
1682         int i;
1683         edict_t *ent;
1684         int oldmax_edicts = sv.max_edicts;
1685         void *oldedictsengineprivate = sv.edictsengineprivate;
1686         void *oldedictsfields = sv.edictsfields;
1687         void *oldmoved_edicts = sv.moved_edicts;
1688
1689         if (sv.max_edicts >= MAX_EDICTS)
1690                 return;
1691
1692         // links don't survive the transition, so unlink everything
1693         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1694         {
1695                 if (!ent->e->free)
1696                         SV_UnlinkEdict(sv.edicts + i);
1697                 memset(&ent->e->areagrid, 0, sizeof(ent->e->areagrid));
1698         }
1699         SV_ClearWorld();
1700
1701         sv.max_edicts   = min(sv.max_edicts + 256, MAX_EDICTS);
1702         sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t));
1703         sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size);
1704         sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *));
1705
1706         memcpy(sv.edictsengineprivate, oldedictsengineprivate, oldmax_edicts * sizeof(edict_engineprivate_t));
1707         memcpy(sv.edictsfields, oldedictsfields, oldmax_edicts * pr_edict_size);
1708
1709         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1710         {
1711                 ent->e = sv.edictsengineprivate + i;
1712                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1713                 // link every entity except world
1714                 if (!ent->e->free)
1715                         SV_LinkEdict(ent, false);
1716         }
1717
1718         Mem_Free(oldedictsengineprivate);
1719         Mem_Free(oldedictsfields);
1720         Mem_Free(oldmoved_edicts);
1721 }
1722
1723 /*
1724 ================
1725 SV_SpawnServer
1726
1727 This is called at the start of each level
1728 ================
1729 */
1730 extern float            scr_centertime_off;
1731
1732 void SV_SpawnServer (const char *server)
1733 {
1734         edict_t *ent;
1735         int i;
1736         qbyte *entities;
1737
1738         // let's not have any servers with no name
1739         if (hostname.string[0] == 0)
1740                 Cvar_Set ("hostname", "UNNAMED");
1741         scr_centertime_off = 0;
1742
1743         Con_DPrintf ("SpawnServer: %s\n",server);
1744         svs.changelevel_issued = false;         // now safe to issue another
1745
1746 //
1747 // tell all connected clients that we are going to a new level
1748 //
1749         if (sv.active)
1750                 SV_SendReconnect();
1751         else
1752                 NetConn_OpenServerPorts(true);
1753
1754 //
1755 // make cvars consistant
1756 //
1757         if (coop.integer)
1758                 Cvar_SetValue ("deathmatch", 0);
1759         current_skill = bound(0, (int)(skill.value + 0.5), 3);
1760
1761         Cvar_SetValue ("skill", (float)current_skill);
1762
1763 //
1764 // set up the new server
1765 //
1766         Host_ClearMemory ();
1767
1768         memset (&sv, 0, sizeof(sv));
1769
1770         strcpy (sv.name, server);
1771
1772 // load progs to get entity field count
1773         PR_LoadProgs ();
1774
1775 // allocate server memory
1776         // start out with just enough room for clients and a reasonable estimate of entities
1777         sv.max_edicts = max(MAX_SCOREBOARD + 1, 512);
1778         sv.max_edicts = min(sv.max_edicts, MAX_EDICTS);
1779
1780         // clear the edict memory pool
1781         Mem_EmptyPool(sv_edicts_mempool);
1782         // edict_t structures (hidden from progs)
1783         sv.edicts = Mem_Alloc(sv_edicts_mempool, MAX_EDICTS * sizeof(edict_t));
1784         // engine private structures (hidden from progs)
1785         sv.edictsengineprivate = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_engineprivate_t));
1786         // progs fields, often accessed by server
1787         sv.edictsfields = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * pr_edict_size);
1788         // used by PushMove to move back pushed entities
1789         sv.moved_edicts = Mem_Alloc(sv_edicts_mempool, sv.max_edicts * sizeof(edict_t *));
1790         for (i = 0;i < sv.max_edicts;i++)
1791         {
1792                 ent = sv.edicts + i;
1793                 ent->e = sv.edictsengineprivate + i;
1794                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1795         }
1796
1797         sv.datagram.maxsize = sizeof(sv.datagram_buf);
1798         sv.datagram.cursize = 0;
1799         sv.datagram.data = sv.datagram_buf;
1800
1801         sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
1802         sv.reliable_datagram.cursize = 0;
1803         sv.reliable_datagram.data = sv.reliable_datagram_buf;
1804
1805         sv.signon.maxsize = sizeof(sv.signon_buf);
1806         sv.signon.cursize = 0;
1807         sv.signon.data = sv.signon_buf;
1808
1809 // leave slots at start for clients only
1810         sv.num_edicts = MAX_SCOREBOARD+1;
1811
1812         sv.state = ss_loading;
1813         sv.paused = false;
1814
1815         sv.time = 1.0;
1816
1817         Mod_ClearUsed();
1818
1819         strcpy (sv.name, server);
1820         sprintf (sv.modelname,"maps/%s.bsp", server);
1821         sv.worldmodel = Mod_ForName(sv.modelname, false, true, true);
1822         if (!sv.worldmodel)
1823         {
1824                 Con_Printf ("Couldn't spawn server %s\n", sv.modelname);
1825                 sv.active = false;
1826                 return;
1827         }
1828         sv.models[1] = sv.worldmodel;
1829
1830 //
1831 // clear world interaction links
1832 //
1833         SV_ClearWorld ();
1834
1835         sv.sound_precache[0] = "";
1836
1837         sv.model_precache[0] = "";
1838         sv.model_precache[1] = sv.modelname;
1839         for (i = 1;i < sv.worldmodel->brushq1.numsubmodels;i++)
1840         {
1841                 sv.model_precache[i+1] = localmodels[i];
1842                 sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);
1843         }
1844
1845 //
1846 // load the rest of the entities
1847 //
1848         ent = EDICT_NUM(0);
1849         memset (ent->v, 0, progs->entityfields * 4);
1850         ent->e->free = false;
1851         ent->v->model = PR_SetString(sv.modelname);
1852         ent->v->modelindex = 1;         // world model
1853         ent->v->solid = SOLID_BSP;
1854         ent->v->movetype = MOVETYPE_PUSH;
1855
1856         if (coop.value)
1857                 pr_global_struct->coop = coop.integer;
1858         else
1859                 pr_global_struct->deathmatch = deathmatch.integer;
1860
1861         pr_global_struct->mapname = PR_SetString(sv.name);
1862
1863 // serverflags are for cross level information (sigils)
1864         pr_global_struct->serverflags = svs.serverflags;
1865
1866         // load replacement entity file if found
1867         entities = NULL;
1868         if (sv_entpatch.integer)
1869                 entities = FS_LoadFile(va("maps/%s.ent", sv.name), true);
1870         if (entities)
1871         {
1872                 Con_Printf("Loaded maps/%s.ent\n", sv.name);
1873                 ED_LoadFromFile (entities);
1874                 Mem_Free(entities);
1875         }
1876         else
1877                 ED_LoadFromFile (sv.worldmodel->brush.entities);
1878
1879
1880         // LordHavoc: clear world angles (to fix e3m3.bsp)
1881         VectorClear(sv.edicts->v->angles);
1882
1883         sv.active = true;
1884
1885 // all setup is completed, any further precache statements are errors
1886         sv.state = ss_active;
1887
1888 // run two frames to allow everything to settle
1889         for (i = 0;i < 2;i++)
1890         {
1891                 sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
1892                 SV_Physics ();
1893         }
1894
1895         Mod_PurgeUnused();
1896
1897 #ifdef QUAKEENTITIES
1898 // create a baseline for more efficient communications
1899         SV_CreateBaseline ();
1900 #endif
1901
1902 // send serverinfo to all connected clients
1903         for (i = 0;i < MAX_SCOREBOARD;i++)
1904                 if ((host_client = svs.connectedclients[i]))
1905                         SV_SendServerinfo(host_client);
1906
1907         Con_DPrintf ("Server spawned.\n");
1908         NetConn_Heartbeat (2);
1909 }
1910