]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - sv_main.c
added sv_gameplayfix_blowupfallenzombies and sv_gameplayfix_findradiusdistancetobox...
[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
24 // select which protocol to host, by name
25 // this is named the same as PROTOCOL_DARKPLACES6 for example, minus the PROTOCOL_ prefix
26 cvar_t sv_protocolname = {0, "sv_protocolname", "DARKPLACES6"};
27 cvar_t sv_ratelimitlocalplayer = {0, "sv_ratelimitlocalplayer", "0"};
28 cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000"};
29
30 static cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "1"}; // fast but loose
31 static cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "0"}; // tends to get false negatives, uses a timeout to keep entities visible a short time after becoming hidden
32 static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
33 static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
34
35 extern cvar_t sys_ticrate;
36
37 cvar_t sv_gameplayfix_grenadebouncedownslopes = {0, "sv_gameplayfix_grenadebouncedownslopes", "1"};
38 cvar_t sv_gameplayfix_noairborncorpse = {0, "sv_gameplayfix_noairborncorpse", "1"};
39 cvar_t sv_gameplayfix_stepdown = {0, "sv_gameplayfix_stepdown", "1"};
40 cvar_t sv_gameplayfix_stepwhilejumping = {0, "sv_gameplayfix_stepwhilejumping", "1"};
41 cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1"};
42 cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1"};
43 cvar_t sv_gameplayfix_blowupfallenzombies = {0, "sv_gameplayfix_blowupfallenzombies", "1"};
44 cvar_t sv_gameplayfix_findradiusdistancetobox = {0, "sv_gameplayfix_findradiusdistancetobox", "1"};
45
46 cvar_t sv_progs = {0, "sv_progs", "progs.dat" };
47
48 server_t sv;
49 server_static_t svs;
50
51 mempool_t *sv_mempool = NULL;
52
53 //============================================================================
54
55 extern void SV_Phys_Init (void);
56 extern void SV_World_Init (void);
57 static void SV_SaveEntFile_f(void);
58
59 /*
60 ===============
61 SV_Init
62 ===============
63 */
64 void SV_Init (void)
65 {
66         Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f);
67         Cvar_RegisterVariable (&sv_maxvelocity);
68         Cvar_RegisterVariable (&sv_gravity);
69         Cvar_RegisterVariable (&sv_friction);
70         Cvar_RegisterVariable (&sv_edgefriction);
71         Cvar_RegisterVariable (&sv_stopspeed);
72         Cvar_RegisterVariable (&sv_maxspeed);
73         Cvar_RegisterVariable (&sv_accelerate);
74         Cvar_RegisterVariable (&sv_idealpitchscale);
75         Cvar_RegisterVariable (&sv_aim);
76         Cvar_RegisterVariable (&sv_nostep);
77         Cvar_RegisterVariable (&sv_deltacompress);
78         Cvar_RegisterVariable (&sv_cullentities_pvs);
79         Cvar_RegisterVariable (&sv_cullentities_trace);
80         Cvar_RegisterVariable (&sv_cullentities_stats);
81         Cvar_RegisterVariable (&sv_entpatch);
82         Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes);
83         Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse);
84         Cvar_RegisterVariable (&sv_gameplayfix_stepdown);
85         Cvar_RegisterVariable (&sv_gameplayfix_stepwhilejumping);
86         Cvar_RegisterVariable (&sv_gameplayfix_swiminbmodels);
87         Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
88         Cvar_RegisterVariable (&sv_gameplayfix_blowupfallenzombies);
89         Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
90         Cvar_RegisterVariable (&sv_protocolname);
91         Cvar_RegisterVariable (&sv_ratelimitlocalplayer);
92         Cvar_RegisterVariable (&sv_maxrate);
93         Cvar_RegisterVariable (&sv_progs);
94
95         SV_Phys_Init();
96         SV_World_Init();
97
98         sv_mempool = Mem_AllocPool("server", 0, NULL);
99 }
100
101 static void SV_SaveEntFile_f(void)
102 {
103         char basename[MAX_QPATH];
104         if (!sv.active || !sv.worldmodel)
105         {
106                 Con_Print("Not running a server\n");
107                 return;
108         }
109         FS_StripExtension(sv.worldmodel->name, basename, sizeof(basename));
110         FS_WriteFile(va("%s.ent", basename), sv.worldmodel->brush.entities, strlen(sv.worldmodel->brush.entities));
111 }
112
113
114 /*
115 =============================================================================
116
117 EVENT MESSAGES
118
119 =============================================================================
120 */
121
122 /*
123 ==================
124 SV_StartParticle
125
126 Make sure the event gets sent to all clients
127 ==================
128 */
129 void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
130 {
131         int             i, v;
132
133         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-18)
134                 return;
135         MSG_WriteByte (&sv.datagram, svc_particle);
136         MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
137         MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
138         MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
139         for (i=0 ; i<3 ; i++)
140         {
141                 v = dir[i]*16;
142                 if (v > 127)
143                         v = 127;
144                 else if (v < -128)
145                         v = -128;
146                 MSG_WriteChar (&sv.datagram, v);
147         }
148         MSG_WriteByte (&sv.datagram, count);
149         MSG_WriteByte (&sv.datagram, color);
150 }
151
152 /*
153 ==================
154 SV_StartEffect
155
156 Make sure the event gets sent to all clients
157 ==================
158 */
159 void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
160 {
161         if (modelindex >= 256 || startframe >= 256)
162         {
163                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-19)
164                         return;
165                 MSG_WriteByte (&sv.datagram, svc_effect2);
166                 MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
167                 MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
168                 MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
169                 MSG_WriteShort (&sv.datagram, modelindex);
170                 MSG_WriteShort (&sv.datagram, startframe);
171                 MSG_WriteByte (&sv.datagram, framecount);
172                 MSG_WriteByte (&sv.datagram, framerate);
173         }
174         else
175         {
176                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-17)
177                         return;
178                 MSG_WriteByte (&sv.datagram, svc_effect);
179                 MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
180                 MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
181                 MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
182                 MSG_WriteByte (&sv.datagram, modelindex);
183                 MSG_WriteByte (&sv.datagram, startframe);
184                 MSG_WriteByte (&sv.datagram, framecount);
185                 MSG_WriteByte (&sv.datagram, framerate);
186         }
187 }
188
189 /*
190 ==================
191 SV_StartSound
192
193 Each entity can have eight independant sound sources, like voice,
194 weapon, feet, etc.
195
196 Channel 0 is an auto-allocate channel, the others override anything
197 already running on that entity/channel pair.
198
199 An attenuation of 0 will play full volume everywhere in the level.
200 Larger attenuations will drop off.  (max 4 attenuation)
201
202 ==================
203 */
204 void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
205 {
206         int sound_num, field_mask, i, ent;
207
208         if (volume < 0 || volume > 255)
209                 Host_Error ("SV_StartSound: volume = %i", volume);
210
211         if (attenuation < 0 || attenuation > 4)
212                 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
213
214         if (channel < 0 || channel > 7)
215                 Host_Error ("SV_StartSound: channel = %i", channel);
216
217         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-21)
218                 return;
219
220 // find precache number for sound
221         sound_num = SV_SoundIndex(sample, 1);
222         if (!sound_num)
223                 return;
224
225         ent = NUM_FOR_EDICT(entity);
226
227         field_mask = 0;
228         if (volume != DEFAULT_SOUND_PACKET_VOLUME)
229                 field_mask |= SND_VOLUME;
230         if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
231                 field_mask |= SND_ATTENUATION;
232         if (ent >= 8192)
233                 field_mask |= SND_LARGEENTITY;
234         if (sound_num >= 256 || channel >= 8)
235                 field_mask |= SND_LARGESOUND;
236
237 // directed messages go only to the entity they are targeted on
238         MSG_WriteByte (&sv.datagram, svc_sound);
239         MSG_WriteByte (&sv.datagram, field_mask);
240         if (field_mask & SND_VOLUME)
241                 MSG_WriteByte (&sv.datagram, volume);
242         if (field_mask & SND_ATTENUATION)
243                 MSG_WriteByte (&sv.datagram, attenuation*64);
244         if (field_mask & SND_LARGEENTITY)
245         {
246                 MSG_WriteShort (&sv.datagram, ent);
247                 MSG_WriteByte (&sv.datagram, channel);
248         }
249         else
250                 MSG_WriteShort (&sv.datagram, (ent<<3) | channel);
251         if (field_mask & SND_LARGESOUND)
252                 MSG_WriteShort (&sv.datagram, sound_num);
253         else
254                 MSG_WriteByte (&sv.datagram, sound_num);
255         for (i = 0;i < 3;i++)
256                 MSG_WriteCoord (&sv.datagram, entity->v->origin[i]+0.5*(entity->v->mins[i]+entity->v->maxs[i]), sv.protocol);
257 }
258
259 /*
260 ==============================================================================
261
262 CLIENT SPAWNING
263
264 ==============================================================================
265 */
266
267 /*
268 ================
269 SV_SendServerinfo
270
271 Sends the first message from the server to a connected client.
272 This will be sent on the initial connection and upon each server load.
273 ================
274 */
275 void SV_SendServerinfo (client_t *client)
276 {
277         int i;
278         char message[128];
279
280         // edicts get reallocated on level changes, so we need to update it here
281         client->edict = EDICT_NUM((client - svs.clients) + 1);
282
283         // if client is a botclient coming from a level change, we need to set up
284         // client info that normally requires networking
285         if (!client->netconnection)
286         {
287                 // set up the edict
288                 ED_ClearEdict(client->edict);
289
290                 // copy spawn parms out of the client_t
291                 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
292                         (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
293
294                 // call the spawn function
295                 pr_global_struct->time = sv.time;
296                 pr_global_struct->self = EDICT_TO_PROG(client->edict);
297                 PR_ExecuteProgram (pr_global_struct->ClientConnect, "QC function ClientConnect is missing");
298                 PR_ExecuteProgram (pr_global_struct->PutClientInServer, "QC function PutClientInServer is missing");
299                 host_client->spawned = true;
300                 return;
301         }
302
303         // LordHavoc: clear entityframe tracking
304         client->latestframenum = 0;
305
306         if (client->entitydatabase)
307                 EntityFrame_FreeDatabase(client->entitydatabase);
308         if (client->entitydatabase4)
309                 EntityFrame4_FreeDatabase(client->entitydatabase4);
310         if (client->entitydatabase5)
311                 EntityFrame5_FreeDatabase(client->entitydatabase5);
312
313         if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
314                 client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool);
315         if (sv.protocol == PROTOCOL_DARKPLACES4)
316                 client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_mempool);
317         if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
318                 client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool);
319
320         MSG_WriteByte (&client->message, svc_print);
321         dpsnprintf (message, sizeof (message), "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, pr_crc);
322         MSG_WriteString (&client->message,message);
323
324         MSG_WriteByte (&client->message, svc_serverinfo);
325         MSG_WriteLong (&client->message, sv.protocol);
326         MSG_WriteByte (&client->message, svs.maxclients);
327
328         if (!coop.integer && deathmatch.integer)
329                 MSG_WriteByte (&client->message, GAME_DEATHMATCH);
330         else
331                 MSG_WriteByte (&client->message, GAME_COOP);
332
333         MSG_WriteString (&client->message,PR_GetString(sv.edicts->v->message));
334
335         for (i = 1;i < MAX_MODELS && sv.model_precache[i][0];i++)
336                 MSG_WriteString (&client->message, sv.model_precache[i]);
337         MSG_WriteByte (&client->message, 0);
338
339         for (i = 1;i < MAX_SOUNDS && sv.sound_precache[i][0];i++)
340                 MSG_WriteString (&client->message, sv.sound_precache[i]);
341         MSG_WriteByte (&client->message, 0);
342
343 // send music
344         MSG_WriteByte (&client->message, svc_cdtrack);
345         MSG_WriteByte (&client->message, sv.edicts->v->sounds);
346         MSG_WriteByte (&client->message, sv.edicts->v->sounds);
347
348 // set view
349         MSG_WriteByte (&client->message, svc_setview);
350         MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
351
352         MSG_WriteByte (&client->message, svc_signonnum);
353         MSG_WriteByte (&client->message, 1);
354
355         client->sendsignon = true;
356         client->spawned = false;                // need prespawn, spawn, etc
357 }
358
359 /*
360 ================
361 SV_ConnectClient
362
363 Initializes a client_t for a new net connection.  This will only be called
364 once for a player each game, not once for each level change.
365 ================
366 */
367 void SV_ConnectClient (int clientnum, netconn_t *netconnection)
368 {
369         client_t                *client;
370         int                             i;
371         float                   spawn_parms[NUM_SPAWN_PARMS];
372
373         client = svs.clients + clientnum;
374
375 // set up the client_t
376         if (sv.loadgame)
377                 memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
378         memset (client, 0, sizeof(*client));
379         client->active = true;
380         client->netconnection = netconnection;
381
382         Con_DPrintf("Client %s connected\n", client->netconnection ? client->netconnection->address : "botclient");
383
384         strcpy(client->name, "unconnected");
385         strcpy(client->old_name, "unconnected");
386         client->spawned = false;
387         client->edict = EDICT_NUM(clientnum+1);
388         client->message.data = client->msgbuf;
389         client->message.maxsize = sizeof(client->msgbuf);
390         client->message.allowoverflow = true;           // we can catch it
391         // updated by receiving "rate" command from client
392         client->rate = NET_MINRATE;
393         // no limits for local player
394         if (client->netconnection && LHNETADDRESS_GetAddressType(&client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
395                 client->rate = 1000000000;
396         client->connecttime = realtime;
397
398         if (sv.loadgame)
399                 memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
400         else
401         {
402                 // call the progs to get default spawn parms for the new client
403                 PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
404                 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
405                         client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
406         }
407
408         // don't call SendServerinfo for a fresh botclient because its fields have
409         // not been set up by the qc yet
410         if (client->netconnection)
411                 SV_SendServerinfo (client);
412         else
413                 client->spawned = true;
414 }
415
416
417 /*
418 ===============================================================================
419
420 FRAME UPDATES
421
422 ===============================================================================
423 */
424
425 /*
426 ==================
427 SV_ClearDatagram
428
429 ==================
430 */
431 void SV_ClearDatagram (void)
432 {
433         SZ_Clear (&sv.datagram);
434 }
435
436 /*
437 =============================================================================
438
439 The PVS must include a small area around the client to allow head bobbing
440 or other small motion on the client side.  Otherwise, a bob might cause an
441 entity that should be visible to not show up, especially when the bob
442 crosses a waterline.
443
444 =============================================================================
445 */
446
447 int sv_writeentitiestoclient_pvsbytes;
448 qbyte sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
449
450 static int numsendentities;
451 static entity_state_t sendentities[MAX_EDICTS];
452 static entity_state_t *sendentitiesindex[MAX_EDICTS];
453
454 void SV_PrepareEntitiesForSending(void)
455 {
456         int e, i;
457         float f;
458         edict_t *ent;
459         eval_t *val;
460         entity_state_t cs;
461         // send all entities that touch the pvs
462         numsendentities = 0;
463         sendentitiesindex[0] = NULL;
464         for (e = 1, ent = NEXT_EDICT(sv.edicts);e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
465         {
466                 sendentitiesindex[e] = NULL;
467                 if (ent->e->free)
468                         continue;
469
470                 cs = defaultstate;
471                 cs.active = true;
472                 cs.number = e;
473                 VectorCopy(ent->v->origin, cs.origin);
474                 VectorCopy(ent->v->angles, cs.angles);
475                 cs.flags = 0;
476                 cs.effects = (unsigned)ent->v->effects;
477                 cs.colormap = (unsigned)ent->v->colormap;
478                 cs.skin = (unsigned)ent->v->skin;
479                 cs.frame = (unsigned)ent->v->frame;
480                 cs.viewmodelforclient = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
481                 cs.exteriormodelforclient = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
482                 cs.nodrawtoclient = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
483                 cs.drawonlytoclient = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
484                 cs.tagentity = GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
485                 cs.tagindex = (qbyte)GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
486                 i = (int)(GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
487                 cs.glowsize = (qbyte)bound(0, i, 255);
488                 if (GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
489                         cs.flags |= RENDER_GLOWTRAIL;
490
491                 // don't need to init cs.colormod because the defaultstate did that for us
492                 //cs.colormod[0] = cs.colormod[1] = cs.colormod[2] = 32;
493                 val = GETEDICTFIELDVALUE(ent, eval_colormod);
494                 if (val->vector[0] || val->vector[1] || val->vector[2])
495                 {
496                         i = val->vector[0] * 32.0f;cs.colormod[0] = bound(0, i, 255);
497                         i = val->vector[1] * 32.0f;cs.colormod[1] = bound(0, i, 255);
498                         i = val->vector[2] * 32.0f;cs.colormod[2] = bound(0, i, 255);
499                 }
500
501                 cs.modelindex = 0;
502                 i = (int)ent->v->modelindex;
503                 if (i >= 1 && i < MAX_MODELS && *PR_GetString(ent->v->model))
504                         cs.modelindex = i;
505
506                 cs.alpha = 255;
507                 f = (GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
508                 if (f)
509                 {
510                         i = (int)f;
511                         cs.alpha = (qbyte)bound(0, i, 255);
512                 }
513                 // halflife
514                 f = (GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
515                 if (f)
516                 {
517                         i = (int)f;
518                         cs.alpha = (qbyte)bound(0, i, 255);
519                 }
520
521                 cs.scale = 16;
522                 f = (GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
523                 if (f)
524                 {
525                         i = (int)f;
526                         cs.scale = (qbyte)bound(0, i, 255);
527                 }
528
529                 cs.glowcolor = 254;
530                 f = (GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
531                 if (f)
532                         cs.glowcolor = (int)f;
533
534                 if (GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
535                         cs.effects |= EF_FULLBRIGHT;
536
537                 if (ent->v->movetype == MOVETYPE_STEP)
538                         cs.flags |= RENDER_STEP;
539                 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)
540                         cs.flags |= RENDER_LOWPRECISION;
541                 if (ent->v->colormap >= 1024)
542                         cs.flags |= RENDER_COLORMAPPED;
543                 if (cs.viewmodelforclient)
544                         cs.flags |= RENDER_VIEWMODEL; // show relative to the view
545
546                 f = GETEDICTFIELDVALUE(ent, eval_color)->vector[0]*256;
547                 cs.light[0] = (unsigned short)bound(0, f, 65535);
548                 f = GETEDICTFIELDVALUE(ent, eval_color)->vector[1]*256;
549                 cs.light[1] = (unsigned short)bound(0, f, 65535);
550                 f = GETEDICTFIELDVALUE(ent, eval_color)->vector[2]*256;
551                 cs.light[2] = (unsigned short)bound(0, f, 65535);
552                 f = GETEDICTFIELDVALUE(ent, eval_light_lev)->_float;
553                 cs.light[3] = (unsigned short)bound(0, f, 65535);
554                 cs.lightstyle = (qbyte)GETEDICTFIELDVALUE(ent, eval_style)->_float;
555                 cs.lightpflags = (qbyte)GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
556
557                 if (gamemode == GAME_TENEBRAE)
558                 {
559                         // tenebrae's EF_FULLDYNAMIC conflicts with Q2's EF_NODRAW
560                         if (cs.effects & 16)
561                         {
562                                 cs.effects &= ~16;
563                                 cs.lightpflags |= PFLAGS_FULLDYNAMIC;
564                         }
565                         // tenebrae's EF_GREEN conflicts with DP's EF_ADDITIVE
566                         if (cs.effects & 32)
567                         {
568                                 cs.effects &= ~32;
569                                 cs.light[0] = 0.2;
570                                 cs.light[1] = 1;
571                                 cs.light[2] = 0.2;
572                                 cs.light[3] = 200;
573                                 cs.lightpflags |= PFLAGS_FULLDYNAMIC;
574                         }
575                 }
576
577                 cs.specialvisibilityradius = 0;
578                 if (cs.lightpflags & PFLAGS_FULLDYNAMIC)
579                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, cs.light[3]);
580                 if (cs.glowsize)
581                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, cs.glowsize * 4);
582                 if (cs.flags & RENDER_GLOWTRAIL)
583                         cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
584                 if (cs.effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
585                 {
586                         if (cs.effects & EF_BRIGHTFIELD)
587                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 80);
588                         if (cs.effects & EF_MUZZLEFLASH)
589                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
590                         if (cs.effects & EF_BRIGHTLIGHT)
591                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 400);
592                         if (cs.effects & EF_DIMLIGHT)
593                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
594                         if (cs.effects & EF_RED)
595                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
596                         if (cs.effects & EF_BLUE)
597                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 200);
598                         if (cs.effects & EF_FLAME)
599                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 250);
600                         if (cs.effects & EF_STARDUST)
601                                 cs.specialvisibilityradius = max(cs.specialvisibilityradius, 100);
602                 }
603
604                 if (numsendentities >= MAX_EDICTS)
605                         continue;
606                 // we can omit invisible entities with no effects that are not clients
607                 // LordHavoc: this could kill tags attached to an invisible entity, I
608                 // just hope we never have to support that case
609                 if (cs.number > svs.maxclients && ((cs.effects & EF_NODRAW) || (!cs.modelindex && !cs.specialvisibilityradius)))
610                         continue;
611                 sendentitiesindex[e] = sendentities + numsendentities;
612                 sendentities[numsendentities++] = cs;
613         }
614 }
615
616 static int sententitiesmark = 0;
617 static int sententities[MAX_EDICTS];
618 static int sententitiesconsideration[MAX_EDICTS];
619 static int sv_writeentitiestoclient_culled_pvs;
620 static int sv_writeentitiestoclient_culled_trace;
621 static int sv_writeentitiestoclient_visibleentities;
622 static int sv_writeentitiestoclient_totalentities;
623 //static entity_frame_t sv_writeentitiestoclient_entityframe;
624 static int sv_writeentitiestoclient_clentnum;
625 static vec3_t sv_writeentitiestoclient_testeye;
626 static client_t *sv_writeentitiestoclient_client;
627
628 void SV_MarkWriteEntityStateToClient(entity_state_t *s)
629 {
630         int isbmodel;
631         vec3_t entmins, entmaxs, lightmins, lightmaxs, testorigin;
632         model_t *model;
633         trace_t trace;
634         if (sententitiesconsideration[s->number] == sententitiesmark)
635                 return;
636         sententitiesconsideration[s->number] = sententitiesmark;
637         // viewmodels don't have visibility checking
638         if (s->viewmodelforclient)
639         {
640                 if (s->viewmodelforclient != sv_writeentitiestoclient_clentnum)
641                         return;
642         }
643         // never reject player
644         else if (s->number != sv_writeentitiestoclient_clentnum)
645         {
646                 // check various rejection conditions
647                 if (s->nodrawtoclient == sv_writeentitiestoclient_clentnum)
648                         return;
649                 if (s->drawonlytoclient && s->drawonlytoclient != sv_writeentitiestoclient_clentnum)
650                         return;
651                 if (s->effects & EF_NODRAW)
652                         return;
653                 // LordHavoc: only send entities with a model or important effects
654                 if (!s->modelindex && s->specialvisibilityradius == 0)
655                         return;
656                 if (s->tagentity)
657                 {
658                         // tag attached entities simply check their parent
659                         if (!sendentitiesindex[s->tagentity])
660                                 return;
661                         SV_MarkWriteEntityStateToClient(sendentitiesindex[s->tagentity]);
662                         if (sententities[s->tagentity] != sententitiesmark)
663                                 return;
664                 }
665                 // skip invalid modelindexes to avoid crashes
666                 else if (s->modelindex >= MAX_MODELS)
667                         return;
668                 // always send world submodels, they don't generate much traffic
669                 // except in PROTOCOL_QUAKE where they hog bandwidth like crazy
670                 else if (!(s->effects & EF_NODEPTHTEST) && (!(isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*') || sv.protocol == PROTOCOL_QUAKE))
671                 {
672                         Mod_CheckLoaded(model);
673                         // entity has survived every check so far, check if visible
674                         // enlarged box to account for prediction (not that there is
675                         // any currently, but still helps the 'run into a room and
676                         // watch items pop up' problem)
677                         entmins[0] = s->origin[0] - 32.0f;
678                         entmins[1] = s->origin[1] - 32.0f;
679                         entmins[2] = s->origin[2] - 32.0f;
680                         entmaxs[0] = s->origin[0] + 32.0f;
681                         entmaxs[1] = s->origin[1] + 32.0f;
682                         entmaxs[2] = s->origin[2] + 32.0f;
683                         // using the model's bounding box to ensure things are visible regardless of their physics box
684                         if (model)
685                         {
686                                 if (s->angles[0] || s->angles[2]) // pitch and roll
687                                 {
688                                         VectorAdd(entmins, model->rotatedmins, entmins);
689                                         VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
690                                 }
691                                 else if (s->angles[1])
692                                 {
693                                         VectorAdd(entmins, model->yawmins, entmins);
694                                         VectorAdd(entmaxs, model->yawmaxs, entmaxs);
695                                 }
696                                 else
697                                 {
698                                         VectorAdd(entmins, model->normalmins, entmins);
699                                         VectorAdd(entmaxs, model->normalmaxs, entmaxs);
700                                 }
701                         }
702                         lightmins[0] = min(entmins[0], s->origin[0] - s->specialvisibilityradius);
703                         lightmins[1] = min(entmins[1], s->origin[1] - s->specialvisibilityradius);
704                         lightmins[2] = min(entmins[2], s->origin[2] - s->specialvisibilityradius);
705                         lightmaxs[0] = max(entmaxs[0], s->origin[0] + s->specialvisibilityradius);
706                         lightmaxs[1] = max(entmaxs[1], s->origin[1] + s->specialvisibilityradius);
707                         lightmaxs[2] = max(entmaxs[2], s->origin[2] + s->specialvisibilityradius);
708                         sv_writeentitiestoclient_totalentities++;
709                         // if not touching a visible leaf
710                         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))
711                         {
712                                 sv_writeentitiestoclient_culled_pvs++;
713                                 return;
714                         }
715                         // or not seen by random tracelines
716                         if (sv_cullentities_trace.integer && !isbmodel)
717                         {
718                                 // LordHavoc: test center first
719                                 testorigin[0] = (entmins[0] + entmaxs[0]) * 0.5f;
720                                 testorigin[1] = (entmins[1] + entmaxs[1]) * 0.5f;
721                                 testorigin[2] = (entmins[2] + entmaxs[2]) * 0.5f;
722                                 sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
723                                 if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
724                                         sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
725                                 else
726                                 {
727                                         // LordHavoc: test random offsets, to maximize chance of detection
728                                         testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
729                                         testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
730                                         testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
731                                         sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
732                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
733                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
734                                         else
735                                         {
736                                                 if (s->specialvisibilityradius)
737                                                 {
738                                                         // LordHavoc: test random offsets, to maximize chance of detection
739                                                         testorigin[0] = lhrandom(lightmins[0], lightmaxs[0]);
740                                                         testorigin[1] = lhrandom(lightmins[1], lightmaxs[1]);
741                                                         testorigin[2] = lhrandom(lightmins[2], lightmaxs[2]);
742                                                         sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
743                                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, entmins, entmaxs))
744                                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
745                                                 }
746                                         }
747                                 }
748                                 if (realtime > sv_writeentitiestoclient_client->visibletime[s->number])
749                                 {
750                                         sv_writeentitiestoclient_culled_trace++;
751                                         return;
752                                 }
753                         }
754                         sv_writeentitiestoclient_visibleentities++;
755                 }
756         }
757         // this just marks it for sending
758         // FIXME: it would be more efficient to send here, but the entity
759         // compressor isn't that flexible
760         sententities[s->number] = sententitiesmark;
761 }
762
763 entity_state_t sendstates[MAX_EDICTS];
764
765 void SV_WriteEntitiesToClient(client_t *client, edict_t *clent, sizebuf_t *msg, int *stats)
766 {
767         int i, numsendstates;
768         entity_state_t *s;
769
770         // if there isn't enough space to accomplish anything, skip it
771         if (msg->cursize + 25 > msg->maxsize)
772                 return;
773
774         sv_writeentitiestoclient_client = client;
775
776         sv_writeentitiestoclient_culled_pvs = 0;
777         sv_writeentitiestoclient_culled_trace = 0;
778         sv_writeentitiestoclient_visibleentities = 0;
779         sv_writeentitiestoclient_totalentities = 0;
780
781         Mod_CheckLoaded(sv.worldmodel);
782
783 // find the client's PVS
784         // the real place being tested from
785         VectorAdd(clent->v->origin, clent->v->view_ofs, sv_writeentitiestoclient_testeye);
786         sv_writeentitiestoclient_pvsbytes = 0;
787         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
788                 sv_writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv_writeentitiestoclient_testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
789
790         sv_writeentitiestoclient_clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
791
792         sententitiesmark++;
793
794         for (i = 0;i < numsendentities;i++)
795                 SV_MarkWriteEntityStateToClient(sendentities + i);
796
797         numsendstates = 0;
798         for (i = 0;i < numsendentities;i++)
799         {
800                 if (sententities[sendentities[i].number] == sententitiesmark)
801                 {
802                         s = &sendstates[numsendstates++];
803                         *s = sendentities[i];
804                         if (s->exteriormodelforclient && s->exteriormodelforclient == sv_writeentitiestoclient_clentnum)
805                                 s->flags |= RENDER_EXTERIORMODEL;
806                 }
807         }
808
809         if (sv_cullentities_stats.integer)
810                 Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
811
812         if (client->entitydatabase5)
813                 EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats);
814         else if (client->entitydatabase4)
815                 EntityFrame4_WriteFrame(msg, client->entitydatabase4, numsendstates, sendstates);
816         else if (client->entitydatabase)
817                 EntityFrame_WriteFrame(msg, client->entitydatabase, numsendstates, sendstates, client - svs.clients + 1);
818         else
819                 EntityFrameQuake_WriteFrame(msg, numsendstates, sendstates);
820 }
821
822 /*
823 =============
824 SV_CleanupEnts
825
826 =============
827 */
828 void SV_CleanupEnts (void)
829 {
830         int             e;
831         edict_t *ent;
832
833         ent = NEXT_EDICT(sv.edicts);
834         for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
835                 ent->v->effects = (int)ent->v->effects & ~EF_MUZZLEFLASH;
836 }
837
838 /*
839 ==================
840 SV_WriteClientdataToMessage
841
842 ==================
843 */
844 void SV_WriteClientdataToMessage (client_t *client, edict_t *ent, sizebuf_t *msg, int *stats)
845 {
846         int             bits;
847         int             i;
848         edict_t *other;
849         int             items;
850         eval_t  *val;
851         vec3_t  punchvector;
852         qbyte   viewzoom;
853         int             weaponmodelindex;
854
855 //
856 // send a damage message
857 //
858         if (ent->v->dmg_take || ent->v->dmg_save)
859         {
860                 other = PROG_TO_EDICT(ent->v->dmg_inflictor);
861                 MSG_WriteByte (msg, svc_damage);
862                 MSG_WriteByte (msg, ent->v->dmg_save);
863                 MSG_WriteByte (msg, ent->v->dmg_take);
864                 for (i=0 ; i<3 ; i++)
865                         MSG_WriteCoord (msg, other->v->origin[i] + 0.5*(other->v->mins[i] + other->v->maxs[i]), sv.protocol);
866
867                 ent->v->dmg_take = 0;
868                 ent->v->dmg_save = 0;
869         }
870
871 //
872 // send the current viewpos offset from the view entity
873 //
874         SV_SetIdealPitch ();            // how much to look up / down ideally
875
876 // a fixangle might get lost in a dropped packet.  Oh well.
877         if ( ent->v->fixangle )
878         {
879                 MSG_WriteByte (msg, svc_setangle);
880                 for (i=0 ; i < 3 ; i++)
881                         MSG_WriteAngle (msg, ent->v->angles[i], sv.protocol);
882                 ent->v->fixangle = 0;
883         }
884
885         // stuff the sigil bits into the high bits of items for sbar, or else
886         // mix in items2
887         val = GETEDICTFIELDVALUE(ent, eval_items2);
888         if (val)
889                 items = (int)ent->v->items | ((int)val->_float << 23);
890         else
891                 items = (int)ent->v->items | ((int)pr_global_struct->serverflags << 28);
892
893         VectorClear(punchvector);
894         if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
895                 VectorCopy(val->vector, punchvector);
896
897         weaponmodelindex = SV_ModelIndex(PR_GetString(ent->v->weaponmodel), 1);
898
899         viewzoom = 255;
900         if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom)))
901                 viewzoom = val->_float * 255.0f;
902         if (viewzoom == 0)
903                 viewzoom = 255;
904
905         bits = 0;
906
907         if ((int)ent->v->flags & FL_ONGROUND)
908                 bits |= SU_ONGROUND;
909         if (ent->v->waterlevel >= 2)
910                 bits |= SU_INWATER;
911         if (ent->v->idealpitch)
912                 bits |= SU_IDEALPITCH;
913
914         for (i=0 ; i<3 ; i++)
915         {
916                 if (ent->v->punchangle[i])
917                         bits |= (SU_PUNCH1<<i);
918                 if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
919                         if (punchvector[i])
920                                 bits |= (SU_PUNCHVEC1<<i);
921                 if (ent->v->velocity[i])
922                         bits |= (SU_VELOCITY1<<i);
923         }
924
925         memset(stats, 0, sizeof(int[MAX_CL_STATS]));
926         stats[STAT_VIEWHEIGHT] = ent->v->view_ofs[2];
927         stats[STAT_ITEMS] = items;
928         stats[STAT_WEAPONFRAME] = ent->v->weaponframe;
929         stats[STAT_ARMOR] = ent->v->armorvalue;
930         stats[STAT_WEAPON] = weaponmodelindex;
931         stats[STAT_HEALTH] = ent->v->health;
932         stats[STAT_AMMO] = ent->v->currentammo;
933         stats[STAT_SHELLS] = ent->v->ammo_shells;
934         stats[STAT_NAILS] = ent->v->ammo_nails;
935         stats[STAT_ROCKETS] = ent->v->ammo_rockets;
936         stats[STAT_CELLS] = ent->v->ammo_cells;
937         stats[STAT_ACTIVEWEAPON] = ent->v->weapon;
938         stats[STAT_VIEWZOOM] = viewzoom;
939         // the QC bumps these itself by sending svc_'s, so we have to keep them
940         // zero or they'll be corrected by the engine
941         //stats[STAT_TOTALSECRETS] = pr_global_struct->total_secrets;
942         //stats[STAT_TOTALMONSTERS] = pr_global_struct->total_monsters;
943         //stats[STAT_SECRETS] = pr_global_struct->found_secrets;
944         //stats[STAT_MONSTERS] = pr_global_struct->killed_monsters;
945
946         if (sv.protocol != PROTOCOL_DARKPLACES6)
947         {
948                 if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT;
949                 bits |= SU_ITEMS;
950                 if (stats[STAT_WEAPONFRAME]) bits |= SU_WEAPONFRAME;
951                 if (stats[STAT_ARMOR]) bits |= SU_ARMOR;
952                 bits |= SU_WEAPON;
953                 // FIXME: which protocols support this?  does PROTOCOL_DARKPLACES3 support viewzoom?
954                 if (sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
955                         if (viewzoom != 255)
956                                 bits |= SU_VIEWZOOM;
957         }
958
959         if (bits >= 65536)
960                 bits |= SU_EXTEND1;
961         if (bits >= 16777216)
962                 bits |= SU_EXTEND2;
963
964         // send the data
965         MSG_WriteByte (msg, svc_clientdata);
966         MSG_WriteShort (msg, bits);
967         if (bits & SU_EXTEND1)
968                 MSG_WriteByte(msg, bits >> 16);
969         if (bits & SU_EXTEND2)
970                 MSG_WriteByte(msg, bits >> 24);
971
972         if (bits & SU_VIEWHEIGHT)
973                 MSG_WriteChar (msg, stats[STAT_VIEWHEIGHT]);
974
975         if (bits & SU_IDEALPITCH)
976                 MSG_WriteChar (msg, ent->v->idealpitch);
977
978         for (i=0 ; i<3 ; i++)
979         {
980                 if (bits & (SU_PUNCH1<<i))
981                 {
982                         if (sv.protocol == PROTOCOL_QUAKE)
983                                 MSG_WriteChar(msg, ent->v->punchangle[i]);
984                         else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
985                                 MSG_WriteAngle16i(msg, ent->v->punchangle[i]);
986                 }
987                 if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
988                 {
989                         if (bits & (SU_PUNCHVEC1<<i))
990                         {
991                                 if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
992                                         MSG_WriteCoord16i(msg, punchvector[i]);
993                                 else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
994                                         MSG_WriteCoord32f(msg, punchvector[i]);
995                         }
996                 }
997                 if (bits & (SU_VELOCITY1<<i))
998                 {
999                         if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1000                                 MSG_WriteChar(msg, ent->v->velocity[i] * (1.0f / 16.0f));
1001                         else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
1002                                 MSG_WriteCoord32f(msg, ent->v->velocity[i]);
1003                 }
1004         }
1005
1006         if (bits & SU_ITEMS)
1007                 MSG_WriteLong (msg, stats[STAT_ITEMS]);
1008
1009         if (sv.protocol == PROTOCOL_DARKPLACES5)
1010         {
1011                 if (bits & SU_WEAPONFRAME)
1012                         MSG_WriteShort (msg, stats[STAT_WEAPONFRAME]);
1013                 if (bits & SU_ARMOR)
1014                         MSG_WriteShort (msg, stats[STAT_ARMOR]);
1015                 if (bits & SU_WEAPON)
1016                         MSG_WriteShort (msg, stats[STAT_WEAPON]);
1017                 MSG_WriteShort (msg, stats[STAT_HEALTH]);
1018                 MSG_WriteShort (msg, stats[STAT_AMMO]);
1019                 MSG_WriteShort (msg, stats[STAT_SHELLS]);
1020                 MSG_WriteShort (msg, stats[STAT_NAILS]);
1021                 MSG_WriteShort (msg, stats[STAT_ROCKETS]);
1022                 MSG_WriteShort (msg, stats[STAT_CELLS]);
1023                 MSG_WriteShort (msg, stats[STAT_ACTIVEWEAPON]);
1024                 if (bits & SU_VIEWZOOM)
1025                         MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
1026         }
1027         else if (sv.protocol != PROTOCOL_DARKPLACES6)
1028         {
1029                 if (bits & SU_WEAPONFRAME)
1030                         MSG_WriteByte (msg, stats[STAT_WEAPONFRAME]);
1031                 if (bits & SU_ARMOR)
1032                         MSG_WriteByte (msg, stats[STAT_ARMOR]);
1033                 if (bits & SU_WEAPON)
1034                         MSG_WriteByte (msg, stats[STAT_WEAPON]);
1035                 MSG_WriteShort (msg, stats[STAT_HEALTH]);
1036                 MSG_WriteByte (msg, stats[STAT_AMMO]);
1037                 MSG_WriteByte (msg, stats[STAT_SHELLS]);
1038                 MSG_WriteByte (msg, stats[STAT_NAILS]);
1039                 MSG_WriteByte (msg, stats[STAT_ROCKETS]);
1040                 MSG_WriteByte (msg, stats[STAT_CELLS]);
1041                 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
1042                 {
1043                         for (i = 0;i < 32;i++)
1044                                 if (stats[STAT_WEAPON] & (1<<i))
1045                                         break;
1046                         MSG_WriteByte (msg, i);
1047                 }
1048                 else
1049                         MSG_WriteByte (msg, stats[STAT_WEAPON]);
1050                 if (bits & SU_VIEWZOOM)
1051                 {
1052                         if (sv.protocol == PROTOCOL_DARKPLACES4)
1053                                 MSG_WriteByte (msg, min(stats[STAT_VIEWZOOM], 255));
1054                         else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
1055                                 MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
1056                 }
1057         }
1058 }
1059
1060 /*
1061 =======================
1062 SV_SendClientDatagram
1063 =======================
1064 */
1065 static qbyte sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
1066 qboolean SV_SendClientDatagram (client_t *client)
1067 {
1068         int rate, maxrate, maxsize, maxsize2;
1069         sizebuf_t msg;
1070         int stats[MAX_CL_STATS];
1071
1072         if (LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP && !sv_ratelimitlocalplayer.integer)
1073         {
1074                 // for good singleplayer, send huge packets
1075                 maxsize = sizeof(sv_sendclientdatagram_buf);
1076                 maxsize2 = sizeof(sv_sendclientdatagram_buf);
1077         }
1078         else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
1079         {
1080                 // PROTOCOL_DARKPLACES5 supports packet size limiting of updates
1081                 maxrate = bound(NET_MINRATE, sv_maxrate.integer, NET_MAXRATE);
1082                 if (sv_maxrate.integer != maxrate)
1083                         Cvar_SetValueQuick(&sv_maxrate, maxrate);
1084
1085                 rate = bound(NET_MINRATE, client->rate, maxrate);
1086                 rate = (int)(client->rate * sys_ticrate.value);
1087                 maxsize = bound(100, rate, 1400);
1088                 maxsize2 = 1400;
1089         }
1090         else
1091         {
1092                 // no rate limiting support on older protocols because dp protocols
1093                 // 1-4 kick the client off if they overflow, and quake protocol shows
1094                 // less than the full entity set if rate limited
1095                 maxsize = 1400;
1096                 maxsize2 = 1400;
1097         }
1098
1099         msg.data = sv_sendclientdatagram_buf;
1100         msg.maxsize = maxsize;
1101         msg.cursize = 0;
1102
1103         MSG_WriteByte (&msg, svc_time);
1104         MSG_WriteFloat (&msg, sv.time);
1105
1106         // add the client specific data to the datagram
1107         SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
1108         SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
1109
1110         // expand packet size to allow effects to go over the rate limit
1111         // (dropping them is FAR too ugly)
1112         msg.maxsize = maxsize2;
1113
1114         // copy the server datagram if there is space
1115         // FIXME: put in delayed queue of effects to send
1116         if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
1117                 SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
1118
1119 // send the datagram
1120         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1121         {
1122                 SV_DropClient (true);// if the message couldn't send, kick off
1123                 return false;
1124         }
1125
1126         return true;
1127 }
1128
1129 /*
1130 =======================
1131 SV_UpdateToReliableMessages
1132 =======================
1133 */
1134 void SV_UpdateToReliableMessages (void)
1135 {
1136         int i, j;
1137         client_t *client;
1138         eval_t *val;
1139         char *name;
1140         char *model;
1141         char *skin;
1142
1143 // check for changes to be sent over the reliable streams
1144         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1145         {
1146                 // update the host_client fields we care about according to the entity fields
1147                 host_client->edict = EDICT_NUM(i+1);
1148
1149                 // DP_SV_CLIENTNAME
1150                 name = PR_GetString(host_client->edict->v->netname);
1151                 if (name == NULL)
1152                         name = "";
1153                 // always point the string back at host_client->name to keep it safe
1154                 strlcpy (host_client->name, name, sizeof (host_client->name));
1155                 host_client->edict->v->netname = PR_SetString(host_client->name);
1156                 if (strcmp(host_client->old_name, host_client->name))
1157                 {
1158                         if (host_client->spawned)
1159                                 SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
1160                         strcpy(host_client->old_name, host_client->name);
1161                         // send notification to all clients
1162                         MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
1163                         MSG_WriteByte (&sv.reliable_datagram, i);
1164                         MSG_WriteString (&sv.reliable_datagram, host_client->name);
1165                 }
1166
1167                 // DP_SV_CLIENTCOLORS
1168                 // this is always found (since it's added by the progs loader)
1169                 if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors)))
1170                         host_client->colors = (int)val->_float;
1171                 if (host_client->old_colors != host_client->colors)
1172                 {
1173                         host_client->old_colors = host_client->colors;
1174                         // send notification to all clients
1175                         MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1176                         MSG_WriteByte (&sv.reliable_datagram, i);
1177                         MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
1178                 }
1179
1180                 // NEXUIZ_PLAYERMODEL
1181                 if( eval_playermodel ) {
1182                         model = PR_GetString(GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string);
1183                         if (model == NULL)
1184                                 model = "";
1185                         // always point the string back at host_client->name to keep it safe
1186                         strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
1187                         GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(host_client->playermodel);
1188                 }
1189
1190                 // NEXUIZ_PLAYERSKIN
1191                 if( eval_playerskin ) {
1192                         skin = PR_GetString(GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string);
1193                         if (skin == NULL)
1194                                 skin = "";
1195                         // always point the string back at host_client->name to keep it safe
1196                         strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
1197                         GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(host_client->playerskin);
1198                 }
1199
1200                 // frags
1201                 host_client->frags = (int)host_client->edict->v->frags;
1202                 if (host_client->old_frags != host_client->frags)
1203                 {
1204                         host_client->old_frags = host_client->frags;
1205                         // send notification to all clients
1206                         MSG_WriteByte (&sv.reliable_datagram, svc_updatefrags);
1207                         MSG_WriteByte (&sv.reliable_datagram, i);
1208                         MSG_WriteShort (&sv.reliable_datagram, host_client->frags);
1209                 }
1210         }
1211
1212         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1213                 if (client->netconnection)
1214                         SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
1215
1216         SZ_Clear (&sv.reliable_datagram);
1217 }
1218
1219
1220 /*
1221 =======================
1222 SV_SendNop
1223
1224 Send a nop message without trashing or sending the accumulated client
1225 message buffer
1226 =======================
1227 */
1228 void SV_SendNop (client_t *client)
1229 {
1230         sizebuf_t       msg;
1231         qbyte           buf[4];
1232
1233         msg.data = buf;
1234         msg.maxsize = sizeof(buf);
1235         msg.cursize = 0;
1236
1237         MSG_WriteChar (&msg, svc_nop);
1238
1239         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1240                 SV_DropClient (true);   // if the message couldn't send, kick off
1241         client->last_message = realtime;
1242 }
1243
1244 /*
1245 =======================
1246 SV_SendClientMessages
1247 =======================
1248 */
1249 void SV_SendClientMessages (void)
1250 {
1251         int i, prepared = false;
1252
1253 // update frags, names, etc
1254         SV_UpdateToReliableMessages();
1255
1256 // build individual updates
1257         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1258         {
1259                 if (!host_client->active)
1260                         continue;
1261                 if (!host_client->netconnection)
1262                 {
1263                         SZ_Clear(&host_client->message);
1264                         continue;
1265                 }
1266
1267                 if (host_client->deadsocket || host_client->message.overflowed)
1268                 {
1269                         SV_DropClient (true);   // if the message couldn't send, kick off
1270                         continue;
1271                 }
1272
1273                 if (host_client->spawned)
1274                 {
1275                         if (!prepared)
1276                         {
1277                                 prepared = true;
1278                                 // only prepare entities once per frame
1279                                 SV_PrepareEntitiesForSending();
1280                         }
1281                         if (!SV_SendClientDatagram (host_client))
1282                                 continue;
1283                 }
1284                 else
1285                 {
1286                 // the player isn't totally in the game yet
1287                 // send small keepalive messages if too much time has passed
1288                 // send a full message when the next signon stage has been requested
1289                 // some other message data (name changes, etc) may accumulate
1290                 // between signon stages
1291                         if (!host_client->sendsignon)
1292                         {
1293                                 if (realtime - host_client->last_message > 5)
1294                                         SV_SendNop (host_client);
1295                                 continue;       // don't send out non-signon messages
1296                         }
1297                 }
1298
1299                 if (host_client->message.cursize || host_client->dropasap)
1300                 {
1301                         if (!NetConn_CanSendMessage (host_client->netconnection))
1302                                 continue;
1303
1304                         if (host_client->dropasap)
1305                                 SV_DropClient (false);  // went to another level
1306                         else
1307                         {
1308                                 if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1)
1309                                         SV_DropClient (true);   // if the message couldn't send, kick off
1310                                 SZ_Clear (&host_client->message);
1311                                 host_client->last_message = realtime;
1312                                 host_client->sendsignon = false;
1313                         }
1314                 }
1315         }
1316
1317 // clear muzzle flashes
1318         SV_CleanupEnts();
1319 }
1320
1321
1322 /*
1323 ==============================================================================
1324
1325 SERVER SPAWNING
1326
1327 ==============================================================================
1328 */
1329
1330 /*
1331 ================
1332 SV_ModelIndex
1333
1334 ================
1335 */
1336 int SV_ModelIndex(char *s, int precachemode)
1337 {
1338         int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1339         char filename[MAX_QPATH];
1340         if (!s || !*s)
1341                 return 0;
1342         // testing
1343         //if (precachemode == 2)
1344         //      return 0;
1345         strlcpy(filename, s, sizeof(filename));
1346         for (i = 2;i < limit;i++)
1347         {
1348                 if (!sv.model_precache[i][0])
1349                 {
1350                         if (precachemode)
1351                         {
1352                                 if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
1353                                 {
1354                                         Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename);
1355                                         return 0;
1356                                 }
1357                                 if (precachemode == 1)
1358                                         Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
1359                                 strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
1360                                 sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, false);
1361                                 if (sv.protocol == PROTOCOL_DARKPLACES6 && sv.state != ss_loading)
1362                                 {
1363                                         MSG_WriteByte(&sv.reliable_datagram, svc_precache);
1364                                         MSG_WriteShort(&sv.reliable_datagram, i);
1365                                         MSG_WriteString(&sv.reliable_datagram, filename);
1366                                 }
1367                                 return i;
1368                         }
1369                         Con_Printf("SV_ModelIndex(\"%s\"): not precached\n", filename);
1370                         return 0;
1371                 }
1372                 if (!strcmp(sv.model_precache[i], filename))
1373                         return i;
1374         }
1375         Con_Printf("SV_ModelIndex(\"%s\"): i (%i) == MAX_MODELS (%i)\n", filename, i, MAX_MODELS);
1376         return 0;
1377 }
1378
1379 /*
1380 ================
1381 SV_SoundIndex
1382
1383 ================
1384 */
1385 int SV_SoundIndex(char *s, int precachemode)
1386 {
1387         int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1388         char filename[MAX_QPATH];
1389         if (!s || !*s)
1390                 return 0;
1391         // testing
1392         //if (precachemode == 2)
1393         //      return 0;
1394         strlcpy(filename, s, sizeof(filename));
1395         for (i = 1;i < limit;i++)
1396         {
1397                 if (!sv.sound_precache[i][0])
1398                 {
1399                         if (precachemode)
1400                         {
1401                                 if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
1402                                 {
1403                                         Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename);
1404                                         return 0;
1405                                 }
1406                                 if (precachemode == 1)
1407                                         Con_Printf("SV_SoundIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
1408                                 strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i]));
1409                                 if (sv.protocol == PROTOCOL_DARKPLACES6 && sv.state != ss_loading)
1410                                 {
1411                                         MSG_WriteByte(&sv.reliable_datagram, svc_precache);
1412                                         MSG_WriteShort(&sv.reliable_datagram, i + 32768);
1413                                         MSG_WriteString(&sv.reliable_datagram, filename);
1414                                 }
1415                                 return i;
1416                         }
1417                         Con_Printf("SV_SoundIndex(\"%s\"): not precached\n", filename);
1418                         return 0;
1419                 }
1420                 if (!strcmp(sv.sound_precache[i], filename))
1421                         return i;
1422         }
1423         Con_Printf("SV_SoundIndex(\"%s\"): i (%i) == MAX_SOUNDS (%i)\n", filename, i, MAX_SOUNDS);
1424         return 0;
1425 }
1426
1427 /*
1428 ================
1429 SV_CreateBaseline
1430
1431 ================
1432 */
1433 void SV_CreateBaseline (void)
1434 {
1435         int i, entnum, large;
1436         edict_t *svent;
1437
1438         // LordHavoc: clear *all* states (note just active ones)
1439         for (entnum = 0;entnum < sv.max_edicts;entnum++)
1440         {
1441                 // get the current server version
1442                 svent = EDICT_NUM(entnum);
1443
1444                 // LordHavoc: always clear state values, whether the entity is in use or not
1445                 svent->e->baseline = defaultstate;
1446
1447                 if (svent->e->free)
1448                         continue;
1449                 if (entnum > svs.maxclients && !svent->v->modelindex)
1450                         continue;
1451
1452                 // create entity baseline
1453                 VectorCopy (svent->v->origin, svent->e->baseline.origin);
1454                 VectorCopy (svent->v->angles, svent->e->baseline.angles);
1455                 svent->e->baseline.frame = svent->v->frame;
1456                 svent->e->baseline.skin = svent->v->skin;
1457                 if (entnum > 0 && entnum <= svs.maxclients)
1458                 {
1459                         svent->e->baseline.colormap = entnum;
1460                         svent->e->baseline.modelindex = SV_ModelIndex("progs/player.mdl", 1);
1461                 }
1462                 else
1463                 {
1464                         svent->e->baseline.colormap = 0;
1465                         svent->e->baseline.modelindex = svent->v->modelindex;
1466                 }
1467
1468                 large = false;
1469                 if (svent->e->baseline.modelindex & 0xFF00 || svent->e->baseline.frame & 0xFF00)
1470                         large = true;
1471
1472                 // add to the message
1473                 if (large)
1474                         MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
1475                 else
1476                         MSG_WriteByte (&sv.signon, svc_spawnbaseline);
1477                 MSG_WriteShort (&sv.signon, entnum);
1478
1479                 if (large)
1480                 {
1481                         MSG_WriteShort (&sv.signon, svent->e->baseline.modelindex);
1482                         MSG_WriteShort (&sv.signon, svent->e->baseline.frame);
1483                 }
1484                 else
1485                 {
1486                         MSG_WriteByte (&sv.signon, svent->e->baseline.modelindex);
1487                         MSG_WriteByte (&sv.signon, svent->e->baseline.frame);
1488                 }
1489                 MSG_WriteByte (&sv.signon, svent->e->baseline.colormap);
1490                 MSG_WriteByte (&sv.signon, svent->e->baseline.skin);
1491                 for (i=0 ; i<3 ; i++)
1492                 {
1493                         MSG_WriteCoord(&sv.signon, svent->e->baseline.origin[i], sv.protocol);
1494                         MSG_WriteAngle(&sv.signon, svent->e->baseline.angles[i], sv.protocol);
1495                 }
1496         }
1497 }
1498
1499
1500 /*
1501 ================
1502 SV_SendReconnect
1503
1504 Tell all the clients that the server is changing levels
1505 ================
1506 */
1507 void SV_SendReconnect (void)
1508 {
1509         char    data[128];
1510         sizebuf_t       msg;
1511
1512         msg.data = data;
1513         msg.cursize = 0;
1514         msg.maxsize = sizeof(data);
1515
1516         MSG_WriteChar (&msg, svc_stufftext);
1517         MSG_WriteString (&msg, "reconnect\n");
1518         NetConn_SendToAll (&msg, 5);
1519
1520         if (cls.state != ca_dedicated)
1521                 Cmd_ExecuteString ("reconnect\n", src_command);
1522 }
1523
1524
1525 /*
1526 ================
1527 SV_SaveSpawnparms
1528
1529 Grabs the current state of each client for saving across the
1530 transition to another level
1531 ================
1532 */
1533 void SV_SaveSpawnparms (void)
1534 {
1535         int             i, j;
1536
1537         svs.serverflags = pr_global_struct->serverflags;
1538
1539         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1540         {
1541                 if (!host_client->active)
1542                         continue;
1543
1544         // call the progs to get default spawn parms for the new client
1545                 pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
1546                 PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing");
1547                 for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
1548                         host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
1549         }
1550 }
1551
1552 void SV_IncreaseEdicts(void)
1553 {
1554         int i;
1555         edict_t *ent;
1556         int oldmax_edicts = sv.max_edicts;
1557         void *oldedictsengineprivate = sv.edictsengineprivate;
1558         void *oldedictsfields = sv.edictsfields;
1559         void *oldmoved_edicts = sv.moved_edicts;
1560
1561         if (sv.max_edicts >= MAX_EDICTS)
1562                 return;
1563
1564         // links don't survive the transition, so unlink everything
1565         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1566         {
1567                 if (!ent->e->free)
1568                         SV_UnlinkEdict(sv.edicts + i);
1569                 memset(&ent->e->areagrid, 0, sizeof(ent->e->areagrid));
1570         }
1571         SV_ClearWorld();
1572
1573         sv.max_edicts   = min(sv.max_edicts + 256, MAX_EDICTS);
1574         sv.edictsengineprivate = PR_Alloc(sv.max_edicts * sizeof(edict_engineprivate_t));
1575         sv.edictsfields = PR_Alloc(sv.max_edicts * pr_edict_size);
1576         sv.moved_edicts = PR_Alloc(sv.max_edicts * sizeof(edict_t *));
1577
1578         memcpy(sv.edictsengineprivate, oldedictsengineprivate, oldmax_edicts * sizeof(edict_engineprivate_t));
1579         memcpy(sv.edictsfields, oldedictsfields, oldmax_edicts * pr_edict_size);
1580
1581         for (i = 0, ent = sv.edicts;i < sv.max_edicts;i++, ent++)
1582         {
1583                 ent->e = sv.edictsengineprivate + i;
1584                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1585                 // link every entity except world
1586                 if (!ent->e->free)
1587                         SV_LinkEdict(ent, false);
1588         }
1589
1590         PR_Free(oldedictsengineprivate);
1591         PR_Free(oldedictsfields);
1592         PR_Free(oldmoved_edicts);
1593 }
1594
1595 /*
1596 ================
1597 SV_SpawnServer
1598
1599 This is called at the start of each level
1600 ================
1601 */
1602 extern float            scr_centertime_off;
1603
1604 void SV_SpawnServer (const char *server)
1605 {
1606         edict_t *ent;
1607         int i;
1608         qbyte *entities;
1609         model_t *worldmodel;
1610         char modelname[sizeof(sv.modelname)];
1611
1612         Con_DPrintf("SpawnServer: %s\n", server);
1613
1614         if (cls.state != ca_dedicated)
1615                 SCR_BeginLoadingPlaque();
1616
1617         dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", server);
1618         worldmodel = Mod_ForName(modelname, false, true, true);
1619         if (!worldmodel || !worldmodel->TraceBox)
1620         {
1621                 Con_Printf("Couldn't load map %s\n", modelname);
1622                 return;
1623         }
1624
1625         // let's not have any servers with no name
1626         if (hostname.string[0] == 0)
1627                 Cvar_Set ("hostname", "UNNAMED");
1628         scr_centertime_off = 0;
1629
1630         svs.changelevel_issued = false;         // now safe to issue another
1631
1632 //
1633 // tell all connected clients that we are going to a new level
1634 //
1635         if (sv.active)
1636                 SV_SendReconnect();
1637         else
1638         {
1639                 // make sure cvars have been checked before opening the ports
1640                 NetConn_ServerFrame();
1641                 NetConn_OpenServerPorts(true);
1642         }
1643
1644 //
1645 // make cvars consistant
1646 //
1647         if (coop.integer)
1648                 Cvar_SetValue ("deathmatch", 0);
1649         // LordHavoc: it can be useful to have skills outside the range 0-3...
1650         //current_skill = bound(0, (int)(skill.value + 0.5), 3);
1651         //Cvar_SetValue ("skill", (float)current_skill);
1652         current_skill = (int)(skill.value + 0.5);
1653
1654 //
1655 // set up the new server
1656 //
1657         Host_ClearMemory ();
1658
1659         memset (&sv, 0, sizeof(sv));
1660
1661         strlcpy (sv.name, server, sizeof (sv.name));
1662
1663         sv.netquakecompatible = false;
1664         if (!strcasecmp(sv_protocolname.string, "QUAKE"))
1665         {
1666                 sv.protocol = PROTOCOL_QUAKE;
1667                 sv.netquakecompatible = true;
1668         }
1669         else if (!strcasecmp(sv_protocolname.string, "QUAKEDP"))
1670                 sv.protocol = PROTOCOL_QUAKE;
1671         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES1"))
1672                 sv.protocol = PROTOCOL_DARKPLACES1;
1673         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES2"))
1674                 sv.protocol = PROTOCOL_DARKPLACES2;
1675         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES3"))
1676                 sv.protocol = PROTOCOL_DARKPLACES3;
1677         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES4"))
1678                 sv.protocol = PROTOCOL_DARKPLACES4;
1679         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES5"))
1680                 sv.protocol = PROTOCOL_DARKPLACES5;
1681         else if (!strcasecmp(sv_protocolname.string, "DARKPLACES6"))
1682                 sv.protocol = PROTOCOL_DARKPLACES6;
1683         else
1684         {
1685                 sv.protocol = PROTOCOL_DARKPLACES6;
1686                 Con_Printf("Unknown sv_protocolname \"%s\", valid values are QUAKE, QUAKEDP, DARKPLACES1, DARKPLACES2, DARKPLACES3, DARKPLACES4, DARKPLACES5, DARKPLACES6, falling back to DARKPLACES6 protocol\n", sv_protocolname.string);
1687         }
1688
1689 // load progs to get entity field count
1690         PR_LoadProgs ( sv_progs.string );
1691
1692 // allocate server memory
1693         // start out with just enough room for clients and a reasonable estimate of entities
1694         sv.max_edicts = max(svs.maxclients + 1, 512);
1695         sv.max_edicts = min(sv.max_edicts, MAX_EDICTS);
1696
1697         // edict_t structures (hidden from progs)
1698         sv.edicts = PR_Alloc(MAX_EDICTS * sizeof(edict_t));
1699         // engine private structures (hidden from progs)
1700         sv.edictsengineprivate = PR_Alloc(sv.max_edicts * sizeof(edict_engineprivate_t));
1701         // progs fields, often accessed by server
1702         sv.edictsfields = PR_Alloc(sv.max_edicts * pr_edict_size);
1703         // used by PushMove to move back pushed entities
1704         sv.moved_edicts = PR_Alloc(sv.max_edicts * sizeof(edict_t *));
1705         for (i = 0;i < sv.max_edicts;i++)
1706         {
1707                 ent = sv.edicts + i;
1708                 ent->e = sv.edictsengineprivate + i;
1709                 ent->v = (void *)((qbyte *)sv.edictsfields + i * pr_edict_size);
1710         }
1711
1712         // fix up client->edict pointers for returning clients right away...
1713         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1714                 host_client->edict = EDICT_NUM(i + 1);
1715
1716         sv.datagram.maxsize = sizeof(sv.datagram_buf);
1717         sv.datagram.cursize = 0;
1718         sv.datagram.data = sv.datagram_buf;
1719
1720         sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
1721         sv.reliable_datagram.cursize = 0;
1722         sv.reliable_datagram.data = sv.reliable_datagram_buf;
1723
1724         sv.signon.maxsize = sizeof(sv.signon_buf);
1725         sv.signon.cursize = 0;
1726         sv.signon.data = sv.signon_buf;
1727
1728 // leave slots at start for clients only
1729         sv.num_edicts = svs.maxclients+1;
1730
1731         sv.state = ss_loading;
1732         sv.paused = false;
1733
1734         sv.time = 1.0;
1735
1736         Mod_ClearUsed();
1737         worldmodel->used = true;
1738
1739         strlcpy (sv.name, server, sizeof (sv.name));
1740         strcpy(sv.modelname, modelname);
1741         sv.worldmodel = worldmodel;
1742         sv.models[1] = sv.worldmodel;
1743
1744 //
1745 // clear world interaction links
1746 //
1747         SV_ClearWorld ();
1748
1749         strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0]));
1750
1751         strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0]));
1752         strlcpy(sv.model_precache[1], sv.modelname, sizeof(sv.model_precache[1]));
1753         for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
1754         {
1755                 dpsnprintf(sv.model_precache[i+1], sizeof(sv.model_precache[i+1]), "*%i", i);
1756                 sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, false);
1757         }
1758
1759 //
1760 // load the rest of the entities
1761 //
1762         ent = EDICT_NUM(0);
1763         memset (ent->v, 0, progs->entityfields * 4);
1764         ent->e->free = false;
1765         ent->v->model = PR_SetString(sv.modelname);
1766         ent->v->modelindex = 1;         // world model
1767         ent->v->solid = SOLID_BSP;
1768         ent->v->movetype = MOVETYPE_PUSH;
1769
1770         if (coop.value)
1771                 pr_global_struct->coop = coop.integer;
1772         else
1773                 pr_global_struct->deathmatch = deathmatch.integer;
1774
1775         pr_global_struct->mapname = PR_SetString(sv.name);
1776
1777 // serverflags are for cross level information (sigils)
1778         pr_global_struct->serverflags = svs.serverflags;
1779
1780         // load replacement entity file if found
1781         entities = NULL;
1782         if (sv_entpatch.integer)
1783                 entities = FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true);
1784         if (entities)
1785         {
1786                 Con_Printf("Loaded maps/%s.ent\n", sv.name);
1787                 ED_LoadFromFile (entities);
1788                 Mem_Free(entities);
1789         }
1790         else
1791                 ED_LoadFromFile (sv.worldmodel->brush.entities);
1792
1793
1794         // LordHavoc: clear world angles (to fix e3m3.bsp)
1795         VectorClear(sv.edicts->v->angles);
1796
1797         sv.active = true;
1798
1799 // all setup is completed, any further precache statements are errors
1800         sv.state = ss_active;
1801
1802 // run two frames to allow everything to settle
1803         for (i = 0;i < 2;i++)
1804         {
1805                 sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
1806                 SV_Physics ();
1807         }
1808
1809         Mod_PurgeUnused();
1810
1811 // create a baseline for more efficient communications
1812         if (sv.protocol == PROTOCOL_QUAKE)
1813                 SV_CreateBaseline ();
1814
1815 // send serverinfo to all connected clients
1816         // (note this also handles botclients coming back from a level change)
1817         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1818                 if (host_client->active)
1819                         SV_SendServerinfo(host_client);
1820
1821         Con_DPrint("Server spawned.\n");
1822         NetConn_Heartbeat (2);
1823 }
1824