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