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