]> icculus.org git repositories - divverent/darkplaces.git/blob - sv_main.c
csqc patch from [515], seems to work with [515]'s dpcsqc test mod, needs a lot of...
[divverent/darkplaces.git] / sv_main.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // sv_main.c -- server main program
21
22 #include "quakedef.h"
23
24 void SV_VM_Init();
25 void SV_VM_Setup();
26
27 void VM_AutoSentStats_Clear (void);
28 void EntityFrameCSQC_ClearVersions (void);
29 void EntityFrameCSQC_InitClientVersions (int client, qboolean clear);
30 void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
31 void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_state_t *states);
32
33
34 // select which protocol to host, this is fed to Protocol_EnumForName
35 cvar_t sv_protocolname = {0, "sv_protocolname", "DP7"};
36 cvar_t sv_ratelimitlocalplayer = {0, "sv_ratelimitlocalplayer", "0"};
37 cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000"};
38
39 static cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "1"}; // fast but loose
40 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
41 static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
42 static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
43
44 cvar_t sv_gameplayfix_grenadebouncedownslopes = {0, "sv_gameplayfix_grenadebouncedownslopes", "1"};
45 cvar_t sv_gameplayfix_noairborncorpse = {0, "sv_gameplayfix_noairborncorpse", "1"};
46 cvar_t sv_gameplayfix_stepdown = {0, "sv_gameplayfix_stepdown", "1"};
47 cvar_t sv_gameplayfix_stepwhilejumping = {0, "sv_gameplayfix_stepwhilejumping", "1"};
48 cvar_t sv_gameplayfix_swiminbmodels = {0, "sv_gameplayfix_swiminbmodels", "1"};
49 cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1"};
50 cvar_t sv_gameplayfix_blowupfallenzombies = {0, "sv_gameplayfix_blowupfallenzombies", "1"};
51 cvar_t sv_gameplayfix_findradiusdistancetobox = {0, "sv_gameplayfix_findradiusdistancetobox", "1"};
52
53 cvar_t sv_progs = {0, "sv_progs", "progs.dat" };
54
55 server_t sv;
56 server_static_t svs;
57
58 mempool_t *sv_mempool = NULL;
59
60 //============================================================================
61
62 extern void SV_Phys_Init (void);
63 extern void SV_World_Init (void);
64 static void SV_SaveEntFile_f(void);
65
66 /*
67 ===============
68 SV_Init
69 ===============
70 */
71 void SV_Init (void)
72 {
73         Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f);
74         Cvar_RegisterVariable (&sv_maxvelocity);
75         Cvar_RegisterVariable (&sv_gravity);
76         Cvar_RegisterVariable (&sv_friction);
77         Cvar_RegisterVariable (&sv_edgefriction);
78         Cvar_RegisterVariable (&sv_stopspeed);
79         Cvar_RegisterVariable (&sv_maxspeed);
80         Cvar_RegisterVariable (&sv_maxairspeed);
81         Cvar_RegisterVariable (&sv_accelerate);
82         Cvar_RegisterVariable (&sv_idealpitchscale);
83         Cvar_RegisterVariable (&sv_aim);
84         Cvar_RegisterVariable (&sv_nostep);
85         Cvar_RegisterVariable (&sv_deltacompress);
86         Cvar_RegisterVariable (&sv_cullentities_pvs);
87         Cvar_RegisterVariable (&sv_cullentities_trace);
88         Cvar_RegisterVariable (&sv_cullentities_stats);
89         Cvar_RegisterVariable (&sv_entpatch);
90         Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes);
91         Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse);
92         Cvar_RegisterVariable (&sv_gameplayfix_stepdown);
93         Cvar_RegisterVariable (&sv_gameplayfix_stepwhilejumping);
94         Cvar_RegisterVariable (&sv_gameplayfix_swiminbmodels);
95         Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
96         Cvar_RegisterVariable (&sv_gameplayfix_blowupfallenzombies);
97         Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
98         Cvar_RegisterVariable (&sv_protocolname);
99         Cvar_RegisterVariable (&sv_ratelimitlocalplayer);
100         Cvar_RegisterVariable (&sv_maxrate);
101         Cvar_RegisterVariable (&sv_progs);
102
103         SV_VM_Init();
104         SV_Phys_Init();
105         SV_World_Init();
106
107         sv_mempool = Mem_AllocPool("server", 0, NULL);
108 }
109
110 static void SV_SaveEntFile_f(void)
111 {
112         char basename[MAX_QPATH];
113         if (!sv.active || !sv.worldmodel)
114         {
115                 Con_Print("Not running a server\n");
116                 return;
117         }
118         FS_StripExtension(sv.worldmodel->name, basename, sizeof(basename));
119         FS_WriteFile(va("%s.ent", basename), sv.worldmodel->brush.entities, (fs_offset_t)strlen(sv.worldmodel->brush.entities));
120 }
121
122
123 /*
124 =============================================================================
125
126 EVENT MESSAGES
127
128 =============================================================================
129 */
130
131 /*
132 ==================
133 SV_StartParticle
134
135 Make sure the event gets sent to all clients
136 ==================
137 */
138 void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
139 {
140         int             i, v;
141
142         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-18)
143                 return;
144         MSG_WriteByte (&sv.datagram, svc_particle);
145         MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
146         MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
147         MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
148         for (i=0 ; i<3 ; i++)
149         {
150                 v = dir[i]*16;
151                 if (v > 127)
152                         v = 127;
153                 else if (v < -128)
154                         v = -128;
155                 MSG_WriteChar (&sv.datagram, v);
156         }
157         MSG_WriteByte (&sv.datagram, count);
158         MSG_WriteByte (&sv.datagram, color);
159 }
160
161 /*
162 ==================
163 SV_StartEffect
164
165 Make sure the event gets sent to all clients
166 ==================
167 */
168 void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
169 {
170         if (modelindex >= 256 || startframe >= 256)
171         {
172                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-19)
173                         return;
174                 MSG_WriteByte (&sv.datagram, svc_effect2);
175                 MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
176                 MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
177                 MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
178                 MSG_WriteShort (&sv.datagram, modelindex);
179                 MSG_WriteShort (&sv.datagram, startframe);
180                 MSG_WriteByte (&sv.datagram, framecount);
181                 MSG_WriteByte (&sv.datagram, framerate);
182         }
183         else
184         {
185                 if (sv.datagram.cursize > MAX_PACKETFRAGMENT-17)
186                         return;
187                 MSG_WriteByte (&sv.datagram, svc_effect);
188                 MSG_WriteCoord (&sv.datagram, org[0], sv.protocol);
189                 MSG_WriteCoord (&sv.datagram, org[1], sv.protocol);
190                 MSG_WriteCoord (&sv.datagram, org[2], sv.protocol);
191                 MSG_WriteByte (&sv.datagram, modelindex);
192                 MSG_WriteByte (&sv.datagram, startframe);
193                 MSG_WriteByte (&sv.datagram, framecount);
194                 MSG_WriteByte (&sv.datagram, framerate);
195         }
196 }
197
198 /*
199 ==================
200 SV_StartSound
201
202 Each entity can have eight independant sound sources, like voice,
203 weapon, feet, etc.
204
205 Channel 0 is an auto-allocate channel, the others override anything
206 already running on that entity/channel pair.
207
208 An attenuation of 0 will play full volume everywhere in the level.
209 Larger attenuations will drop off.  (max 4 attenuation)
210
211 ==================
212 */
213 void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int volume, float attenuation)
214 {
215         int sound_num, field_mask, i, ent;
216
217         if (volume < 0 || volume > 255)
218         {
219                 Con_Printf ("SV_StartSound: volume = %i\n", volume);
220                 return;
221         }
222
223         if (attenuation < 0 || attenuation > 4)
224         {
225                 Con_Printf ("SV_StartSound: attenuation = %f\n", attenuation);
226                 return;
227         }
228
229         if (channel < 0 || channel > 7)
230         {
231                 Con_Printf ("SV_StartSound: channel = %i\n", channel);
232                 return;
233         }
234
235         if (sv.datagram.cursize > MAX_PACKETFRAGMENT-21)
236                 return;
237
238 // find precache number for sound
239         sound_num = SV_SoundIndex(sample, 1);
240         if (!sound_num)
241                 return;
242
243         ent = PRVM_NUM_FOR_EDICT(entity);
244
245         field_mask = 0;
246         if (volume != DEFAULT_SOUND_PACKET_VOLUME)
247                 field_mask |= SND_VOLUME;
248         if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
249                 field_mask |= SND_ATTENUATION;
250         if (ent >= 8192)
251                 field_mask |= SND_LARGEENTITY;
252         if (sound_num >= 256 || channel >= 8)
253                 field_mask |= SND_LARGESOUND;
254
255 // directed messages go only to the entity they are targeted on
256         MSG_WriteByte (&sv.datagram, svc_sound);
257         MSG_WriteByte (&sv.datagram, field_mask);
258         if (field_mask & SND_VOLUME)
259                 MSG_WriteByte (&sv.datagram, volume);
260         if (field_mask & SND_ATTENUATION)
261                 MSG_WriteByte (&sv.datagram, attenuation*64);
262         if (field_mask & SND_LARGEENTITY)
263         {
264                 MSG_WriteShort (&sv.datagram, ent);
265                 MSG_WriteByte (&sv.datagram, channel);
266         }
267         else
268                 MSG_WriteShort (&sv.datagram, (ent<<3) | channel);
269         if (field_mask & SND_LARGESOUND)
270                 MSG_WriteShort (&sv.datagram, sound_num);
271         else
272                 MSG_WriteByte (&sv.datagram, sound_num);
273         for (i = 0;i < 3;i++)
274                 MSG_WriteCoord (&sv.datagram, entity->fields.server->origin[i]+0.5*(entity->fields.server->mins[i]+entity->fields.server->maxs[i]), sv.protocol);
275 }
276
277 /*
278 ==============================================================================
279
280 CLIENT SPAWNING
281
282 ==============================================================================
283 */
284
285 static const char *SV_InitCmd;  //[515]: svprogs able to send cmd to client on connect
286 /*
287 ================
288 SV_SendServerinfo
289
290 Sends the first message from the server to a connected client.
291 This will be sent on the initial connection and upon each server load.
292 ================
293 */
294 void SV_SendServerinfo (client_t *client)
295 {
296         int i;
297         char message[128];
298
299         // edicts get reallocated on level changes, so we need to update it here
300         client->edict = PRVM_EDICT_NUM((client - svs.clients) + 1);
301
302         // clear cached stuff that depends on the level
303         client->weaponmodel[0] = 0;
304         client->weaponmodelindex = 0;
305
306         // LordHavoc: clear entityframe tracking
307         client->latestframenum = 0;
308
309         if (client->entitydatabase)
310                 EntityFrame_FreeDatabase(client->entitydatabase);
311         if (client->entitydatabase4)
312                 EntityFrame4_FreeDatabase(client->entitydatabase4);
313         if (client->entitydatabase5)
314                 EntityFrame5_FreeDatabase(client->entitydatabase5);
315
316         if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE)
317         {
318                 if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
319                         client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool);
320                 else if (sv.protocol == PROTOCOL_DARKPLACES4)
321                         client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_mempool);
322                 else
323                         client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool);
324         }
325
326         SZ_Clear (&client->message);
327         MSG_WriteByte (&client->message, svc_print);
328         dpsnprintf (message, sizeof (message), "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, prog->filecrc);
329         MSG_WriteString (&client->message,message);
330
331         // LordHavoc: this does not work on dedicated servers, needs fixing.
332 extern qboolean csqc_loaded;
333 //[515]: init csprogs according to version of svprogs, check the crc, etc.
334         if(csqc_loaded && (cls.state == ca_dedicated || PRVM_NUM_FOR_EDICT(client->edict) != 1))
335         {
336                 MSG_WriteByte (&client->message, svc_stufftext);
337                 if(SV_InitCmd)
338                         MSG_WriteString (&client->message, va("csqc_progcrc %i;%s\n", csqc_progcrc.integer, SV_InitCmd));
339                 else
340                         MSG_WriteString (&client->message, va("csqc_progcrc %i\n", csqc_progcrc.integer));
341         }
342
343         MSG_WriteByte (&client->message, svc_serverinfo);
344         MSG_WriteLong (&client->message, Protocol_NumberForEnum(sv.protocol));
345         MSG_WriteByte (&client->message, svs.maxclients);
346
347         if (!coop.integer && deathmatch.integer)
348                 MSG_WriteByte (&client->message, GAME_DEATHMATCH);
349         else
350                 MSG_WriteByte (&client->message, GAME_COOP);
351
352         MSG_WriteString (&client->message,PRVM_GetString(prog->edicts->fields.server->message));
353
354         for (i = 1;i < MAX_MODELS && sv.model_precache[i][0];i++)
355                 MSG_WriteString (&client->message, sv.model_precache[i]);
356         MSG_WriteByte (&client->message, 0);
357
358         for (i = 1;i < MAX_SOUNDS && sv.sound_precache[i][0];i++)
359                 MSG_WriteString (&client->message, sv.sound_precache[i]);
360         MSG_WriteByte (&client->message, 0);
361
362 // send music
363         MSG_WriteByte (&client->message, svc_cdtrack);
364         MSG_WriteByte (&client->message, prog->edicts->fields.server->sounds);
365         MSG_WriteByte (&client->message, prog->edicts->fields.server->sounds);
366
367 // set view
368         MSG_WriteByte (&client->message, svc_setview);
369         MSG_WriteShort (&client->message, PRVM_NUM_FOR_EDICT(client->edict));
370
371         MSG_WriteByte (&client->message, svc_signonnum);
372         MSG_WriteByte (&client->message, 1);
373
374         client->sendsignon = true;
375         client->spawned = false;                // need prespawn, spawn, etc
376 }
377
378 /*
379 ================
380 SV_ConnectClient
381
382 Initializes a client_t for a new net connection.  This will only be called
383 once for a player each game, not once for each level change.
384 ================
385 */
386 void SV_ConnectClient (int clientnum, netconn_t *netconnection)
387 {
388         client_t                *client;
389         int                             i;
390         float                   spawn_parms[NUM_SPAWN_PARMS];
391
392         client = svs.clients + clientnum;
393
394         if(netconnection)//[515]: bots don't play with csqc =)
395                 EntityFrameCSQC_InitClientVersions(clientnum, false);
396
397 // set up the client_t
398         if (sv.loadgame)
399                 memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
400         memset (client, 0, sizeof(*client));
401         client->active = true;
402         client->netconnection = netconnection;
403
404         Con_DPrintf("Client %s connected\n", client->netconnection ? client->netconnection->address : "botclient");
405
406         strcpy(client->name, "unconnected");
407         strcpy(client->old_name, "unconnected");
408         client->spawned = false;
409         client->edict = PRVM_EDICT_NUM(clientnum+1);
410         client->message.data = client->msgbuf;
411         client->message.maxsize = sizeof(client->msgbuf);
412         client->message.allowoverflow = true;           // we can catch it
413         // updated by receiving "rate" command from client
414         client->rate = NET_MINRATE;
415         // no limits for local player
416         if (client->netconnection && LHNETADDRESS_GetAddressType(&client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
417                 client->rate = 1000000000;
418         client->connecttime = realtime;
419
420         if (sv.loadgame)
421                 memcpy (client->spawn_parms, spawn_parms, sizeof(spawn_parms));
422         else
423         {
424                 // call the progs to get default spawn parms for the new client
425                 // set self to world to intentionally cause errors with broken SetNewParms code in some mods
426                 prog->globals.server->self = 0;
427                 PRVM_ExecuteProgram (prog->globals.server->SetNewParms, "QC function SetNewParms is missing");
428                 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
429                         client->spawn_parms[i] = (&prog->globals.server->parm1)[i];
430         }
431
432         // set up the entity for this client (including .colormap, .team, etc)
433         PRVM_ED_ClearEdict(client->edict);
434
435         // don't call SendServerinfo for a fresh botclient because its fields have
436         // not been set up by the qc yet
437         if (client->netconnection)
438                 SV_SendServerinfo (client);
439         else
440                 client->spawned = true;
441 }
442
443
444 /*
445 ===============================================================================
446
447 FRAME UPDATES
448
449 ===============================================================================
450 */
451
452 /*
453 ==================
454 SV_ClearDatagram
455
456 ==================
457 */
458 void SV_ClearDatagram (void)
459 {
460         SZ_Clear (&sv.datagram);
461 }
462
463 /*
464 =============================================================================
465
466 The PVS must include a small area around the client to allow head bobbing
467 or other small motion on the client side.  Otherwise, a bob might cause an
468 entity that should be visible to not show up, especially when the bob
469 crosses a waterline.
470
471 =============================================================================
472 */
473
474 int sv_writeentitiestoclient_pvsbytes;
475 unsigned char sv_writeentitiestoclient_pvs[MAX_MAP_LEAFS/8];
476
477 static int numsendentities;
478 static entity_state_t sendentities[MAX_EDICTS];
479 static entity_state_t *sendentitiesindex[MAX_EDICTS];
480
481 qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *cs, int e)
482 {
483         int i;
484         unsigned int modelindex, effects, flags, glowsize, lightstyle, lightpflags, light[4], specialvisibilityradius;
485         unsigned int customizeentityforclient;
486         float f;
487         vec3_t cullmins, cullmaxs;
488         model_t *model;
489         prvm_eval_t *val;
490
491         // EF_NODRAW prevents sending for any reason except for your own
492         // client, so we must keep all clients in this superset
493         effects = (unsigned)ent->fields.server->effects;
494
495         // we can omit invisible entities with no effects that are not clients
496         // LordHavoc: this could kill tags attached to an invisible entity, I
497         // just hope we never have to support that case
498         i = (int)ent->fields.server->modelindex;
499         modelindex = (i >= 1 && i < MAX_MODELS && *PRVM_GetString(ent->fields.server->model)) ? i : 0;
500
501         flags = 0;
502         i = (int)(PRVM_GETEDICTFIELDVALUE(ent, eval_glow_size)->_float * 0.25f);
503         glowsize = (unsigned char)bound(0, i, 255);
504         if (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_trail)->_float)
505                 flags |= RENDER_GLOWTRAIL;
506
507         f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[0]*256;
508         light[0] = (unsigned short)bound(0, f, 65535);
509         f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[1]*256;
510         light[1] = (unsigned short)bound(0, f, 65535);
511         f = PRVM_GETEDICTFIELDVALUE(ent, eval_color)->vector[2]*256;
512         light[2] = (unsigned short)bound(0, f, 65535);
513         f = PRVM_GETEDICTFIELDVALUE(ent, eval_light_lev)->_float;
514         light[3] = (unsigned short)bound(0, f, 65535);
515         lightstyle = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_style)->_float;
516         lightpflags = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_pflags)->_float;
517
518         if (gamemode == GAME_TENEBRAE)
519         {
520                 // tenebrae's EF_FULLDYNAMIC conflicts with Q2's EF_NODRAW
521                 if (effects & 16)
522                 {
523                         effects &= ~16;
524                         lightpflags |= PFLAGS_FULLDYNAMIC;
525                 }
526                 // tenebrae's EF_GREEN conflicts with DP's EF_ADDITIVE
527                 if (effects & 32)
528                 {
529                         effects &= ~32;
530                         light[0] = 0.2;
531                         light[1] = 1;
532                         light[2] = 0.2;
533                         light[3] = 200;
534                         lightpflags |= PFLAGS_FULLDYNAMIC;
535                 }
536         }
537
538         specialvisibilityradius = 0;
539         if (lightpflags & PFLAGS_FULLDYNAMIC)
540                 specialvisibilityradius = max(specialvisibilityradius, light[3]);
541         if (glowsize)
542                 specialvisibilityradius = max(specialvisibilityradius, glowsize * 4);
543         if (flags & RENDER_GLOWTRAIL)
544                 specialvisibilityradius = max(specialvisibilityradius, 100);
545         if (effects & (EF_BRIGHTFIELD | EF_MUZZLEFLASH | EF_BRIGHTLIGHT | EF_DIMLIGHT | EF_RED | EF_BLUE | EF_FLAME | EF_STARDUST))
546         {
547                 if (effects & EF_BRIGHTFIELD)
548                         specialvisibilityradius = max(specialvisibilityradius, 80);
549                 if (effects & EF_MUZZLEFLASH)
550                         specialvisibilityradius = max(specialvisibilityradius, 100);
551                 if (effects & EF_BRIGHTLIGHT)
552                         specialvisibilityradius = max(specialvisibilityradius, 400);
553                 if (effects & EF_DIMLIGHT)
554                         specialvisibilityradius = max(specialvisibilityradius, 200);
555                 if (effects & EF_RED)
556                         specialvisibilityradius = max(specialvisibilityradius, 200);
557                 if (effects & EF_BLUE)
558                         specialvisibilityradius = max(specialvisibilityradius, 200);
559                 if (effects & EF_FLAME)
560                         specialvisibilityradius = max(specialvisibilityradius, 250);
561                 if (effects & EF_STARDUST)
562                         specialvisibilityradius = max(specialvisibilityradius, 100);
563         }
564
565         // early culling checks
566         // (final culling is done by SV_MarkWriteEntityStateToClient)
567         customizeentityforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_customizeentityforclient)->function;
568         if (!customizeentityforclient)
569         {
570                 if (e > svs.maxclients && (!modelindex && !specialvisibilityradius))
571                         return false;
572                 // this 2 billion unit check is actually to detect NAN origins
573                 // (we really don't want to send those)
574                 if (VectorLength2(ent->fields.server->origin) > 2000000000.0*2000000000.0)
575                         return false;
576         }
577
578
579         *cs = defaultstate;
580         cs->active = true;
581         cs->number = e;
582         VectorCopy(ent->fields.server->origin, cs->origin);
583         VectorCopy(ent->fields.server->angles, cs->angles);
584         cs->flags = flags;
585         cs->effects = effects;
586         cs->colormap = (unsigned)ent->fields.server->colormap;
587         cs->modelindex = modelindex;
588         cs->skin = (unsigned)ent->fields.server->skin;
589         cs->frame = (unsigned)ent->fields.server->frame;
590         cs->viewmodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)->edict;
591         cs->exteriormodelforclient = PRVM_GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)->edict;
592         cs->nodrawtoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)->edict;
593         cs->drawonlytoclient = PRVM_GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)->edict;
594         cs->customizeentityforclient = customizeentityforclient;
595         cs->tagentity = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)->edict;
596         cs->tagindex = (unsigned char)PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float;
597         cs->glowsize = glowsize;
598
599         // don't need to init cs->colormod because the defaultstate did that for us
600         //cs->colormod[0] = cs->colormod[1] = cs->colormod[2] = 32;
601         val = PRVM_GETEDICTFIELDVALUE(ent, eval_colormod);
602         if (val->vector[0] || val->vector[1] || val->vector[2])
603         {
604                 i = val->vector[0] * 32.0f;cs->colormod[0] = bound(0, i, 255);
605                 i = val->vector[1] * 32.0f;cs->colormod[1] = bound(0, i, 255);
606                 i = val->vector[2] * 32.0f;cs->colormod[2] = bound(0, i, 255);
607         }
608
609         cs->modelindex = modelindex;
610
611         cs->alpha = 255;
612         f = (PRVM_GETEDICTFIELDVALUE(ent, eval_alpha)->_float * 255.0f);
613         if (f)
614         {
615                 i = (int)f;
616                 cs->alpha = (unsigned char)bound(0, i, 255);
617         }
618         // halflife
619         f = (PRVM_GETEDICTFIELDVALUE(ent, eval_renderamt)->_float);
620         if (f)
621         {
622                 i = (int)f;
623                 cs->alpha = (unsigned char)bound(0, i, 255);
624         }
625
626         cs->scale = 16;
627         f = (PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float * 16.0f);
628         if (f)
629         {
630                 i = (int)f;
631                 cs->scale = (unsigned char)bound(0, i, 255);
632         }
633
634         cs->glowcolor = 254;
635         f = (PRVM_GETEDICTFIELDVALUE(ent, eval_glow_color)->_float);
636         if (f)
637                 cs->glowcolor = (int)f;
638
639         if (PRVM_GETEDICTFIELDVALUE(ent, eval_fullbright)->_float)
640                 cs->effects |= EF_FULLBRIGHT;
641
642         if (ent->fields.server->movetype == MOVETYPE_STEP)
643                 cs->flags |= RENDER_STEP;
644         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)
645                 cs->flags |= RENDER_LOWPRECISION;
646         if (ent->fields.server->colormap >= 1024)
647                 cs->flags |= RENDER_COLORMAPPED;
648         if (cs->viewmodelforclient)
649                 cs->flags |= RENDER_VIEWMODEL; // show relative to the view
650
651         cs->light[0] = light[0];
652         cs->light[1] = light[1];
653         cs->light[2] = light[2];
654         cs->light[3] = light[3];
655         cs->lightstyle = lightstyle;
656         cs->lightpflags = lightpflags;
657
658         cs->specialvisibilityradius = specialvisibilityradius;
659
660         // calculate the visible box of this entity (don't use the physics box
661         // as that is often smaller than a model, and would not count
662         // specialvisibilityradius)
663         if ((model = sv.models[modelindex]))
664         {
665                 float scale = cs->scale * (1.0f / 16.0f);
666                 if (cs->angles[0] || cs->angles[2]) // pitch and roll
667                 {
668                         VectorMA(cs->origin, scale, model->rotatedmins, cullmins);
669                         VectorMA(cs->origin, scale, model->rotatedmaxs, cullmaxs);
670                 }
671                 else if (cs->angles[1])
672                 {
673                         VectorMA(cs->origin, scale, model->yawmins, cullmins);
674                         VectorMA(cs->origin, scale, model->yawmaxs, cullmaxs);
675                 }
676                 else
677                 {
678                         VectorMA(cs->origin, scale, model->normalmins, cullmins);
679                         VectorMA(cs->origin, scale, model->normalmaxs, cullmaxs);
680                 }
681         }
682         else
683         {
684                 VectorCopy(cs->origin, cullmins);
685                 VectorCopy(cs->origin, cullmaxs);
686         }
687         if (specialvisibilityradius)
688         {
689                 cullmins[0] = min(cullmins[0], cs->origin[0] - specialvisibilityradius);
690                 cullmins[1] = min(cullmins[1], cs->origin[1] - specialvisibilityradius);
691                 cullmins[2] = min(cullmins[2], cs->origin[2] - specialvisibilityradius);
692                 cullmaxs[0] = max(cullmaxs[0], cs->origin[0] + specialvisibilityradius);
693                 cullmaxs[1] = max(cullmaxs[1], cs->origin[1] + specialvisibilityradius);
694                 cullmaxs[2] = max(cullmaxs[2], cs->origin[2] + specialvisibilityradius);
695         }
696         if (!VectorCompare(cullmins, ent->priv.server->cullmins) || !VectorCompare(cullmaxs, ent->priv.server->cullmaxs))
697         {
698                 VectorCopy(cullmins, ent->priv.server->cullmins);
699                 VectorCopy(cullmaxs, ent->priv.server->cullmaxs);
700                 ent->priv.server->pvs_numclusters = -1;
701                 if (sv.worldmodel && sv.worldmodel->brush.FindBoxClusters)
702                 {
703                         i = sv.worldmodel->brush.FindBoxClusters(sv.worldmodel, cullmins, cullmaxs, MAX_ENTITYCLUSTERS, ent->priv.server->pvs_clusterlist);
704                         if (i <= MAX_ENTITYCLUSTERS)
705                                 ent->priv.server->pvs_numclusters = i;
706                 }
707         }
708
709         return true;
710 }
711
712 void SV_PrepareEntitiesForSending(void)
713 {
714         int e;
715         prvm_edict_t *ent;
716         // send all entities that touch the pvs
717         numsendentities = 0;
718         sendentitiesindex[0] = NULL;
719         memset(sendentitiesindex, 0, prog->num_edicts * sizeof(entity_state_t *));
720         for (e = 1, ent = PRVM_NEXT_EDICT(prog->edicts);e < prog->num_edicts;e++, ent = PRVM_NEXT_EDICT(ent))
721         {
722                 if (!ent->priv.server->free && SV_PrepareEntityForSending(ent, sendentities + numsendentities, e))
723                 {
724                         sendentitiesindex[e] = sendentities + numsendentities;
725                         numsendentities++;
726                 }
727         }
728 }
729
730 static int sententitiesmark = 0;
731 static int sententities[MAX_EDICTS];
732 static int sententitiesconsideration[MAX_EDICTS];
733 static int sv_writeentitiestoclient_culled_pvs;
734 static int sv_writeentitiestoclient_culled_trace;
735 static int sv_writeentitiestoclient_visibleentities;
736 static int sv_writeentitiestoclient_totalentities;
737 //static entity_frame_t sv_writeentitiestoclient_entityframe;
738 static int sv_writeentitiestoclient_clentnum;
739 static vec3_t sv_writeentitiestoclient_testeye;
740 static client_t *sv_writeentitiestoclient_client;
741
742 void SV_MarkWriteEntityStateToClient(entity_state_t *s)
743 {
744         int isbmodel;
745         vec3_t testorigin;
746         model_t *model;
747         prvm_edict_t *ed;
748         trace_t trace;
749         if (sententitiesconsideration[s->number] == sententitiesmark)
750                 return;
751         sententitiesconsideration[s->number] = sententitiesmark;
752         sv_writeentitiestoclient_totalentities++;
753
754         if (s->customizeentityforclient)
755         {
756                 prog->globals.server->self = s->number;
757                 prog->globals.server->other = sv_writeentitiestoclient_clentnum;
758                 PRVM_ExecuteProgram(s->customizeentityforclient, "customizeentityforclient: NULL function");
759                 if(!PRVM_G_FLOAT(OFS_RETURN) || !SV_PrepareEntityForSending(PRVM_EDICT_NUM(s->number), s, s->number))
760                         return;
761         }
762
763         // never reject player
764         if (s->number != sv_writeentitiestoclient_clentnum)
765         {
766                 // check various rejection conditions
767                 if (s->nodrawtoclient == sv_writeentitiestoclient_clentnum)
768                         return;
769                 if (s->drawonlytoclient && s->drawonlytoclient != sv_writeentitiestoclient_clentnum)
770                         return;
771                 if (s->effects & EF_NODRAW)
772                         return;
773                 // LordHavoc: only send entities with a model or important effects
774                 if (!s->modelindex && s->specialvisibilityradius == 0)
775                         return;
776
777                 // viewmodels don't have visibility checking
778                 if (s->viewmodelforclient)
779                 {
780                         if (s->viewmodelforclient != sv_writeentitiestoclient_clentnum)
781                                 return;
782                 }
783                 else if (s->tagentity)
784                 {
785                         // tag attached entities simply check their parent
786                         if (!sendentitiesindex[s->tagentity])
787                                 return;
788                         SV_MarkWriteEntityStateToClient(sendentitiesindex[s->tagentity]);
789                         if (sententities[s->tagentity] != sententitiesmark)
790                                 return;
791                 }
792                 // always send world submodels in newer protocols because they don't
793                 // generate much traffic (in old protocols they hog bandwidth)
794                 else if (!(s->effects & EF_NODEPTHTEST) && !((isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*') && (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE)))
795                 {
796                         // entity has survived every check so far, check if visible
797                         ed = PRVM_EDICT_NUM(s->number);
798
799                         // if not touching a visible leaf
800                         if (sv_cullentities_pvs.integer && sv_writeentitiestoclient_pvsbytes)
801                         {
802                                 if (ed->priv.server->pvs_numclusters < 0)
803                                 {
804                                         // entity too big for clusters list
805                                         if (sv.worldmodel && sv.worldmodel->brush.BoxTouchingPVS && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, sv_writeentitiestoclient_pvs, ed->priv.server->cullmins, ed->priv.server->cullmaxs))
806                                         {
807                                                 sv_writeentitiestoclient_culled_pvs++;
808                                                 return;
809                                         }
810                                 }
811                                 else
812                                 {
813                                         int i;
814                                         // check cached clusters list
815                                         for (i = 0;i < ed->priv.server->pvs_numclusters;i++)
816                                                 if (CHECKPVSBIT(sv_writeentitiestoclient_pvs, ed->priv.server->pvs_clusterlist[i]))
817                                                         break;
818                                         if (i == ed->priv.server->pvs_numclusters)
819                                         {
820                                                 sv_writeentitiestoclient_culled_pvs++;
821                                                 return;
822                                         }
823                                 }
824                         }
825
826                         // or not seen by random tracelines
827                         if (sv_cullentities_trace.integer && !isbmodel)
828                         {
829                                 // LordHavoc: test center first
830                                 testorigin[0] = (ed->priv.server->cullmins[0] + ed->priv.server->cullmaxs[0]) * 0.5f;
831                                 testorigin[1] = (ed->priv.server->cullmins[1] + ed->priv.server->cullmaxs[1]) * 0.5f;
832                                 testorigin[2] = (ed->priv.server->cullmins[2] + ed->priv.server->cullmaxs[2]) * 0.5f;
833                                 sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
834                                 if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, ed->priv.server->cullmins, ed->priv.server->cullmaxs))
835                                         sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
836                                 else
837                                 {
838                                         // LordHavoc: test random offsets, to maximize chance of detection
839                                         testorigin[0] = lhrandom(ed->priv.server->cullmins[0], ed->priv.server->cullmaxs[0]);
840                                         testorigin[1] = lhrandom(ed->priv.server->cullmins[1], ed->priv.server->cullmaxs[1]);
841                                         testorigin[2] = lhrandom(ed->priv.server->cullmins[2], ed->priv.server->cullmaxs[2]);
842                                         sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
843                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, ed->priv.server->cullmins, ed->priv.server->cullmaxs))
844                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
845                                         else
846                                         {
847                                                 if (s->specialvisibilityradius)
848                                                 {
849                                                         // LordHavoc: test random offsets, to maximize chance of detection
850                                                         testorigin[0] = lhrandom(ed->priv.server->cullmins[0], ed->priv.server->cullmaxs[0]);
851                                                         testorigin[1] = lhrandom(ed->priv.server->cullmins[1], ed->priv.server->cullmaxs[1]);
852                                                         testorigin[2] = lhrandom(ed->priv.server->cullmins[2], ed->priv.server->cullmaxs[2]);
853                                                         sv.worldmodel->TraceBox(sv.worldmodel, 0, &trace, sv_writeentitiestoclient_testeye, sv_writeentitiestoclient_testeye, testorigin, testorigin, SUPERCONTENTS_SOLID);
854                                                         if (trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, ed->priv.server->cullmins, ed->priv.server->cullmaxs))
855                                                                 sv_writeentitiestoclient_client->visibletime[s->number] = realtime + 1;
856                                                 }
857                                         }
858                                 }
859                                 if (realtime > sv_writeentitiestoclient_client->visibletime[s->number])
860                                 {
861                                         sv_writeentitiestoclient_culled_trace++;
862                                         return;
863                                 }
864                         }
865                 }
866         }
867
868         // this just marks it for sending
869         // FIXME: it would be more efficient to send here, but the entity
870         // compressor isn't that flexible
871         sv_writeentitiestoclient_visibleentities++;
872         sententities[s->number] = sententitiesmark;
873 }
874
875 entity_state_t sendstates[MAX_EDICTS];
876
877 void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg, int *stats)
878 {
879         int i, numsendstates;
880         entity_state_t *s;
881         extern int csqc_clent;
882
883         // if there isn't enough space to accomplish anything, skip it
884         if (msg->cursize + 25 > msg->maxsize)
885                 return;
886
887         sv_writeentitiestoclient_client = client;
888
889         sv_writeentitiestoclient_culled_pvs = 0;
890         sv_writeentitiestoclient_culled_trace = 0;
891         sv_writeentitiestoclient_visibleentities = 0;
892         sv_writeentitiestoclient_totalentities = 0;
893
894 // find the client's PVS
895         // the real place being tested from
896         VectorAdd(clent->fields.server->origin, clent->fields.server->view_ofs, sv_writeentitiestoclient_testeye);
897         sv_writeentitiestoclient_pvsbytes = 0;
898         if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
899                 sv_writeentitiestoclient_pvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, sv_writeentitiestoclient_testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
900
901         csqc_clent = sv_writeentitiestoclient_clentnum = PRVM_EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
902
903         sententitiesmark++;
904
905         for (i = 0;i < numsendentities;i++)
906                 SV_MarkWriteEntityStateToClient(sendentities + i);
907
908         numsendstates = 0;
909         for (i = 0;i < numsendentities;i++)
910         {
911                 if (sententities[sendentities[i].number] == sententitiesmark)
912                 {
913                         s = &sendstates[numsendstates++];
914                         *s = sendentities[i];
915                         if (s->exteriormodelforclient && s->exteriormodelforclient == sv_writeentitiestoclient_clentnum)
916                                 s->flags |= RENDER_EXTERIORMODEL;
917                 }
918         }
919
920         if (sv_cullentities_stats.integer)
921                 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);
922
923         EntityFrameCSQC_WriteFrame(msg, numsendstates, sendstates);
924
925         if (client->entitydatabase5)
926                 EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats, client->movesequence);
927         else if (client->entitydatabase4)
928                 EntityFrame4_WriteFrame(msg, client->entitydatabase4, numsendstates, sendstates);
929         else if (client->entitydatabase)
930                 EntityFrame_WriteFrame(msg, client->entitydatabase, numsendstates, sendstates, client - svs.clients + 1);
931         else
932                 EntityFrameQuake_WriteFrame(msg, numsendstates, sendstates);
933 }
934
935 /*
936 =============
937 SV_CleanupEnts
938
939 =============
940 */
941 void SV_CleanupEnts (void)
942 {
943         int             e;
944         prvm_edict_t    *ent;
945
946         ent = PRVM_NEXT_EDICT(prog->edicts);
947         for (e=1 ; e<prog->num_edicts ; e++, ent = PRVM_NEXT_EDICT(ent))
948                 ent->fields.server->effects = (int)ent->fields.server->effects & ~EF_MUZZLEFLASH;
949 }
950
951 /*
952 ==================
953 SV_WriteClientdataToMessage
954
955 ==================
956 */
957 void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
958 {
959         int             bits;
960         int             i;
961         prvm_edict_t    *other;
962         int             items;
963         prvm_eval_t     *val;
964         vec3_t  punchvector;
965         unsigned char   viewzoom;
966         const char *s;
967
968 //
969 // send a damage message
970 //
971         if (ent->fields.server->dmg_take || ent->fields.server->dmg_save)
972         {
973                 other = PRVM_PROG_TO_EDICT(ent->fields.server->dmg_inflictor);
974                 MSG_WriteByte (msg, svc_damage);
975                 MSG_WriteByte (msg, ent->fields.server->dmg_save);
976                 MSG_WriteByte (msg, ent->fields.server->dmg_take);
977                 for (i=0 ; i<3 ; i++)
978                         MSG_WriteCoord (msg, other->fields.server->origin[i] + 0.5*(other->fields.server->mins[i] + other->fields.server->maxs[i]), sv.protocol);
979
980                 ent->fields.server->dmg_take = 0;
981                 ent->fields.server->dmg_save = 0;
982         }
983
984 //
985 // send the current viewpos offset from the view entity
986 //
987         SV_SetIdealPitch ();            // how much to look up / down ideally
988
989 // a fixangle might get lost in a dropped packet.  Oh well.
990         if ( ent->fields.server->fixangle )
991         {
992                 MSG_WriteByte (msg, svc_setangle);
993                 for (i=0 ; i < 3 ; i++)
994                         MSG_WriteAngle (msg, ent->fields.server->angles[i], sv.protocol);
995                 ent->fields.server->fixangle = 0;
996         }
997
998         // stuff the sigil bits into the high bits of items for sbar, or else
999         // mix in items2
1000         val = PRVM_GETEDICTFIELDVALUE(ent, eval_items2);
1001         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1002                 items = (int)ent->fields.server->items | ((int)val->_float << 23);
1003         else
1004                 items = (int)ent->fields.server->items | ((int)prog->globals.server->serverflags << 28);
1005
1006         VectorClear(punchvector);
1007         if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_punchvector)))
1008                 VectorCopy(val->vector, punchvector);
1009
1010         // cache weapon model name and index in client struct to save time
1011         // (this search can be almost 1% of cpu time!)
1012         s = PRVM_GetString(ent->fields.server->weaponmodel);
1013         if (strcmp(s, client->weaponmodel))
1014         {
1015                 strlcpy(client->weaponmodel, s, sizeof(client->weaponmodel));
1016                 client->weaponmodelindex = SV_ModelIndex(s, 1);
1017         }
1018
1019         viewzoom = 255;
1020         if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewzoom)))
1021                 viewzoom = val->_float * 255.0f;
1022         if (viewzoom == 0)
1023                 viewzoom = 255;
1024
1025         bits = 0;
1026
1027         if ((int)ent->fields.server->flags & FL_ONGROUND)
1028                 bits |= SU_ONGROUND;
1029         if (ent->fields.server->waterlevel >= 2)
1030                 bits |= SU_INWATER;
1031         if (ent->fields.server->idealpitch)
1032                 bits |= SU_IDEALPITCH;
1033
1034         for (i=0 ; i<3 ; i++)
1035         {
1036                 if (ent->fields.server->punchangle[i])
1037                         bits |= (SU_PUNCH1<<i);
1038                 if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE)
1039                         if (punchvector[i])
1040                                 bits |= (SU_PUNCHVEC1<<i);
1041                 if (ent->fields.server->velocity[i])
1042                         bits |= (SU_VELOCITY1<<i);
1043         }
1044
1045         memset(stats, 0, sizeof(int[MAX_CL_STATS]));
1046         stats[STAT_VIEWHEIGHT] = ent->fields.server->view_ofs[2];
1047         stats[STAT_ITEMS] = items;
1048         stats[STAT_WEAPONFRAME] = ent->fields.server->weaponframe;
1049         stats[STAT_ARMOR] = ent->fields.server->armorvalue;
1050         stats[STAT_WEAPON] = client->weaponmodelindex;
1051         stats[STAT_HEALTH] = ent->fields.server->health;
1052         stats[STAT_AMMO] = ent->fields.server->currentammo;
1053         stats[STAT_SHELLS] = ent->fields.server->ammo_shells;
1054         stats[STAT_NAILS] = ent->fields.server->ammo_nails;
1055         stats[STAT_ROCKETS] = ent->fields.server->ammo_rockets;
1056         stats[STAT_CELLS] = ent->fields.server->ammo_cells;
1057         stats[STAT_ACTIVEWEAPON] = ent->fields.server->weapon;
1058         stats[STAT_VIEWZOOM] = viewzoom;
1059         // the QC bumps these itself by sending svc_'s, so we have to keep them
1060         // zero or they'll be corrected by the engine
1061         //stats[STAT_TOTALSECRETS] = prog->globals.server->total_secrets;
1062         //stats[STAT_TOTALMONSTERS] = prog->globals.server->total_monsters;
1063         //stats[STAT_SECRETS] = prog->globals.server->found_secrets;
1064         //stats[STAT_MONSTERS] = prog->globals.server->killed_monsters;
1065
1066         if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
1067         {
1068                 if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT;
1069                 bits |= SU_ITEMS;
1070                 if (stats[STAT_WEAPONFRAME]) bits |= SU_WEAPONFRAME;
1071                 if (stats[STAT_ARMOR]) bits |= SU_ARMOR;
1072                 bits |= SU_WEAPON;
1073                 // FIXME: which protocols support this?  does PROTOCOL_DARKPLACES3 support viewzoom?
1074                 if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
1075                         if (viewzoom != 255)
1076                                 bits |= SU_VIEWZOOM;
1077         }
1078
1079         if (bits >= 65536)
1080                 bits |= SU_EXTEND1;
1081         if (bits >= 16777216)
1082                 bits |= SU_EXTEND2;
1083
1084         // send the data
1085         MSG_WriteByte (msg, svc_clientdata);
1086         MSG_WriteShort (msg, bits);
1087         if (bits & SU_EXTEND1)
1088                 MSG_WriteByte(msg, bits >> 16);
1089         if (bits & SU_EXTEND2)
1090                 MSG_WriteByte(msg, bits >> 24);
1091
1092         if (bits & SU_VIEWHEIGHT)
1093                 MSG_WriteChar (msg, stats[STAT_VIEWHEIGHT]);
1094
1095         if (bits & SU_IDEALPITCH)
1096                 MSG_WriteChar (msg, ent->fields.server->idealpitch);
1097
1098         for (i=0 ; i<3 ; i++)
1099         {
1100                 if (bits & (SU_PUNCH1<<i))
1101                 {
1102                         if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
1103                                 MSG_WriteChar(msg, ent->fields.server->punchangle[i]);
1104                         else
1105                                 MSG_WriteAngle16i(msg, ent->fields.server->punchangle[i]);
1106                 }
1107                 if (bits & (SU_PUNCHVEC1<<i))
1108                 {
1109                         if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1110                                 MSG_WriteCoord16i(msg, punchvector[i]);
1111                         else
1112                                 MSG_WriteCoord32f(msg, punchvector[i]);
1113                 }
1114                 if (bits & (SU_VELOCITY1<<i))
1115                 {
1116                         if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1117                                 MSG_WriteChar(msg, ent->fields.server->velocity[i] * (1.0f / 16.0f));
1118                         else
1119                                 MSG_WriteCoord32f(msg, ent->fields.server->velocity[i]);
1120                 }
1121         }
1122
1123         if (bits & SU_ITEMS)
1124                 MSG_WriteLong (msg, stats[STAT_ITEMS]);
1125
1126         if (sv.protocol == PROTOCOL_DARKPLACES5)
1127         {
1128                 if (bits & SU_WEAPONFRAME)
1129                         MSG_WriteShort (msg, stats[STAT_WEAPONFRAME]);
1130                 if (bits & SU_ARMOR)
1131                         MSG_WriteShort (msg, stats[STAT_ARMOR]);
1132                 if (bits & SU_WEAPON)
1133                         MSG_WriteShort (msg, stats[STAT_WEAPON]);
1134                 MSG_WriteShort (msg, stats[STAT_HEALTH]);
1135                 MSG_WriteShort (msg, stats[STAT_AMMO]);
1136                 MSG_WriteShort (msg, stats[STAT_SHELLS]);
1137                 MSG_WriteShort (msg, stats[STAT_NAILS]);
1138                 MSG_WriteShort (msg, stats[STAT_ROCKETS]);
1139                 MSG_WriteShort (msg, stats[STAT_CELLS]);
1140                 MSG_WriteShort (msg, stats[STAT_ACTIVEWEAPON]);
1141                 if (bits & SU_VIEWZOOM)
1142                         MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
1143         }
1144         else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1145         {
1146                 if (bits & SU_WEAPONFRAME)
1147                         MSG_WriteByte (msg, stats[STAT_WEAPONFRAME]);
1148                 if (bits & SU_ARMOR)
1149                         MSG_WriteByte (msg, stats[STAT_ARMOR]);
1150                 if (bits & SU_WEAPON)
1151                         MSG_WriteByte (msg, stats[STAT_WEAPON]);
1152                 MSG_WriteShort (msg, stats[STAT_HEALTH]);
1153                 MSG_WriteByte (msg, stats[STAT_AMMO]);
1154                 MSG_WriteByte (msg, stats[STAT_SHELLS]);
1155                 MSG_WriteByte (msg, stats[STAT_NAILS]);
1156                 MSG_WriteByte (msg, stats[STAT_ROCKETS]);
1157                 MSG_WriteByte (msg, stats[STAT_CELLS]);
1158                 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
1159                 {
1160                         for (i = 0;i < 32;i++)
1161                                 if (stats[STAT_WEAPON] & (1<<i))
1162                                         break;
1163                         MSG_WriteByte (msg, i);
1164                 }
1165                 else
1166                         MSG_WriteByte (msg, stats[STAT_WEAPON]);
1167                 if (bits & SU_VIEWZOOM)
1168                 {
1169                         if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1170                                 MSG_WriteByte (msg, min(stats[STAT_VIEWZOOM], 255));
1171                         else
1172                                 MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
1173                 }
1174         }
1175 }
1176
1177 /*
1178 =======================
1179 SV_SendClientDatagram
1180 =======================
1181 */
1182 static unsigned char sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
1183 qboolean SV_SendClientDatagram (client_t *client)
1184 {
1185         int rate, maxrate, maxsize, maxsize2;
1186         sizebuf_t msg;
1187         int stats[MAX_CL_STATS];
1188
1189         if (LHNETADDRESS_GetAddressType(&host_client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP && !sv_ratelimitlocalplayer.integer)
1190         {
1191                 // for good singleplayer, send huge packets
1192                 maxsize = sizeof(sv_sendclientdatagram_buf);
1193                 maxsize2 = sizeof(sv_sendclientdatagram_buf);
1194         }
1195         else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
1196         {
1197                 // no rate limiting support on older protocols because dp protocols
1198                 // 1-4 kick the client off if they overflow, and quake protocol shows
1199                 // less than the full entity set if rate limited
1200                 maxsize = 1400;
1201                 maxsize2 = 1400;
1202         }
1203         else
1204         {
1205                 // PROTOCOL_DARKPLACES5 and later support packet size limiting of updates
1206                 maxrate = bound(NET_MINRATE, sv_maxrate.integer, NET_MAXRATE);
1207                 if (sv_maxrate.integer != maxrate)
1208                         Cvar_SetValueQuick(&sv_maxrate, maxrate);
1209
1210                 rate = bound(NET_MINRATE, client->rate, maxrate);
1211                 rate = (int)(client->rate * sys_ticrate.value);
1212                 maxsize = bound(100, rate, 1400);
1213                 maxsize2 = 1400;
1214         }
1215
1216         msg.data = sv_sendclientdatagram_buf;
1217         msg.maxsize = maxsize;
1218         msg.cursize = 0;
1219
1220         MSG_WriteByte (&msg, svc_time);
1221         MSG_WriteFloat (&msg, sv.time);
1222
1223         // add the client specific data to the datagram
1224         SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
1225         VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
1226         SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
1227
1228         // expand packet size to allow effects to go over the rate limit
1229         // (dropping them is FAR too ugly)
1230         msg.maxsize = maxsize2;
1231
1232         // copy the server datagram if there is space
1233         // FIXME: put in delayed queue of effects to send
1234         if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
1235                 SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
1236
1237 // send the datagram
1238         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1239         {
1240                 SV_DropClient (true);// if the message couldn't send, kick off
1241                 return false;
1242         }
1243
1244         return true;
1245 }
1246
1247 /*
1248 =======================
1249 SV_UpdateToReliableMessages
1250 =======================
1251 */
1252 void SV_UpdateToReliableMessages (void)
1253 {
1254         int i, j;
1255         client_t *client;
1256         prvm_eval_t *val;
1257         const char *name;
1258         const char *model;
1259         const char *skin;
1260
1261 // check for changes to be sent over the reliable streams
1262         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1263         {
1264                 // update the host_client fields we care about according to the entity fields
1265                 host_client->edict = PRVM_EDICT_NUM(i+1);
1266
1267                 // DP_SV_CLIENTNAME
1268                 name = PRVM_GetString(host_client->edict->fields.server->netname);
1269                 if (name == NULL)
1270                         name = "";
1271                 // always point the string back at host_client->name to keep it safe
1272                 strlcpy (host_client->name, name, sizeof (host_client->name));
1273                 host_client->edict->fields.server->netname = PRVM_SetEngineString(host_client->name);
1274                 if (strcmp(host_client->old_name, host_client->name))
1275                 {
1276                         if (host_client->spawned)
1277                                 SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
1278                         strcpy(host_client->old_name, host_client->name);
1279                         // send notification to all clients
1280                         MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
1281                         MSG_WriteByte (&sv.reliable_datagram, i);
1282                         MSG_WriteString (&sv.reliable_datagram, host_client->name);
1283                 }
1284
1285                 // DP_SV_CLIENTCOLORS
1286                 // this is always found (since it's added by the progs loader)
1287                 if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors)))
1288                         host_client->colors = (int)val->_float;
1289                 if (host_client->old_colors != host_client->colors)
1290                 {
1291                         host_client->old_colors = host_client->colors;
1292                         // send notification to all clients
1293                         MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
1294                         MSG_WriteByte (&sv.reliable_datagram, i);
1295                         MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
1296                 }
1297
1298                 // NEXUIZ_PLAYERMODEL
1299                 if( eval_playermodel ) {
1300                         model = PRVM_GetString(PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string);
1301                         if (model == NULL)
1302                                 model = "";
1303                         // always point the string back at host_client->name to keep it safe
1304                         strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
1305                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(host_client->playermodel);
1306                 }
1307
1308                 // NEXUIZ_PLAYERSKIN
1309                 if( eval_playerskin ) {
1310                         skin = PRVM_GetString(PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string);
1311                         if (skin == NULL)
1312                                 skin = "";
1313                         // always point the string back at host_client->name to keep it safe
1314                         strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
1315                         PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PRVM_SetEngineString(host_client->playerskin);
1316                 }
1317
1318                 // frags
1319                 host_client->frags = (int)host_client->edict->fields.server->frags;
1320                 if (host_client->old_frags != host_client->frags)
1321                 {
1322                         host_client->old_frags = host_client->frags;
1323                         // send notification to all clients
1324                         MSG_WriteByte (&sv.reliable_datagram, svc_updatefrags);
1325                         MSG_WriteByte (&sv.reliable_datagram, i);
1326                         MSG_WriteShort (&sv.reliable_datagram, host_client->frags);
1327                 }
1328         }
1329
1330         for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1331                 if (client->netconnection)
1332                         SZ_Write (&client->message, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
1333
1334         SZ_Clear (&sv.reliable_datagram);
1335 }
1336
1337
1338 /*
1339 =======================
1340 SV_SendNop
1341
1342 Send a nop message without trashing or sending the accumulated client
1343 message buffer
1344 =======================
1345 */
1346 void SV_SendNop (client_t *client)
1347 {
1348         sizebuf_t       msg;
1349         unsigned char           buf[4];
1350
1351         msg.data = buf;
1352         msg.maxsize = sizeof(buf);
1353         msg.cursize = 0;
1354
1355         MSG_WriteChar (&msg, svc_nop);
1356
1357         if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
1358                 SV_DropClient (true);   // if the message couldn't send, kick off
1359         client->last_message = realtime;
1360 }
1361
1362 /*
1363 =======================
1364 SV_SendClientMessages
1365 =======================
1366 */
1367 void SV_SendClientMessages (void)
1368 {
1369         int i, prepared = false;
1370
1371 // update frags, names, etc
1372         SV_UpdateToReliableMessages();
1373
1374 // build individual updates
1375         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1376         {
1377                 if (!host_client->active)
1378                         continue;
1379                 if (!host_client->netconnection)
1380                 {
1381                         SZ_Clear(&host_client->message);
1382                         continue;
1383                 }
1384
1385                 if (host_client->message.overflowed)
1386                 {
1387                         SV_DropClient (true);   // if the message couldn't send, kick off
1388                         continue;
1389                 }
1390
1391                 if (host_client->spawned)
1392                 {
1393                         if (!prepared)
1394                         {
1395                                 prepared = true;
1396                                 // only prepare entities once per frame
1397                                 SV_PrepareEntitiesForSending();
1398                         }
1399                         if (!SV_SendClientDatagram (host_client))
1400                                 continue;
1401                 }
1402                 else
1403                 {
1404                 // the player isn't totally in the game yet
1405                 // send small keepalive messages if too much time has passed
1406                 // send a full message when the next signon stage has been requested
1407                 // some other message data (name changes, etc) may accumulate
1408                 // between signon stages
1409                         if (!host_client->sendsignon)
1410                         {
1411                                 if (realtime - host_client->last_message > 5)
1412                                         SV_SendNop (host_client);
1413                                 continue;       // don't send out non-signon messages
1414                         }
1415                 }
1416
1417                 if (host_client->message.cursize || host_client->dropasap)
1418                 {
1419                         if (!NetConn_CanSendMessage (host_client->netconnection))
1420                                 continue;
1421
1422                         if (host_client->dropasap)
1423                                 SV_DropClient (false);  // went to another level
1424                         else
1425                         {
1426                                 if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->message) == -1)
1427                                         SV_DropClient (true);   // if the message couldn't send, kick off
1428                                 SZ_Clear (&host_client->message);
1429                                 host_client->last_message = realtime;
1430                                 host_client->sendsignon = false;
1431                         }
1432                 }
1433         }
1434
1435 // clear muzzle flashes
1436         SV_CleanupEnts();
1437 }
1438
1439
1440 /*
1441 ==============================================================================
1442
1443 SERVER SPAWNING
1444
1445 ==============================================================================
1446 */
1447
1448 /*
1449 ================
1450 SV_ModelIndex
1451
1452 ================
1453 */
1454 int SV_ModelIndex(const char *s, int precachemode)
1455 {
1456         int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
1457         char filename[MAX_QPATH];
1458         if (!s || !*s)
1459                 return 0;
1460         // testing
1461         //if (precachemode == 2)
1462         //      return 0;
1463         strlcpy(filename, s, sizeof(filename));
1464         for (i = 2;i < limit;i++)
1465         {
1466                 if (!sv.model_precache[i][0])
1467                 {
1468                         if (precachemode)
1469                         {
1470                                 if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
1471                                 {
1472                                         Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename);
1473                                         return 0;
1474                                 }
1475                                 if (precachemode == 1)
1476                                         Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
1477                                 strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
1478                                 sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, false);
1479                                 if (sv.state != ss_loading)
1480                                 {
1481                                         MSG_WriteByte(&sv.reliable_datagram, svc_precache);
1482                                         MSG_WriteShort(&sv.reliable_datagram, i);
1483                                         MSG_WriteString(&sv.reliable_datagram, filename);
1484                                 }
1485                                 return i;
1486                         }
1487                         Con_Printf("SV_ModelIndex(\"%s\"): not precached\n", filename);
1488                         return 0;
1489                 }
1490                 if (!strcmp(sv.model_precache[i], filename))
1491                         return i;
1492         }
1493         Con_Printf("SV_ModelIndex(\"%s\"): i (%i) == MAX_MODELS (%i)\n", filename, i, MAX_MODELS);
1494         return 0;
1495 }
1496
1497 /*
1498 ================
1499 SV_SoundIndex
1500
1501 ================
1502 */
1503 int SV_SoundIndex(const char *s, int precachemode)
1504 {
1505         int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_SOUNDS);
1506         char filename[MAX_QPATH];
1507         if (!s || !*s)
1508                 return 0;
1509         // testing
1510         //if (precachemode == 2)
1511         //      return 0;
1512         strlcpy(filename, s, sizeof(filename));
1513         for (i = 1;i < limit;i++)
1514         {
1515                 if (!sv.sound_precache[i][0])
1516                 {
1517                         if (precachemode)
1518                         {
1519                                 if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
1520                                 {
1521                                         Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename);
1522                                         return 0;
1523                                 }
1524                                 if (precachemode == 1)
1525                                         Con_Printf("SV_SoundIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
1526                                 strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i]));
1527                                 if (sv.state != ss_loading)
1528                                 {
1529                                         MSG_WriteByte(&sv.reliable_datagram, svc_precache);
1530                                         MSG_WriteShort(&sv.reliable_datagram, i + 32768);
1531                                         MSG_WriteString(&sv.reliable_datagram, filename);
1532                                 }
1533                                 return i;
1534                         }
1535                         Con_Printf("SV_SoundIndex(\"%s\"): not precached\n", filename);
1536                         return 0;
1537                 }
1538                 if (!strcmp(sv.sound_precache[i], filename))
1539                         return i;
1540         }
1541         Con_Printf("SV_SoundIndex(\"%s\"): i (%i) == MAX_SOUNDS (%i)\n", filename, i, MAX_SOUNDS);
1542         return 0;
1543 }
1544
1545 /*
1546 ================
1547 SV_CreateBaseline
1548
1549 ================
1550 */
1551 void SV_CreateBaseline (void)
1552 {
1553         int i, entnum, large;
1554         prvm_edict_t *svent;
1555
1556         // LordHavoc: clear *all* states (note just active ones)
1557         for (entnum = 0;entnum < prog->max_edicts;entnum++)
1558         {
1559                 // get the current server version
1560                 svent = PRVM_EDICT_NUM(entnum);
1561
1562                 // LordHavoc: always clear state values, whether the entity is in use or not
1563                 svent->priv.server->baseline = defaultstate;
1564
1565                 if (svent->priv.server->free)
1566                         continue;
1567                 if (entnum > svs.maxclients && !svent->fields.server->modelindex)
1568                         continue;
1569
1570                 // create entity baseline
1571                 VectorCopy (svent->fields.server->origin, svent->priv.server->baseline.origin);
1572                 VectorCopy (svent->fields.server->angles, svent->priv.server->baseline.angles);
1573                 svent->priv.server->baseline.frame = svent->fields.server->frame;
1574                 svent->priv.server->baseline.skin = svent->fields.server->skin;
1575                 if (entnum > 0 && entnum <= svs.maxclients)
1576                 {
1577                         svent->priv.server->baseline.colormap = entnum;
1578                         svent->priv.server->baseline.modelindex = SV_ModelIndex("progs/player.mdl", 1);
1579                 }
1580                 else
1581                 {
1582                         svent->priv.server->baseline.colormap = 0;
1583                         svent->priv.server->baseline.modelindex = svent->fields.server->modelindex;
1584                 }
1585
1586                 large = false;
1587                 if (svent->priv.server->baseline.modelindex & 0xFF00 || svent->priv.server->baseline.frame & 0xFF00)
1588                         large = true;
1589
1590                 // add to the message
1591                 if (large)
1592                         MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
1593                 else
1594                         MSG_WriteByte (&sv.signon, svc_spawnbaseline);
1595                 MSG_WriteShort (&sv.signon, entnum);
1596
1597                 if (large)
1598                 {
1599                         MSG_WriteShort (&sv.signon, svent->priv.server->baseline.modelindex);
1600                         MSG_WriteShort (&sv.signon, svent->priv.server->baseline.frame);
1601                 }
1602                 else
1603                 {
1604                         MSG_WriteByte (&sv.signon, svent->priv.server->baseline.modelindex);
1605                         MSG_WriteByte (&sv.signon, svent->priv.server->baseline.frame);
1606                 }
1607                 MSG_WriteByte (&sv.signon, svent->priv.server->baseline.colormap);
1608                 MSG_WriteByte (&sv.signon, svent->priv.server->baseline.skin);
1609                 for (i=0 ; i<3 ; i++)
1610                 {
1611                         MSG_WriteCoord(&sv.signon, svent->priv.server->baseline.origin[i], sv.protocol);
1612                         MSG_WriteAngle(&sv.signon, svent->priv.server->baseline.angles[i], sv.protocol);
1613                 }
1614         }
1615 }
1616
1617
1618 /*
1619 ================
1620 SV_SendReconnect
1621
1622 Tell all the clients that the server is changing levels
1623 ================
1624 */
1625 void SV_SendReconnect (void)
1626 {
1627 #if 1
1628         MSG_WriteByte(&sv.reliable_datagram, svc_stufftext);
1629         MSG_WriteString(&sv.reliable_datagram, "reconnect\n");
1630 #else
1631         unsigned char data[128];
1632         sizebuf_t msg;
1633
1634         msg.data = data;
1635         msg.cursize = 0;
1636         msg.maxsize = sizeof(data);
1637
1638         MSG_WriteChar (&msg, svc_stufftext);
1639         MSG_WriteString (&msg, "reconnect\n");
1640         NetConn_SendToAll (&msg, 5);
1641
1642         if (cls.state != ca_dedicated)
1643                 Cmd_ExecuteString ("reconnect\n", src_command);
1644 #endif
1645 }
1646
1647
1648 /*
1649 ================
1650 SV_SaveSpawnparms
1651
1652 Grabs the current state of each client for saving across the
1653 transition to another level
1654 ================
1655 */
1656 void SV_SaveSpawnparms (void)
1657 {
1658         int             i, j;
1659
1660         svs.serverflags = prog->globals.server->serverflags;
1661
1662         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1663         {
1664                 if (!host_client->active)
1665                         continue;
1666
1667         // call the progs to get default spawn parms for the new client
1668                 prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
1669                 PRVM_ExecuteProgram (prog->globals.server->SetChangeParms, "QC function SetChangeParms is missing");
1670                 for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
1671                         host_client->spawn_parms[j] = (&prog->globals.server->parm1)[j];
1672         }
1673 }
1674 /*
1675 void SV_IncreaseEdicts(void)
1676 {
1677         int i;
1678         prvm_edict_t *ent;
1679         int oldmax_edicts = prog->max_edicts;
1680         void *oldedictsengineprivate = prog->edictprivate;
1681         void *oldedictsfields = prog->edictsfields;
1682         void *oldmoved_edicts = sv.moved_edicts;
1683
1684         if (prog->max_edicts >= MAX_EDICTS)
1685                 return;
1686
1687         // links don't survive the transition, so unlink everything
1688         for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
1689         {
1690                 if (!ent->priv.server->free)
1691                         SV_UnlinkEdict(prog->edicts + i);
1692                 memset(&ent->priv.server->areagrid, 0, sizeof(ent->priv.server->areagrid));
1693         }
1694         SV_ClearWorld();
1695
1696         prog->max_edicts   = min(prog->max_edicts + 256, MAX_EDICTS);
1697         prog->edictprivate = PR_Alloc(prog->max_edicts * sizeof(edict_engineprivate_t));
1698         prog->edictsfields = PR_Alloc(prog->max_edicts * prog->edict_size);
1699         sv.moved_edicts = PR_Alloc(prog->max_edicts * sizeof(prvm_edict_t *));
1700
1701         memcpy(prog->edictprivate, oldedictsengineprivate, oldmax_edicts * sizeof(edict_engineprivate_t));
1702         memcpy(prog->edictsfields, oldedictsfields, oldmax_edicts * prog->edict_size);
1703
1704         for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
1705         {
1706                 ent->priv.vp = (unsigned char*) prog->edictprivate + i * prog->edictprivate_size;
1707                 ent->fields.server = (void *)((unsigned char *)prog->edictsfields + i * prog->edict_size);
1708                 // link every entity except world
1709                 if (!ent->priv.server->free)
1710                         SV_LinkEdict(ent, false);
1711         }
1712
1713         PR_Free(oldedictsengineprivate);
1714         PR_Free(oldedictsfields);
1715         PR_Free(oldmoved_edicts);
1716 }*/
1717
1718 /*
1719 ================
1720 SV_SpawnServer
1721
1722 This is called at the start of each level
1723 ================
1724 */
1725 extern float            scr_centertime_off;
1726
1727 void SV_SpawnServer (const char *server)
1728 {
1729         prvm_edict_t *ent;
1730         int i;
1731         char *entities;
1732         model_t *worldmodel;
1733         char modelname[sizeof(sv.modelname)];
1734
1735         Con_DPrintf("SpawnServer: %s\n", server);
1736
1737         if (cls.state != ca_dedicated)
1738                 SCR_BeginLoadingPlaque();
1739
1740         dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", server);
1741         worldmodel = Mod_ForName(modelname, false, true, true);
1742         if (!worldmodel || !worldmodel->TraceBox)
1743         {
1744                 Con_Printf("Couldn't load map %s\n", modelname);
1745                 return;
1746         }
1747
1748         // let's not have any servers with no name
1749         if (hostname.string[0] == 0)
1750                 Cvar_Set ("hostname", "UNNAMED");
1751         scr_centertime_off = 0;
1752
1753         svs.changelevel_issued = false;         // now safe to issue another
1754
1755 //
1756 // tell all connected clients that we are going to a new level
1757 //
1758         if (sv.active)
1759         {
1760                 SV_VM_Begin();
1761                 SV_SendReconnect();
1762                 SV_VM_End();
1763         }
1764         else
1765         {
1766                 // open server port
1767                 NetConn_OpenServerPorts(true);
1768         }
1769
1770 //
1771 // make cvars consistant
1772 //
1773         if (coop.integer)
1774                 Cvar_SetValue ("deathmatch", 0);
1775         // LordHavoc: it can be useful to have skills outside the range 0-3...
1776         //current_skill = bound(0, (int)(skill.value + 0.5), 3);
1777         //Cvar_SetValue ("skill", (float)current_skill);
1778         current_skill = (int)(skill.value + 0.5);
1779
1780 //
1781 // set up the new server
1782 //
1783         Host_ClearMemory ();
1784
1785         memset (&sv, 0, sizeof(sv));
1786
1787         SV_VM_Setup();
1788
1789         sv.active = true;
1790
1791         strlcpy (sv.name, server, sizeof (sv.name));
1792
1793         sv.protocol = Protocol_EnumForName(sv_protocolname.string);
1794         if (sv.protocol == PROTOCOL_UNKNOWN)
1795         {
1796                 char buffer[1024];
1797                 Protocol_Names(buffer, sizeof(buffer));
1798                 Con_Printf("Unknown sv_protocolname \"%s\", valid values are:\n%s\n", sv_protocolname.string, buffer);
1799                 sv.protocol = PROTOCOL_QUAKE;
1800         }
1801
1802         SV_VM_Begin();
1803
1804 // load progs to get entity field count
1805         //PR_LoadProgs ( sv_progs.string );
1806
1807         // allocate server memory
1808         /*// start out with just enough room for clients and a reasonable estimate of entities
1809         prog->max_edicts = max(svs.maxclients + 1, 512);
1810         prog->max_edicts = min(prog->max_edicts, MAX_EDICTS);
1811
1812         // prvm_edict_t structures (hidden from progs)
1813         prog->edicts = PR_Alloc(MAX_EDICTS * sizeof(prvm_edict_t));
1814         // engine private structures (hidden from progs)
1815         prog->edictprivate = PR_Alloc(prog->max_edicts * sizeof(edict_engineprivate_t));
1816         // progs fields, often accessed by server
1817         prog->edictsfields = PR_Alloc(prog->max_edicts * prog->edict_size);*/
1818         // used by PushMove to move back pushed entities
1819         sv.moved_edicts = (prvm_edict_t **)PRVM_Alloc(prog->max_edicts * sizeof(prvm_edict_t *));
1820         /*for (i = 0;i < prog->max_edicts;i++)
1821         {
1822                 ent = prog->edicts + i;
1823                 ent->priv.vp = (unsigned char*) prog->edictprivate + i * prog->edictprivate_size;
1824                 ent->fields.server = (void *)((unsigned char *)prog->edictsfields + i * prog->edict_size);
1825         }*/
1826
1827         // reset client csqc entity versions right away.
1828         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1829                 EntityFrameCSQC_InitClientVersions(i, true);
1830
1831         sv.datagram.maxsize = sizeof(sv.datagram_buf);
1832         sv.datagram.cursize = 0;
1833         sv.datagram.data = sv.datagram_buf;
1834
1835         sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
1836         sv.reliable_datagram.cursize = 0;
1837         sv.reliable_datagram.data = sv.reliable_datagram_buf;
1838
1839         sv.signon.maxsize = sizeof(sv.signon_buf);
1840         sv.signon.cursize = 0;
1841         sv.signon.data = sv.signon_buf;
1842
1843 // leave slots at start for clients only
1844         //prog->num_edicts = svs.maxclients+1;
1845
1846         sv.state = ss_loading;
1847         prog->allowworldwrites = true;
1848         sv.paused = false;
1849
1850         *prog->time = sv.time = 1.0;
1851
1852         Mod_ClearUsed();
1853         worldmodel->used = true;
1854
1855         strlcpy (sv.name, server, sizeof (sv.name));
1856         strcpy(sv.modelname, modelname);
1857         sv.worldmodel = worldmodel;
1858         sv.models[1] = sv.worldmodel;
1859
1860 //
1861 // clear world interaction links
1862 //
1863         SV_ClearWorld ();
1864
1865         strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0]));
1866
1867         strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0]));
1868         strlcpy(sv.model_precache[1], sv.modelname, sizeof(sv.model_precache[1]));
1869         for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
1870         {
1871                 dpsnprintf(sv.model_precache[i+1], sizeof(sv.model_precache[i+1]), "*%i", i);
1872                 sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, false);
1873         }
1874
1875 //
1876 // load the rest of the entities
1877 //
1878         // AK possible hack since num_edicts is still 0
1879         ent = PRVM_EDICT_NUM(0);
1880         memset (ent->fields.server, 0, prog->progs->entityfields * 4);
1881         ent->priv.server->free = false;
1882         ent->fields.server->model = PRVM_SetEngineString(sv.modelname);
1883         ent->fields.server->modelindex = 1;             // world model
1884         ent->fields.server->solid = SOLID_BSP;
1885         ent->fields.server->movetype = MOVETYPE_PUSH;
1886
1887         if (coop.value)
1888                 prog->globals.server->coop = coop.integer;
1889         else
1890                 prog->globals.server->deathmatch = deathmatch.integer;
1891
1892         prog->globals.server->mapname = PRVM_SetEngineString(sv.name);
1893
1894 // serverflags are for cross level information (sigils)
1895         prog->globals.server->serverflags = svs.serverflags;
1896
1897         // we need to reset the spawned flag on all connected clients here so that
1898         // their thinks don't run during startup (before PutClientInServer)
1899         // we also need to set up the client entities now
1900         // and we need to set the ->edict pointers to point into the progs edicts
1901         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1902         {
1903                 host_client->spawned = false;
1904                 host_client->edict = PRVM_EDICT_NUM(i + 1);
1905                 PRVM_ED_ClearEdict(host_client->edict);
1906         }
1907
1908         // load replacement entity file if found
1909         entities = NULL;
1910         if (sv_entpatch.integer)
1911                 entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true, NULL);
1912         if (entities)
1913         {
1914                 Con_Printf("Loaded maps/%s.ent\n", sv.name);
1915                 PRVM_ED_LoadFromFile (entities);
1916                 Mem_Free(entities);
1917         }
1918         else
1919                 PRVM_ED_LoadFromFile (sv.worldmodel->brush.entities);
1920
1921
1922         // LordHavoc: clear world angles (to fix e3m3.bsp)
1923         VectorClear(prog->edicts->fields.server->angles);
1924
1925 // all setup is completed, any further precache statements are errors
1926         sv.state = ss_active;
1927         prog->allowworldwrites = false;
1928
1929 // run two frames to allow everything to settle
1930         for (i = 0;i < 2;i++)
1931         {
1932                 sv.frametime = host_frametime = 0.1;
1933                 SV_Physics ();
1934         }
1935
1936         Mod_PurgeUnused();
1937
1938 // create a baseline for more efficient communications
1939         if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
1940                 SV_CreateBaseline ();
1941
1942 // send serverinfo to all connected clients, and set up botclients coming back from a level change
1943         for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1944         {
1945                 if (!host_client->active)
1946                         continue;
1947                 if (host_client->netconnection)
1948                         SV_SendServerinfo(host_client);
1949                 else
1950                 {
1951                         int j;
1952                         // if client is a botclient coming from a level change, we need to
1953                         // set up client info that normally requires networking
1954
1955                         // copy spawn parms out of the client_t
1956                         for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
1957                                 (&prog->globals.server->parm1)[j] = host_client->spawn_parms[j];
1958
1959                         // call the spawn function
1960                         host_client->clientconnectcalled = true;
1961                         prog->globals.server->time = sv.time;
1962                         prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
1963                         PRVM_ExecuteProgram (prog->globals.server->ClientConnect, "QC function ClientConnect is missing");
1964                         PRVM_ExecuteProgram (prog->globals.server->PutClientInServer, "QC function PutClientInServer is missing");
1965                         host_client->spawned = true;
1966                 }
1967         }
1968
1969         Con_DPrint("Server spawned.\n");
1970         NetConn_Heartbeat (2);
1971
1972         SV_VM_End();
1973 }
1974
1975 /////////////////////////////////////////////////////
1976 // SV VM stuff
1977
1978 void SV_VM_CB_BeginIncreaseEdicts(void)
1979 {
1980         int i;
1981         prvm_edict_t *ent;
1982
1983         PRVM_Free( sv.moved_edicts );
1984         sv.moved_edicts = (prvm_edict_t **)PRVM_Alloc(prog->max_edicts * sizeof(prvm_edict_t *));
1985
1986         // links don't survive the transition, so unlink everything
1987         for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
1988         {
1989                 if (!ent->priv.server->free)
1990                         SV_UnlinkEdict(prog->edicts + i);
1991                 memset(&ent->priv.server->areagrid, 0, sizeof(ent->priv.server->areagrid));
1992         }
1993         SV_ClearWorld();
1994 }
1995
1996 void SV_VM_CB_EndIncreaseEdicts(void)
1997 {
1998         int i;
1999         prvm_edict_t *ent;
2000
2001         for (i = 0, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
2002         {
2003                 // link every entity except world
2004                 if (!ent->priv.server->free)
2005                         SV_LinkEdict(ent, false);
2006         }
2007 }
2008
2009 void SV_VM_CB_InitEdict(prvm_edict_t *e)
2010 {
2011         // LordHavoc: for consistency set these here
2012         int num = PRVM_NUM_FOR_EDICT(e) - 1;
2013
2014         if (num >= 0 && num < svs.maxclients)
2015         {
2016                 prvm_eval_t *val;
2017                 // set colormap and team on newly created player entity
2018                 e->fields.server->colormap = num + 1;
2019                 e->fields.server->team = (svs.clients[num].colors & 15) + 1;
2020                 // set netname/clientcolors back to client values so that
2021                 // DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS will not immediately
2022                 // reset them
2023                 e->fields.server->netname = PRVM_SetEngineString(svs.clients[num].name);
2024                 if ((val = PRVM_GETEDICTFIELDVALUE(e, eval_clientcolors)))
2025                         val->_float = svs.clients[num].colors;
2026                 // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
2027                 if( eval_playermodel )
2028                         PRVM_GETEDICTFIELDVALUE(e, eval_playermodel)->string = PRVM_SetEngineString(svs.clients[num].playermodel);
2029                 if( eval_playerskin )
2030                         PRVM_GETEDICTFIELDVALUE(e, eval_playerskin)->string = PRVM_SetEngineString(svs.clients[num].playerskin);
2031         }
2032 }
2033
2034 void SV_VM_CB_FreeEdict(prvm_edict_t *ed)
2035 {
2036         SV_UnlinkEdict (ed);            // unlink from world bsp
2037
2038         ed->fields.server->model = 0;
2039         ed->fields.server->takedamage = 0;
2040         ed->fields.server->modelindex = 0;
2041         ed->fields.server->colormap = 0;
2042         ed->fields.server->skin = 0;
2043         ed->fields.server->frame = 0;
2044         VectorClear(ed->fields.server->origin);
2045         VectorClear(ed->fields.server->angles);
2046         ed->fields.server->nextthink = -1;
2047         ed->fields.server->solid = 0;
2048 }
2049
2050 void SV_VM_CB_CountEdicts(void)
2051 {
2052         int             i;
2053         prvm_edict_t    *ent;
2054         int             active, models, solid, step;
2055
2056         active = models = solid = step = 0;
2057         for (i=0 ; i<prog->num_edicts ; i++)
2058         {
2059                 ent = PRVM_EDICT_NUM(i);
2060                 if (ent->priv.server->free)
2061                         continue;
2062                 active++;
2063                 if (ent->fields.server->solid)
2064                         solid++;
2065                 if (ent->fields.server->model)
2066                         models++;
2067                 if (ent->fields.server->movetype == MOVETYPE_STEP)
2068                         step++;
2069         }
2070
2071         Con_Printf("num_edicts:%3i\n", prog->num_edicts);
2072         Con_Printf("active    :%3i\n", active);
2073         Con_Printf("view      :%3i\n", models);
2074         Con_Printf("touch     :%3i\n", solid);
2075         Con_Printf("step      :%3i\n", step);
2076 }
2077
2078 qboolean SV_VM_CB_LoadEdict(prvm_edict_t *ent)
2079 {
2080         // remove things from different skill levels or deathmatch
2081         if (gamemode != GAME_TRANSFUSION) //Transfusion does this in QC
2082         {
2083                 if (deathmatch.integer)
2084                 {
2085                         if (((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
2086                         {
2087                                 return false;
2088                         }
2089                 }
2090                 else if ((current_skill <= 0 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_EASY  ))
2091                         || (current_skill == 1 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_MEDIUM))
2092                         || (current_skill >= 2 && ((int)ent->fields.server->spawnflags & SPAWNFLAG_NOT_HARD  )))
2093                 {
2094                         return false;
2095                 }
2096         }
2097         return true;
2098 }
2099
2100 cvar_t  pr_checkextension = {CVAR_READONLY, "pr_checkextension", "1"};
2101 cvar_t  nomonsters = {0, "nomonsters", "0"};
2102 cvar_t  gamecfg = {0, "gamecfg", "0"};
2103 cvar_t  scratch1 = {0, "scratch1", "0"};
2104 cvar_t  scratch2 = {0,"scratch2", "0"};
2105 cvar_t  scratch3 = {0, "scratch3", "0"};
2106 cvar_t  scratch4 = {0, "scratch4", "0"};
2107 cvar_t  savedgamecfg = {CVAR_SAVE, "savedgamecfg", "0"};
2108 cvar_t  saved1 = {CVAR_SAVE, "saved1", "0"};
2109 cvar_t  saved2 = {CVAR_SAVE, "saved2", "0"};
2110 cvar_t  saved3 = {CVAR_SAVE, "saved3", "0"};
2111 cvar_t  saved4 = {CVAR_SAVE, "saved4", "0"};
2112 cvar_t  decors = {0, "decors", "0"};
2113 cvar_t  nehx00 = {0, "nehx00", "0"};cvar_t      nehx01 = {0, "nehx01", "0"};
2114 cvar_t  nehx02 = {0, "nehx02", "0"};cvar_t      nehx03 = {0, "nehx03", "0"};
2115 cvar_t  nehx04 = {0, "nehx04", "0"};cvar_t      nehx05 = {0, "nehx05", "0"};
2116 cvar_t  nehx06 = {0, "nehx06", "0"};cvar_t      nehx07 = {0, "nehx07", "0"};
2117 cvar_t  nehx08 = {0, "nehx08", "0"};cvar_t      nehx09 = {0, "nehx09", "0"};
2118 cvar_t  nehx10 = {0, "nehx10", "0"};cvar_t      nehx11 = {0, "nehx11", "0"};
2119 cvar_t  nehx12 = {0, "nehx12", "0"};cvar_t      nehx13 = {0, "nehx13", "0"};
2120 cvar_t  nehx14 = {0, "nehx14", "0"};cvar_t      nehx15 = {0, "nehx15", "0"};
2121 cvar_t  nehx16 = {0, "nehx16", "0"};cvar_t      nehx17 = {0, "nehx17", "0"};
2122 cvar_t  nehx18 = {0, "nehx18", "0"};cvar_t      nehx19 = {0, "nehx19", "0"};
2123 cvar_t  cutscene = {0, "cutscene", "1"};
2124
2125 void SV_VM_Init(void)
2126 {
2127         Cvar_RegisterVariable (&pr_checkextension);
2128         Cvar_RegisterVariable (&nomonsters);
2129         Cvar_RegisterVariable (&gamecfg);
2130         Cvar_RegisterVariable (&scratch1);
2131         Cvar_RegisterVariable (&scratch2);
2132         Cvar_RegisterVariable (&scratch3);
2133         Cvar_RegisterVariable (&scratch4);
2134         Cvar_RegisterVariable (&savedgamecfg);
2135         Cvar_RegisterVariable (&saved1);
2136         Cvar_RegisterVariable (&saved2);
2137         Cvar_RegisterVariable (&saved3);
2138         Cvar_RegisterVariable (&saved4);
2139         // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
2140         Cvar_RegisterVariable (&decors);
2141         // LordHavoc: Nehahra uses these to pass data around cutscene demos
2142         if (gamemode == GAME_NEHAHRA)
2143         {
2144                 Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
2145                 Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
2146                 Cvar_RegisterVariable (&nehx04);Cvar_RegisterVariable (&nehx05);
2147                 Cvar_RegisterVariable (&nehx06);Cvar_RegisterVariable (&nehx07);
2148                 Cvar_RegisterVariable (&nehx08);Cvar_RegisterVariable (&nehx09);
2149                 Cvar_RegisterVariable (&nehx10);Cvar_RegisterVariable (&nehx11);
2150                 Cvar_RegisterVariable (&nehx12);Cvar_RegisterVariable (&nehx13);
2151                 Cvar_RegisterVariable (&nehx14);Cvar_RegisterVariable (&nehx15);
2152                 Cvar_RegisterVariable (&nehx16);Cvar_RegisterVariable (&nehx17);
2153                 Cvar_RegisterVariable (&nehx18);Cvar_RegisterVariable (&nehx19);
2154         }
2155         Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
2156 }
2157
2158 // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue...  these are defined as externs in progs.h
2159 int eval_gravity;
2160 int eval_button3;
2161 int eval_button4;
2162 int eval_button5;
2163 int eval_button6;
2164 int eval_button7;
2165 int eval_button8;
2166 int eval_button9;
2167 int eval_button10;
2168 int eval_button11;
2169 int eval_button12;
2170 int eval_button13;
2171 int eval_button14;
2172 int eval_button15;
2173 int eval_button16;
2174 int eval_buttonuse;
2175 int eval_buttonchat;
2176 int eval_glow_size;
2177 int eval_glow_trail;
2178 int eval_glow_color;
2179 int eval_items2;
2180 int eval_scale;
2181 int eval_alpha;
2182 int eval_renderamt; // HalfLife support
2183 int eval_rendermode; // HalfLife support
2184 int eval_fullbright;
2185 int eval_ammo_shells1;
2186 int eval_ammo_nails1;
2187 int eval_ammo_lava_nails;
2188 int eval_ammo_rockets1;
2189 int eval_ammo_multi_rockets;
2190 int eval_ammo_cells1;
2191 int eval_ammo_plasma;
2192 int eval_idealpitch;
2193 int eval_pitch_speed;
2194 int eval_viewmodelforclient;
2195 int eval_nodrawtoclient;
2196 int eval_exteriormodeltoclient;
2197 int eval_drawonlytoclient;
2198 int eval_ping;
2199 int eval_movement;
2200 int eval_pmodel;
2201 int eval_punchvector;
2202 int eval_viewzoom;
2203 int eval_clientcolors;
2204 int eval_tag_entity;
2205 int eval_tag_index;
2206 int eval_light_lev;
2207 int eval_color;
2208 int eval_style;
2209 int eval_pflags;
2210 int eval_cursor_active;
2211 int eval_cursor_screen;
2212 int eval_cursor_trace_start;
2213 int eval_cursor_trace_endpos;
2214 int eval_cursor_trace_ent;
2215 int eval_colormod;
2216 int eval_playermodel;
2217 int eval_playerskin;
2218 int eval_SendEntity;
2219 int eval_Version;
2220 int eval_customizeentityforclient;
2221
2222 mfunction_t *SV_PlayerPhysicsQC;
2223 mfunction_t *EndFrameQC;
2224 //KrimZon - SERVER COMMANDS IN QUAKEC
2225 mfunction_t *SV_ParseClientCommandQC;
2226
2227 ddef_t *PRVM_ED_FindGlobal(const char *name);
2228
2229 void SV_VM_FindEdictFieldOffsets(void)
2230 {
2231         eval_gravity = PRVM_ED_FindFieldOffset("gravity");
2232         eval_button3 = PRVM_ED_FindFieldOffset("button3");
2233         eval_button4 = PRVM_ED_FindFieldOffset("button4");
2234         eval_button5 = PRVM_ED_FindFieldOffset("button5");
2235         eval_button6 = PRVM_ED_FindFieldOffset("button6");
2236         eval_button7 = PRVM_ED_FindFieldOffset("button7");
2237         eval_button8 = PRVM_ED_FindFieldOffset("button8");
2238         eval_button9 = PRVM_ED_FindFieldOffset("button9");
2239         eval_button10 = PRVM_ED_FindFieldOffset("button10");
2240         eval_button11 = PRVM_ED_FindFieldOffset("button11");
2241         eval_button12 = PRVM_ED_FindFieldOffset("button12");
2242         eval_button13 = PRVM_ED_FindFieldOffset("button13");
2243         eval_button14 = PRVM_ED_FindFieldOffset("button14");
2244         eval_button15 = PRVM_ED_FindFieldOffset("button15");
2245         eval_button16 = PRVM_ED_FindFieldOffset("button16");
2246         eval_buttonuse = PRVM_ED_FindFieldOffset("buttonuse");
2247         eval_buttonchat = PRVM_ED_FindFieldOffset("buttonchat");
2248         eval_glow_size = PRVM_ED_FindFieldOffset("glow_size");
2249         eval_glow_trail = PRVM_ED_FindFieldOffset("glow_trail");
2250         eval_glow_color = PRVM_ED_FindFieldOffset("glow_color");
2251         eval_items2 = PRVM_ED_FindFieldOffset("items2");
2252         eval_scale = PRVM_ED_FindFieldOffset("scale");
2253         eval_alpha = PRVM_ED_FindFieldOffset("alpha");
2254         eval_renderamt = PRVM_ED_FindFieldOffset("renderamt"); // HalfLife support
2255         eval_rendermode = PRVM_ED_FindFieldOffset("rendermode"); // HalfLife support
2256         eval_fullbright = PRVM_ED_FindFieldOffset("fullbright");
2257         eval_ammo_shells1 = PRVM_ED_FindFieldOffset("ammo_shells1");
2258         eval_ammo_nails1 = PRVM_ED_FindFieldOffset("ammo_nails1");
2259         eval_ammo_lava_nails = PRVM_ED_FindFieldOffset("ammo_lava_nails");
2260         eval_ammo_rockets1 = PRVM_ED_FindFieldOffset("ammo_rockets1");
2261         eval_ammo_multi_rockets = PRVM_ED_FindFieldOffset("ammo_multi_rockets");
2262         eval_ammo_cells1 = PRVM_ED_FindFieldOffset("ammo_cells1");
2263         eval_ammo_plasma = PRVM_ED_FindFieldOffset("ammo_plasma");
2264         eval_idealpitch = PRVM_ED_FindFieldOffset("idealpitch");
2265         eval_pitch_speed = PRVM_ED_FindFieldOffset("pitch_speed");
2266         eval_viewmodelforclient = PRVM_ED_FindFieldOffset("viewmodelforclient");
2267         eval_nodrawtoclient = PRVM_ED_FindFieldOffset("nodrawtoclient");
2268         eval_exteriormodeltoclient = PRVM_ED_FindFieldOffset("exteriormodeltoclient");
2269         eval_drawonlytoclient = PRVM_ED_FindFieldOffset("drawonlytoclient");
2270         eval_ping = PRVM_ED_FindFieldOffset("ping");
2271         eval_movement = PRVM_ED_FindFieldOffset("movement");
2272         eval_pmodel = PRVM_ED_FindFieldOffset("pmodel");
2273         eval_punchvector = PRVM_ED_FindFieldOffset("punchvector");
2274         eval_viewzoom = PRVM_ED_FindFieldOffset("viewzoom");
2275         eval_clientcolors = PRVM_ED_FindFieldOffset("clientcolors");
2276         eval_tag_entity = PRVM_ED_FindFieldOffset("tag_entity");
2277         eval_tag_index = PRVM_ED_FindFieldOffset("tag_index");
2278         eval_light_lev = PRVM_ED_FindFieldOffset("light_lev");
2279         eval_color = PRVM_ED_FindFieldOffset("color");
2280         eval_style = PRVM_ED_FindFieldOffset("style");
2281         eval_pflags = PRVM_ED_FindFieldOffset("pflags");
2282         eval_cursor_active = PRVM_ED_FindFieldOffset("cursor_active");
2283         eval_cursor_screen = PRVM_ED_FindFieldOffset("cursor_screen");
2284         eval_cursor_trace_start = PRVM_ED_FindFieldOffset("cursor_trace_start");
2285         eval_cursor_trace_endpos = PRVM_ED_FindFieldOffset("cursor_trace_endpos");
2286         eval_cursor_trace_ent = PRVM_ED_FindFieldOffset("cursor_trace_ent");
2287         eval_colormod = PRVM_ED_FindFieldOffset("colormod");
2288         eval_playermodel = PRVM_ED_FindFieldOffset("playermodel");
2289         eval_playerskin = PRVM_ED_FindFieldOffset("playerskin");
2290         eval_SendEntity = PRVM_ED_FindFieldOffset("SendEntity");
2291         eval_Version = PRVM_ED_FindFieldOffset("Version");
2292         eval_customizeentityforclient = PRVM_ED_FindFieldOffset("customizeentityforclient");
2293
2294         // LordHavoc: allowing QuakeC to override the player movement code
2295         SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
2296         // LordHavoc: support for endframe
2297         EndFrameQC = PRVM_ED_FindFunction ("EndFrame");
2298         //KrimZon - SERVER COMMANDS IN QUAKEC
2299         SV_ParseClientCommandQC = PRVM_ED_FindFunction ("SV_ParseClientCommand");
2300
2301         //[515]: init stufftext string (it is sent before svc_serverinfo)
2302         if(PRVM_ED_FindGlobal("SV_InitCmd") && PRVM_ED_FindGlobal("SV_InitCmd")->type & ev_string)
2303                 SV_InitCmd = PRVM_G_STRING(PRVM_ED_FindGlobal("SV_InitCmd")->ofs);
2304         else
2305                 SV_InitCmd = NULL;
2306 }
2307
2308 #define REQFIELDS (sizeof(reqfields) / sizeof(prvm_required_field_t))
2309
2310 prvm_required_field_t reqfields[] =
2311 {
2312         {ev_entity, "cursor_trace_ent"},
2313         {ev_entity, "drawonlytoclient"},
2314         {ev_entity, "exteriormodeltoclient"},
2315         {ev_entity, "nodrawtoclient"},
2316         {ev_entity, "tag_entity"},
2317         {ev_entity, "viewmodelforclient"},
2318         {ev_float, "alpha"},
2319         {ev_float, "ammo_cells1"},
2320         {ev_float, "ammo_lava_nails"},
2321         {ev_float, "ammo_multi_rockets"},
2322         {ev_float, "ammo_nails1"},
2323         {ev_float, "ammo_plasma"},
2324         {ev_float, "ammo_rockets1"},
2325         {ev_float, "ammo_shells1"},
2326         {ev_float, "button3"},
2327         {ev_float, "button4"},
2328         {ev_float, "button5"},
2329         {ev_float, "button6"},
2330         {ev_float, "button7"},
2331         {ev_float, "button8"},
2332         {ev_float, "button9"},
2333         {ev_float, "button10"},
2334         {ev_float, "button11"},
2335         {ev_float, "button12"},
2336         {ev_float, "button13"},
2337         {ev_float, "button14"},
2338         {ev_float, "button15"},
2339         {ev_float, "button16"},
2340         {ev_float, "buttonchat"},
2341         {ev_float, "buttonuse"},
2342         {ev_float, "clientcolors"},
2343         {ev_float, "cursor_active"},
2344         {ev_float, "fullbright"},
2345         {ev_float, "glow_color"},
2346         {ev_float, "glow_size"},
2347         {ev_float, "glow_trail"},
2348         {ev_float, "gravity"},
2349         {ev_float, "idealpitch"},
2350         {ev_float, "items2"},
2351         {ev_float, "light_lev"},
2352         {ev_float, "pflags"},
2353         {ev_float, "ping"},
2354         {ev_float, "pitch_speed"},
2355         {ev_float, "pmodel"},
2356         {ev_float, "renderamt"}, // HalfLife support
2357         {ev_float, "rendermode"}, // HalfLife support
2358         {ev_float, "scale"},
2359         {ev_float, "style"},
2360         {ev_float, "tag_index"},
2361         {ev_float, "Version"},
2362         {ev_float, "viewzoom"},
2363         {ev_vector, "color"},
2364         {ev_vector, "colormod"},
2365         {ev_vector, "cursor_screen"},
2366         {ev_vector, "cursor_trace_endpos"},
2367         {ev_vector, "cursor_trace_start"},
2368         {ev_vector, "movement"},
2369         {ev_vector, "punchvector"},
2370         {ev_string, "playermodel"},
2371         {ev_string, "playerskin"},
2372         {ev_function, "SendEntity"},
2373         {ev_function, "customizeentityforclient"},
2374 };
2375
2376 void SV_VM_Setup(void)
2377 {
2378         PRVM_Begin;
2379         PRVM_InitProg( PRVM_SERVERPROG );
2380
2381         // allocate the mempools
2382         prog->progs_mempool = Mem_AllocPool("Server Progs", 0, NULL);
2383         prog->builtins = vm_sv_builtins;
2384         prog->numbuiltins = vm_sv_numbuiltins;
2385         prog->headercrc = PROGHEADER_CRC;
2386         prog->max_edicts = 512;
2387         prog->limit_edicts = MAX_EDICTS;
2388         prog->reserved_edicts = svs.maxclients;
2389         prog->edictprivate_size = sizeof(edict_engineprivate_t);
2390         prog->name = "server";
2391         prog->extensionstring = vm_sv_extensions;
2392         prog->loadintoworld = true;
2393
2394         prog->begin_increase_edicts = SV_VM_CB_BeginIncreaseEdicts;
2395         prog->end_increase_edicts = SV_VM_CB_EndIncreaseEdicts;
2396         prog->init_edict = SV_VM_CB_InitEdict;
2397         prog->free_edict = SV_VM_CB_FreeEdict;
2398         prog->count_edicts = SV_VM_CB_CountEdicts;
2399         prog->load_edict = SV_VM_CB_LoadEdict;
2400         prog->init_cmd = VM_SV_Cmd_Init;
2401         prog->reset_cmd = VM_SV_Cmd_Reset;
2402         prog->error_cmd = Host_Error;
2403
2404         // TODO: add a requiredfuncs list (ask LH if this is necessary at all)
2405         PRVM_LoadProgs( sv_progs.string, 0, NULL, REQFIELDS, reqfields );
2406         SV_VM_FindEdictFieldOffsets();
2407
2408         VM_AutoSentStats_Clear();//[515]: csqc
2409         EntityFrameCSQC_ClearVersions();//[515]: csqc
2410
2411         PRVM_End;
2412 }
2413
2414 void SV_VM_Begin(void)
2415 {
2416         PRVM_Begin;
2417         PRVM_SetProg( PRVM_SERVERPROG );
2418
2419         *prog->time = (float) sv.time;
2420 }
2421
2422 void SV_VM_End(void)
2423 {
2424         PRVM_End;
2425 }