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