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