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