• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_user.c -- server code for moving users
21 
22 #include "qwsvdef.h"
23 
24 edict_t	*sv_player;
25 
26 usercmd_t	cmd;
27 
28 cvar_t	cl_rollspeed = {"cl_rollspeed", "200"};
29 cvar_t	cl_rollangle = {"cl_rollangle", "2.0"};
30 cvar_t	sv_spectalk = {"sv_spectalk", "1"};
31 
32 cvar_t	sv_mapcheck	= {"sv_mapcheck", "1"};
33 
34 extern	vec3_t	player_mins;
35 
36 extern int fp_messages, fp_persecond, fp_secondsdead;
37 extern char fp_msg[];
38 extern cvar_t pausable;
39 
40 /*
41 ============================================================
42 
43 USER STRINGCMD EXECUTION
44 
45 host_client and sv_player will be valid.
46 ============================================================
47 */
48 
49 /*
50 ================
51 SV_New_f
52 
53 Sends the first message from the server to a connected client.
54 This will be sent on the initial connection and upon each server load.
55 ================
56 */
SV_New_f(void)57 void SV_New_f (void)
58 {
59 	char		*gamedir;
60 	int			playernum;
61 
62 	if (host_client->state == cs_spawned)
63 		return;
64 
65 	host_client->state = cs_connected;
66 	host_client->connection_started = realtime;
67 
68 	// send the info about the new client to all connected clients
69 //	SV_FullClientUpdate (host_client, &sv.reliable_datagram);
70 //	host_client->sendinfo = true;
71 
72 	gamedir = Info_ValueForKey (svs.info, "*gamedir");
73 	if (!gamedir[0])
74 		gamedir = "qw";
75 
76 //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
77 //spawns.  These functions are written to not overflow
78 	if (host_client->num_backbuf) {
79 		Con_Printf("WARNING %s: [SV_New] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize);
80 		host_client->num_backbuf = 0;
81 		SZ_Clear(&host_client->netchan.message);
82 	}
83 
84 	// send the serverdata
85 	MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
86 	MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION);
87 	MSG_WriteLong (&host_client->netchan.message, svs.spawncount);
88 	MSG_WriteString (&host_client->netchan.message, gamedir);
89 
90 	playernum = NUM_FOR_EDICT(host_client->edict)-1;
91 	if (host_client->spectator)
92 		playernum |= 128;
93 	MSG_WriteByte (&host_client->netchan.message, playernum);
94 
95 	// send full levelname
96 	MSG_WriteString (&host_client->netchan.message, PR_GetString(sv.edicts->v.message));
97 
98 	// send the movevars
99 	MSG_WriteFloat(&host_client->netchan.message, movevars.gravity);
100 	MSG_WriteFloat(&host_client->netchan.message, movevars.stopspeed);
101 	MSG_WriteFloat(&host_client->netchan.message, movevars.maxspeed);
102 	MSG_WriteFloat(&host_client->netchan.message, movevars.spectatormaxspeed);
103 	MSG_WriteFloat(&host_client->netchan.message, movevars.accelerate);
104 	MSG_WriteFloat(&host_client->netchan.message, movevars.airaccelerate);
105 	MSG_WriteFloat(&host_client->netchan.message, movevars.wateraccelerate);
106 	MSG_WriteFloat(&host_client->netchan.message, movevars.friction);
107 	MSG_WriteFloat(&host_client->netchan.message, movevars.waterfriction);
108 	MSG_WriteFloat(&host_client->netchan.message, movevars.entgravity);
109 
110 	// send music
111 	MSG_WriteByte (&host_client->netchan.message, svc_cdtrack);
112 	MSG_WriteByte (&host_client->netchan.message, sv.edicts->v.sounds);
113 
114 	// send server info string
115 	MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
116 	MSG_WriteString (&host_client->netchan.message, va("fullserverinfo \"%s\"\n", svs.info) );
117 }
118 
119 /*
120 ==================
121 SV_Soundlist_f
122 ==================
123 */
SV_Soundlist_f(void)124 void SV_Soundlist_f (void)
125 {
126 	char		**s;
127 	int			n;
128 
129 	if (host_client->state != cs_connected)
130 	{
131 		Con_Printf ("soundlist not valid -- allready spawned\n");
132 		return;
133 	}
134 
135 	// handle the case of a level changing while a client was connecting
136 	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
137 	{
138 		Con_Printf ("SV_Soundlist_f from different level\n");
139 		SV_New_f ();
140 		return;
141 	}
142 
143 	n = atoi(Cmd_Argv(2));
144 
145 //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
146 //spawns.  These functions are written to not overflow
147 	if (host_client->num_backbuf) {
148 		Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize);
149 		host_client->num_backbuf = 0;
150 		SZ_Clear(&host_client->netchan.message);
151 	}
152 
153 	MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
154 	MSG_WriteByte (&host_client->netchan.message, n);
155 	for (s = sv.sound_precache+1 + n ;
156 		*s && host_client->netchan.message.cursize < (MAX_MSGLEN/2);
157 		s++, n++)
158 		MSG_WriteString (&host_client->netchan.message, *s);
159 
160 	MSG_WriteByte (&host_client->netchan.message, 0);
161 
162 	// next msg
163 	if (*s)
164 		MSG_WriteByte (&host_client->netchan.message, n);
165 	else
166 		MSG_WriteByte (&host_client->netchan.message, 0);
167 }
168 
169 /*
170 ==================
171 SV_Modellist_f
172 ==================
173 */
SV_Modellist_f(void)174 void SV_Modellist_f (void)
175 {
176 	char		**s;
177 	int			n;
178 
179 	if (host_client->state != cs_connected)
180 	{
181 		Con_Printf ("modellist not valid -- allready spawned\n");
182 		return;
183 	}
184 
185 	// handle the case of a level changing while a client was connecting
186 	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
187 	{
188 		Con_Printf ("SV_Modellist_f from different level\n");
189 		SV_New_f ();
190 		return;
191 	}
192 
193 	n = atoi(Cmd_Argv(2));
194 
195 //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
196 //spawns.  These functions are written to not overflow
197 	if (host_client->num_backbuf) {
198 		Con_Printf("WARNING %s: [SV_Modellist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize);
199 		host_client->num_backbuf = 0;
200 		SZ_Clear(&host_client->netchan.message);
201 	}
202 
203 	MSG_WriteByte (&host_client->netchan.message, svc_modellist);
204 	MSG_WriteByte (&host_client->netchan.message, n);
205 	for (s = sv.model_precache+1+n ;
206 		*s && host_client->netchan.message.cursize < (MAX_MSGLEN/2);
207 		s++, n++)
208 		MSG_WriteString (&host_client->netchan.message, *s);
209 	MSG_WriteByte (&host_client->netchan.message, 0);
210 
211 	// next msg
212 	if (*s)
213 		MSG_WriteByte (&host_client->netchan.message, n);
214 	else
215 		MSG_WriteByte (&host_client->netchan.message, 0);
216 }
217 
218 /*
219 ==================
220 SV_PreSpawn_f
221 ==================
222 */
SV_PreSpawn_f(void)223 void SV_PreSpawn_f (void)
224 {
225 	unsigned	buf;
226 	unsigned	check;
227 
228 	if (host_client->state != cs_connected)
229 	{
230 		Con_Printf ("prespawn not valid -- allready spawned\n");
231 		return;
232 	}
233 
234 	// handle the case of a level changing while a client was connecting
235 	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
236 	{
237 		Con_Printf ("SV_PreSpawn_f from different level\n");
238 		SV_New_f ();
239 		return;
240 	}
241 
242 	buf = atoi(Cmd_Argv(2));
243 	if (buf >= sv.num_signon_buffers)
244 		buf = 0;
245 
246 	if (!buf) {
247 		// should be three numbers following containing checksums
248 		check = atoi(Cmd_Argv(3));
249 
250 //		Con_DPrintf("Client check = %d\n", check);
251 
252 		if (sv_mapcheck.value && check != sv.worldmodel->checksum &&
253 			check != sv.worldmodel->checksum2) {
254 			SV_ClientPrintf (host_client, PRINT_HIGH,
255 				"Map model file does not match (%s), %i != %i/%i.\n"
256 				"You may need a new version of the map, or the proper install files.\n",
257 				sv.modelname, check, sv.worldmodel->checksum, sv.worldmodel->checksum2);
258 			SV_DropClient (host_client);
259 			return;
260 		}
261 		host_client->checksum = check;
262 	}
263 
264 //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
265 //spawns.  These functions are written to not overflow
266 	if (host_client->num_backbuf) {
267 		Con_Printf("WARNING %s: [SV_PreSpawn] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize);
268 		host_client->num_backbuf = 0;
269 		SZ_Clear(&host_client->netchan.message);
270 	}
271 
272 	SZ_Write (&host_client->netchan.message,
273 		sv.signon_buffers[buf],
274 		sv.signon_buffer_size[buf]);
275 
276 	buf++;
277 	if (buf == sv.num_signon_buffers)
278 	{	// all done prespawning
279 		MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
280 		MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i 0\n",svs.spawncount) );
281 	}
282 	else
283 	{	// need to prespawn more
284 		MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
285 		MSG_WriteString (&host_client->netchan.message,
286 			va("cmd prespawn %i %i\n", svs.spawncount, buf) );
287 	}
288 }
289 
290 /*
291 ==================
292 SV_Spawn_f
293 ==================
294 */
SV_Spawn_f(void)295 void SV_Spawn_f (void)
296 {
297 	int		i;
298 	client_t	*client;
299 	edict_t	*ent;
300 	eval_t *val;
301 	int n;
302 
303 	if (host_client->state != cs_connected)
304 	{
305 		Con_Printf ("Spawn not valid -- allready spawned\n");
306 		return;
307 	}
308 
309 // handle the case of a level changing while a client was connecting
310 	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
311 	{
312 		Con_Printf ("SV_Spawn_f from different level\n");
313 		SV_New_f ();
314 		return;
315 	}
316 
317 	n = atoi(Cmd_Argv(2));
318 
319 	// make sure n is valid
320 	if ( n < 0 || n > MAX_CLIENTS )
321 	{
322 		Con_Printf ("SV_Spawn_f invalid client start\n");
323 		SV_New_f ();
324 		return;
325 	}
326 
327 
328 
329 // send all current names, colors, and frag counts
330 	// FIXME: is this a good thing?
331 	SZ_Clear (&host_client->netchan.message);
332 
333 // send current status of all other players
334 
335 	// normally this could overflow, but no need to check due to backbuf
336 	for (i=n, client = svs.clients + n ; i<MAX_CLIENTS ; i++, client++)
337 		SV_FullClientUpdateToClient (client, host_client);
338 
339 // send all current light styles
340 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
341 	{
342 		ClientReliableWrite_Begin (host_client, svc_lightstyle,
343 			3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1));
344 		ClientReliableWrite_Byte (host_client, (char)i);
345 		ClientReliableWrite_String (host_client, sv.lightstyles[i]);
346 	}
347 
348 	// set up the edict
349 	ent = host_client->edict;
350 
351 	memset (&ent->v, 0, progs->entityfields * 4);
352 	ent->v.colormap = NUM_FOR_EDICT(ent);
353 	ent->v.team = 0;	// FIXME
354 	ent->v.netname = PR_SetString(host_client->name);
355 
356 	host_client->entgravity = 1.0;
357 	val = GetEdictFieldValue(ent, "gravity");
358 	if (val)
359 		val->_float = 1.0;
360 	host_client->maxspeed = sv_maxspeed.value;
361 	val = GetEdictFieldValue(ent, "maxspeed");
362 	if (val)
363 		val->_float = sv_maxspeed.value;
364 
365 //
366 // force stats to be updated
367 //
368 	memset (host_client->stats, 0, sizeof(host_client->stats));
369 
370 	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
371 	ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
372 	ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets);
373 
374 	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
375 	ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS);
376 	ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters);
377 
378 	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
379 	ClientReliableWrite_Byte (host_client, STAT_SECRETS);
380 	ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets);
381 
382 	ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
383 	ClientReliableWrite_Byte (host_client, STAT_MONSTERS);
384 	ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
385 
386 	// get the client to check and download skins
387 	// when that is completed, a begin command will be issued
388 	ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
389 	ClientReliableWrite_String (host_client, "skins\n" );
390 
391 }
392 
393 /*
394 ==================
395 SV_SpawnSpectator
396 ==================
397 */
SV_SpawnSpectator(void)398 void SV_SpawnSpectator (void)
399 {
400 	int		i;
401 	edict_t	*e;
402 
403 	VectorCopy (vec3_origin, sv_player->v.origin);
404 	VectorCopy (vec3_origin, sv_player->v.view_ofs);
405 	sv_player->v.view_ofs[2] = 22;
406 
407 	// search for an info_playerstart to spawn the spectator at
408 	for (i=MAX_CLIENTS-1 ; i<sv.num_edicts ; i++)
409 	{
410 		e = EDICT_NUM(i);
411 		if (!strcmp(PR_GetString(e->v.classname), "info_player_start"))
412 		{
413 			VectorCopy (e->v.origin, sv_player->v.origin);
414 			return;
415 		}
416 	}
417 
418 }
419 
420 /*
421 ==================
422 SV_Begin_f
423 ==================
424 */
SV_Begin_f(void)425 void SV_Begin_f (void)
426 {
427 	unsigned pmodel = 0, emodel = 0;
428 	int		i;
429 
430 	if (host_client->state == cs_spawned)
431 		return; // don't begin again
432 
433 	host_client->state = cs_spawned;
434 
435 	// handle the case of a level changing while a client was connecting
436 	if ( atoi(Cmd_Argv(1)) != svs.spawncount )
437 	{
438 		Con_Printf ("SV_Begin_f from different level\n");
439 		SV_New_f ();
440 		return;
441 	}
442 
443 	if (host_client->spectator)
444 	{
445 		SV_SpawnSpectator ();
446 
447 		if (SpectatorConnect) {
448 			// copy spawn parms out of the client_t
449 			for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
450 				(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
451 
452 			// call the spawn function
453 			pr_global_struct->time = sv.time;
454 			pr_global_struct->self = EDICT_TO_PROG(sv_player);
455 			PR_ExecuteProgram (SpectatorConnect);
456 		}
457 	}
458 	else
459 	{
460 		// copy spawn parms out of the client_t
461 		for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
462 			(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
463 
464 		// call the spawn function
465 		pr_global_struct->time = sv.time;
466 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
467 		PR_ExecuteProgram (pr_global_struct->ClientConnect);
468 
469 		// actually spawn the player
470 		pr_global_struct->time = sv.time;
471 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
472 		PR_ExecuteProgram (pr_global_struct->PutClientInServer);
473 	}
474 
475 	// clear the net statistics, because connecting gives a bogus picture
476 	host_client->netchan.frame_latency = 0;
477 	host_client->netchan.frame_rate = 0;
478 	host_client->netchan.drop_count = 0;
479 	host_client->netchan.good_count = 0;
480 
481 	//check he's not cheating
482 
483 	pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel"));
484 	emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel"));
485 
486 	if (pmodel != sv.model_player_checksum ||
487 		emodel != sv.eyes_player_checksum)
488 		SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name);
489 
490 	// if we are paused, tell the client
491 	if (sv.paused) {
492 		ClientReliableWrite_Begin (host_client, svc_setpause, 2);
493 		ClientReliableWrite_Byte (host_client, sv.paused);
494 		SV_ClientPrintf(host_client, PRINT_HIGH, "Server is paused.\n");
495 	}
496 
497 #if 0
498 //
499 // send a fixangle over the reliable channel to make sure it gets there
500 // Never send a roll angle, because savegames can catch the server
501 // in a state where it is expecting the client to correct the angle
502 // and it won't happen if the game was just loaded, so you wind up
503 // with a permanent head tilt
504 	ent = EDICT_NUM( 1 + (host_client - svs.clients) );
505 	MSG_WriteByte (&host_client->netchan.message, svc_setangle);
506 	for (i=0 ; i < 2 ; i++)
507 		MSG_WriteAngle (&host_client->netchan.message, ent->v.angles[i] );
508 	MSG_WriteAngle (&host_client->netchan.message, 0 );
509 #endif
510 }
511 
512 //=============================================================================
513 
514 /*
515 ==================
516 SV_NextDownload_f
517 ==================
518 */
SV_NextDownload_f(void)519 void SV_NextDownload_f (void)
520 {
521 	byte	buffer[1024];
522 	int		r;
523 	int		percent;
524 	int		size;
525 
526 	if (!host_client->download)
527 		return;
528 
529 	r = host_client->downloadsize - host_client->downloadcount;
530 	if (r > 768)
531 		r = 768;
532 	r = fread (buffer, 1, r, host_client->download);
533 	ClientReliableWrite_Begin (host_client, svc_download, 6+r);
534 	ClientReliableWrite_Short (host_client, r);
535 
536 	host_client->downloadcount += r;
537 	size = host_client->downloadsize;
538 	if (!size)
539 		size = 1;
540 	percent = host_client->downloadcount*100/size;
541 	ClientReliableWrite_Byte (host_client, percent);
542 	ClientReliableWrite_SZ (host_client, buffer, r);
543 
544 	if (host_client->downloadcount != host_client->downloadsize)
545 		return;
546 
547 	fclose (host_client->download);
548 	host_client->download = NULL;
549 
550 }
551 
OutofBandPrintf(netadr_t where,char * fmt,...)552 void OutofBandPrintf(netadr_t where, char *fmt, ...)
553 {
554 	va_list		argptr;
555 	char	send[1024];
556 
557 	send[0] = 0xff;
558 	send[1] = 0xff;
559 	send[2] = 0xff;
560 	send[3] = 0xff;
561 	send[4] = A2C_PRINT;
562 	va_start (argptr, fmt);
563 	vsprintf (send+5, fmt, argptr);
564 	va_end (argptr);
565 
566 	NET_SendPacket (strlen(send)+1, send, where);
567 }
568 
569 /*
570 ==================
571 SV_NextUpload
572 ==================
573 */
SV_NextUpload(void)574 void SV_NextUpload (void)
575 {
576 	byte	buffer[1024];
577 	int		r;
578 	int		percent;
579 	int		size;
580 	client_t *client;
581 
582 	if (!*host_client->uploadfn) {
583 		SV_ClientPrintf(host_client, PRINT_HIGH, "Upload denied\n");
584 		ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
585 		ClientReliableWrite_String (host_client, "stopul");
586 
587 		// suck out rest of packet
588 		size = MSG_ReadShort ();	MSG_ReadByte ();
589 		msg_readcount += size;
590 		return;
591 	}
592 
593 	size = MSG_ReadShort ();
594 	percent = MSG_ReadByte ();
595 
596 	if (!host_client->upload)
597 	{
598 		host_client->upload = fopen(host_client->uploadfn, "wb");
599 		if (!host_client->upload) {
600 			Sys_Printf("Can't create %s\n", host_client->uploadfn);
601 			ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
602 			ClientReliableWrite_String (host_client, "stopul");
603 			*host_client->uploadfn = 0;
604 			return;
605 		}
606 		Sys_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
607 		if (host_client->remote_snap)
608 			OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
609 	}
610 
611 	fwrite (net_message.data + msg_readcount, 1, size, host_client->upload);
612 	msg_readcount += size;
613 
614 Con_DPrintf ("UPLOAD: %d received\n", size);
615 
616 	if (percent != 100) {
617 		ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
618 		ClientReliableWrite_String (host_client, "nextul\n");
619 	} else {
620 		fclose (host_client->upload);
621 		host_client->upload = NULL;
622 
623 		Sys_Printf("%s upload completed.\n", host_client->uploadfn);
624 
625 		if (host_client->remote_snap) {
626 			char *p;
627 
628 			if ((p = strchr(host_client->uploadfn, '/')) != NULL)
629 				p++;
630 			else
631 				p = host_client->uploadfn;
632 			OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n",
633 				host_client->uploadfn, p);
634 		}
635 	}
636 
637 }
638 
639 /*
640 ==================
641 SV_BeginDownload_f
642 ==================
643 */
SV_BeginDownload_f(void)644 void SV_BeginDownload_f(void)
645 {
646 	char	*name;
647 	extern	cvar_t	allow_download;
648 	extern	cvar_t	allow_download_skins;
649 	extern	cvar_t	allow_download_models;
650 	extern	cvar_t	allow_download_sounds;
651 	extern	cvar_t	allow_download_maps;
652 	extern	int		file_from_pak; // ZOID did file come from pak?
653 
654 	name = Cmd_Argv(1);
655 // hacked by zoid to allow more conrol over download
656 		// first off, no .. or global allow check
657 	if (strstr (name, "..") || !allow_download.value
658 		// leading dot is no good
659 		|| *name == '.'
660 		// leading slash bad as well, must be in subdir
661 		|| *name == '/'
662 		// next up, skin check
663 		|| (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.value)
664 		// now models
665 		|| (strncmp(name, "progs/", 6) == 0 && !allow_download_models.value)
666 		// now sounds
667 		|| (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.value)
668 		// now maps (note special case for maps, must not be in pak)
669 		|| (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.value)
670 		// MUST be in a subdirectory
671 		|| !strstr (name, "/") )
672 	{	// don't allow anything with .. path
673 		ClientReliableWrite_Begin (host_client, svc_download, 4);
674 		ClientReliableWrite_Short (host_client, -1);
675 		ClientReliableWrite_Byte (host_client, 0);
676 		return;
677 	}
678 
679 	if (host_client->download) {
680 		fclose (host_client->download);
681 		host_client->download = NULL;
682 	}
683 
684 	// lowercase name (needed for casesen file systems)
685 	{
686 		char *p;
687 
688 		for (p = name; *p; p++)
689 			*p = (char)tolower(*p);
690 	}
691 
692 
693 	host_client->downloadsize = COM_FOpenFile (name, &host_client->download);
694 	host_client->downloadcount = 0;
695 
696 	if (!host_client->download
697 		// special check for maps, if it came from a pak file, don't allow
698 		// download  ZOID
699 		|| (strncmp(name, "maps/", 5) == 0 && file_from_pak))
700 	{
701 		if (host_client->download) {
702 			fclose(host_client->download);
703 			host_client->download = NULL;
704 		}
705 
706 		Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name);
707 		ClientReliableWrite_Begin (host_client, svc_download, 4);
708 		ClientReliableWrite_Short (host_client, -1);
709 		ClientReliableWrite_Byte (host_client, 0);
710 		return;
711 	}
712 
713 	SV_NextDownload_f ();
714 	Sys_Printf ("Downloading %s to %s\n", name, host_client->name);
715 }
716 
717 //=============================================================================
718 
719 /*
720 ==================
721 SV_Say
722 ==================
723 */
SV_Say(qboolean team)724 void SV_Say (qboolean team)
725 {
726 	client_t *client;
727 	int		j, tmp;
728 	char	*p;
729 	char	text[2048];
730 	char	t1[32], *t2;
731 
732 	if (Cmd_Argc () < 2)
733 		return;
734 
735 	if (team)
736 	{
737 		strncpy (t1, Info_ValueForKey (host_client->userinfo, "team"), 31);
738 		t1[31] = 0;
739 	}
740 
741 	if (host_client->spectator && (!sv_spectalk.value || team))
742 		sprintf (text, "[SPEC] %s: ", host_client->name);
743 	else if (team)
744 		sprintf (text, "(%s): ", host_client->name);
745 	else {
746 		sprintf (text, "%s: ", host_client->name);
747 	}
748 
749 	if (fp_messages) {
750 		if (!sv.paused && realtime<host_client->lockedtill) {
751 			SV_ClientPrintf(host_client, PRINT_CHAT,
752 				"You can't talk for %d more seconds\n",
753 					(int) (host_client->lockedtill - realtime));
754 			return;
755 		}
756 		tmp = host_client->whensaidhead - fp_messages + 1;
757 		if (tmp < 0)
758 			tmp = 10+tmp;
759 		if (!sv.paused &&
760 			host_client->whensaid[tmp] && (realtime-host_client->whensaid[tmp] < fp_persecond)) {
761 			host_client->lockedtill = realtime + fp_secondsdead;
762 			if (fp_msg[0])
763 				SV_ClientPrintf(host_client, PRINT_CHAT,
764 					"FloodProt: %s\n", fp_msg);
765 			else
766 				SV_ClientPrintf(host_client, PRINT_CHAT,
767 					"FloodProt: You can't talk for %d seconds.\n", fp_secondsdead);
768 			return;
769 		}
770 		host_client->whensaidhead++;
771 		if (host_client->whensaidhead > 9)
772 			host_client->whensaidhead = 0;
773 		host_client->whensaid[host_client->whensaidhead] = realtime;
774 	}
775 
776 	p = Cmd_Args();
777 
778 	if (*p == '"')
779 	{
780 		p++;
781 		p[Q_strlen(p)-1] = 0;
782 	}
783 
784 	Q_strcat(text, p);
785 	Q_strcat(text, "\n");
786 
787 	Sys_Printf ("%s", text);
788 
789 	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
790 	{
791 		if (client->state != cs_spawned)
792 			continue;
793 		if (host_client->spectator && !sv_spectalk.value)
794 			if (!client->spectator)
795 				continue;
796 
797 		if (team)
798 		{
799 			// the spectator team
800 			if (host_client->spectator) {
801 				if (!client->spectator)
802 					continue;
803 			} else {
804 				t2 = Info_ValueForKey (client->userinfo, "team");
805 				if (strcmp(t1, t2) || client->spectator)
806 					continue;	// on different teams
807 			}
808 		}
809 		SV_ClientPrintf(client, PRINT_CHAT, "%s", text);
810 	}
811 }
812 
813 
814 /*
815 ==================
816 SV_Say_f
817 ==================
818 */
SV_Say_f(void)819 void SV_Say_f(void)
820 {
821 	SV_Say (false);
822 }
823 /*
824 ==================
825 SV_Say_Team_f
826 ==================
827 */
SV_Say_Team_f(void)828 void SV_Say_Team_f(void)
829 {
830 	SV_Say (true);
831 }
832 
833 
834 
835 //============================================================================
836 
837 /*
838 =================
839 SV_Pings_f
840 
841 The client is showing the scoreboard, so send new ping times for all
842 clients
843 =================
844 */
SV_Pings_f(void)845 void SV_Pings_f (void)
846 {
847 	client_t *client;
848 	int		j;
849 
850 	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
851 	{
852 		if (client->state != cs_spawned)
853 			continue;
854 
855 		ClientReliableWrite_Begin (host_client, svc_updateping, 4);
856 		ClientReliableWrite_Byte (host_client, j);
857 		ClientReliableWrite_Short (host_client, SV_CalcPing(client));
858 		ClientReliableWrite_Begin (host_client, svc_updatepl, 4);
859 		ClientReliableWrite_Byte (host_client, j);
860 		ClientReliableWrite_Byte (host_client, client->lossage);
861 	}
862 }
863 
864 
865 
866 /*
867 ==================
868 SV_Kill_f
869 ==================
870 */
SV_Kill_f(void)871 void SV_Kill_f (void)
872 {
873 	if (sv_player->v.health <= 0)
874 	{
875 		SV_ClientPrintf (host_client, PRINT_HIGH, "Can't suicide -- allready dead!\n");
876 		return;
877 	}
878 
879 	pr_global_struct->time = sv.time;
880 	pr_global_struct->self = EDICT_TO_PROG(sv_player);
881 	PR_ExecuteProgram (pr_global_struct->ClientKill);
882 }
883 
884 /*
885 ==================
886 SV_TogglePause
887 ==================
888 */
SV_TogglePause(const char * msg)889 void SV_TogglePause (const char *msg)
890 {
891 	int i;
892 	client_t *cl;
893 
894 	sv.paused ^= 1;
895 
896 	if (msg)
897 		SV_BroadcastPrintf (PRINT_HIGH, "%s", msg);
898 
899 	// send notification to all clients
900 	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
901 	{
902 		if (!cl->state)
903 			continue;
904 		ClientReliableWrite_Begin (cl, svc_setpause, 2);
905 		ClientReliableWrite_Byte (cl, sv.paused);
906 	}
907 }
908 
909 
910 /*
911 ==================
912 SV_Pause_f
913 ==================
914 */
SV_Pause_f(void)915 void SV_Pause_f (void)
916 {
917 	int i;
918 	client_t *cl;
919 	char st[sizeof(host_client->name) + 32];
920 
921 	if (!pausable.value) {
922 		SV_ClientPrintf (host_client, PRINT_HIGH, "Pause not allowed.\n");
923 		return;
924 	}
925 
926 	if (host_client->spectator) {
927 		SV_ClientPrintf (host_client, PRINT_HIGH, "Spectators can not pause.\n");
928 		return;
929 	}
930 
931 	if (sv.paused)
932 		sprintf (st, "%s paused the game\n", host_client->name);
933 	else
934 		sprintf (st, "%s unpaused the game\n", host_client->name);
935 
936 	SV_TogglePause(st);
937 }
938 
939 
940 /*
941 =================
942 SV_Drop_f
943 
944 The client is going to disconnect, so remove the connection immediately
945 =================
946 */
SV_Drop_f(void)947 void SV_Drop_f (void)
948 {
949 	SV_EndRedirect ();
950 	if (!host_client->spectator)
951 		SV_BroadcastPrintf (PRINT_HIGH, "%s dropped\n", host_client->name);
952 	SV_DropClient (host_client);
953 }
954 
955 /*
956 =================
957 SV_PTrack_f
958 
959 Change the bandwidth estimate for a client
960 =================
961 */
SV_PTrack_f(void)962 void SV_PTrack_f (void)
963 {
964 	int		i;
965 	edict_t *ent, *tent;
966 
967 	if (!host_client->spectator)
968 		return;
969 
970 	if (Cmd_Argc() != 2)
971 	{
972 		// turn off tracking
973 		host_client->spec_track = 0;
974 		ent = EDICT_NUM(host_client - svs.clients + 1);
975 		tent = EDICT_NUM(0);
976 		ent->v.goalentity = EDICT_TO_PROG(tent);
977 		return;
978 	}
979 
980 	i = atoi(Cmd_Argv(1));
981 	if (i < 0 || i >= MAX_CLIENTS || svs.clients[i].state != cs_spawned ||
982 		svs.clients[i].spectator) {
983 		SV_ClientPrintf (host_client, PRINT_HIGH, "Invalid client to track\n");
984 		host_client->spec_track = 0;
985 		ent = EDICT_NUM(host_client - svs.clients + 1);
986 		tent = EDICT_NUM(0);
987 		ent->v.goalentity = EDICT_TO_PROG(tent);
988 		return;
989 	}
990 	host_client->spec_track = i + 1; // now tracking
991 
992 	ent = EDICT_NUM(host_client - svs.clients + 1);
993 	tent = EDICT_NUM(i + 1);
994 	ent->v.goalentity = EDICT_TO_PROG(tent);
995 }
996 
997 
998 /*
999 =================
1000 SV_Rate_f
1001 
1002 Change the bandwidth estimate for a client
1003 =================
1004 */
SV_Rate_f(void)1005 void SV_Rate_f (void)
1006 {
1007 	int		rate;
1008 
1009 	if (Cmd_Argc() != 2)
1010 	{
1011 		SV_ClientPrintf (host_client, PRINT_HIGH, "Current rate is %i\n",
1012 			(int)(1.0/host_client->netchan.rate + 0.5));
1013 		return;
1014 	}
1015 
1016 	rate = atoi(Cmd_Argv(1));
1017 	if (rate < 500)
1018 		rate = 500;
1019 	if (rate > 10000)
1020 		rate = 10000;
1021 
1022 	SV_ClientPrintf (host_client, PRINT_HIGH, "Net rate set to %i\n", rate);
1023 	host_client->netchan.rate = 1.0/rate;
1024 }
1025 
1026 
1027 /*
1028 =================
1029 SV_Msg_f
1030 
1031 Change the message level for a client
1032 =================
1033 */
SV_Msg_f(void)1034 void SV_Msg_f (void)
1035 {
1036 	if (Cmd_Argc() != 2)
1037 	{
1038 		SV_ClientPrintf (host_client, PRINT_HIGH, "Current msg level is %i\n",
1039 			host_client->messagelevel);
1040 		return;
1041 	}
1042 
1043 	host_client->messagelevel = atoi(Cmd_Argv(1));
1044 
1045 	SV_ClientPrintf (host_client, PRINT_HIGH, "Msg level set to %i\n", host_client->messagelevel);
1046 }
1047 
1048 /*
1049 ==================
1050 SV_SetInfo_f
1051 
1052 Allow clients to change userinfo
1053 ==================
1054 */
SV_SetInfo_f(void)1055 void SV_SetInfo_f (void)
1056 {
1057 	int i;
1058 	char oldval[MAX_INFO_STRING];
1059 
1060 
1061 	if (Cmd_Argc() == 1)
1062 	{
1063 		Con_Printf ("User info settings:\n");
1064 		Info_Print (host_client->userinfo);
1065 		return;
1066 	}
1067 
1068 	if (Cmd_Argc() != 3)
1069 	{
1070 		Con_Printf ("usage: setinfo [ <key> <value> ]\n");
1071 		return;
1072 	}
1073 
1074 	if (Cmd_Argv(1)[0] == '*')
1075 		return;		// don't set priveledged values
1076 
1077 	strcpy(oldval, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
1078 
1079 	Info_SetValueForKey (host_client->userinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_INFO_STRING);
1080 // name is extracted below in ExtractFromUserInfo
1081 //	strncpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name")
1082 //		, sizeof(host_client->name)-1);
1083 //	SV_FullClientUpdate (host_client, &sv.reliable_datagram);
1084 //	host_client->sendinfo = true;
1085 
1086 	if (!strcmp(Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)), oldval))
1087 		return; // key hasn't changed
1088 
1089 	// process any changed values
1090 	SV_ExtractFromUserinfo (host_client);
1091 
1092 	i = host_client - svs.clients;
1093 	MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
1094 	MSG_WriteByte (&sv.reliable_datagram, i);
1095 	MSG_WriteString (&sv.reliable_datagram, Cmd_Argv(1));
1096 	MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
1097 }
1098 
1099 /*
1100 ==================
1101 SV_ShowServerinfo_f
1102 
1103 Dumps the serverinfo info string
1104 ==================
1105 */
SV_ShowServerinfo_f(void)1106 void SV_ShowServerinfo_f (void)
1107 {
1108 	Info_Print (svs.info);
1109 }
1110 
SV_NoSnap_f(void)1111 void SV_NoSnap_f(void)
1112 {
1113 	if (*host_client->uploadfn) {
1114 		*host_client->uploadfn = 0;
1115 		SV_BroadcastPrintf (PRINT_HIGH, "%s refused remote screenshot\n", host_client->name);
1116 	}
1117 }
1118 
1119 typedef struct
1120 {
1121 	char	*name;
1122 	void	(*func) (void);
1123 } ucmd_t;
1124 
1125 ucmd_t ucmds[] =
1126 {
1127 	{"new", SV_New_f},
1128 	{"modellist", SV_Modellist_f},
1129 	{"soundlist", SV_Soundlist_f},
1130 	{"prespawn", SV_PreSpawn_f},
1131 	{"spawn", SV_Spawn_f},
1132 	{"begin", SV_Begin_f},
1133 
1134 	{"drop", SV_Drop_f},
1135 	{"pings", SV_Pings_f},
1136 
1137 // issued by hand at client consoles
1138 	{"rate", SV_Rate_f},
1139 	{"kill", SV_Kill_f},
1140 	{"pause", SV_Pause_f},
1141 	{"msg", SV_Msg_f},
1142 
1143 	{"say", SV_Say_f},
1144 	{"say_team", SV_Say_Team_f},
1145 
1146 	{"setinfo", SV_SetInfo_f},
1147 
1148 	{"serverinfo", SV_ShowServerinfo_f},
1149 
1150 	{"download", SV_BeginDownload_f},
1151 	{"nextdl", SV_NextDownload_f},
1152 
1153 	{"ptrack", SV_PTrack_f}, //ZOID - used with autocam
1154 
1155 	{"snap", SV_NoSnap_f},
1156 
1157 	{NULL, NULL}
1158 };
1159 
1160 /*
1161 ==================
1162 SV_ExecuteUserCommand
1163 ==================
1164 */
SV_ExecuteUserCommand(char * s)1165 void SV_ExecuteUserCommand (char *s)
1166 {
1167 	ucmd_t	*u;
1168 
1169 	Cmd_TokenizeString (s);
1170 	sv_player = host_client->edict;
1171 
1172 	SV_BeginRedirect (RD_CLIENT);
1173 
1174 	for (u=ucmds ; u->name ; u++)
1175 		if (!strcmp (Cmd_Argv(0), u->name) )
1176 		{
1177 			u->func ();
1178 			break;
1179 		}
1180 
1181 	if (!u->name)
1182 		Con_Printf ("Bad user command: %s\n", Cmd_Argv(0));
1183 
1184 	SV_EndRedirect ();
1185 }
1186 
1187 /*
1188 ===========================================================================
1189 
1190 USER CMD EXECUTION
1191 
1192 ===========================================================================
1193 */
1194 
1195 /*
1196 ===============
1197 V_CalcRoll
1198 
1199 Used by view and sv_user
1200 ===============
1201 */
V_CalcRoll(vec3_t angles,vec3_t velocity)1202 float V_CalcRoll (vec3_t angles, vec3_t velocity)
1203 {
1204 	vec3_t	forward, right, up;
1205 	float	sign;
1206 	float	side;
1207 	float	value;
1208 
1209 	AngleVectors (angles, forward, right, up);
1210 	side = DotProduct (velocity, right);
1211 	sign = side < 0 ? -1 : 1;
1212 	side = fabs(side);
1213 
1214 	value = cl_rollangle.value;
1215 
1216 	if (side < cl_rollspeed.value)
1217 		side = side * value / cl_rollspeed.value;
1218 	else
1219 		side = value;
1220 
1221 	return side*sign;
1222 
1223 }
1224 
1225 
1226 
1227 
1228 //============================================================================
1229 
1230 vec3_t	pmove_mins, pmove_maxs;
1231 
1232 /*
1233 ====================
1234 AddLinksToPmove
1235 
1236 ====================
1237 */
AddLinksToPmove(areanode_t * node)1238 void AddLinksToPmove ( areanode_t *node )
1239 {
1240 	link_t		*l, *next;
1241 	edict_t		*check;
1242 	int			pl;
1243 	int			i;
1244 	physent_t	*pe;
1245 
1246 	pl = EDICT_TO_PROG(sv_player);
1247 
1248 	// touch linked edicts
1249 	for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
1250 	{
1251 		next = l->next;
1252 		check = EDICT_FROM_AREA(l);
1253 
1254 		if (check->v.owner == pl)
1255 			continue;		// player's own missile
1256 		if (check->v.solid == SOLID_BSP
1257 			|| check->v.solid == SOLID_BBOX
1258 			|| check->v.solid == SOLID_SLIDEBOX)
1259 		{
1260 			if (check == sv_player)
1261 				continue;
1262 
1263 			for (i=0 ; i<3 ; i++)
1264 				if (check->v.absmin[i] > pmove_maxs[i]
1265 				|| check->v.absmax[i] < pmove_mins[i])
1266 					break;
1267 			if (i != 3)
1268 				continue;
1269 			if (pmove.numphysent == MAX_PHYSENTS)
1270 				return;
1271 			pe = &pmove.physents[pmove.numphysent];
1272 			pmove.numphysent++;
1273 
1274 			VectorCopy (check->v.origin, pe->origin);
1275 			pe->info = NUM_FOR_EDICT(check);
1276 			if (check->v.solid == SOLID_BSP)
1277 				pe->model = sv.models[(int)(check->v.modelindex)];
1278 			else
1279 			{
1280 				pe->model = NULL;
1281 				VectorCopy (check->v.mins, pe->mins);
1282 				VectorCopy (check->v.maxs, pe->maxs);
1283 			}
1284 		}
1285 	}
1286 
1287 // recurse down both sides
1288 	if (node->axis == -1)
1289 		return;
1290 
1291 	if ( pmove_maxs[node->axis] > node->dist )
1292 		AddLinksToPmove ( node->children[0] );
1293 	if ( pmove_mins[node->axis] < node->dist )
1294 		AddLinksToPmove ( node->children[1] );
1295 }
1296 
1297 
1298 /*
1299 ================
1300 AddAllEntsToPmove
1301 
1302 For debugging
1303 ================
1304 */
AddAllEntsToPmove(void)1305 void AddAllEntsToPmove (void)
1306 {
1307 	int			e;
1308 	edict_t		*check;
1309 	int			i;
1310 	physent_t	*pe;
1311 	int			pl;
1312 
1313 	pl = EDICT_TO_PROG(sv_player);
1314 	check = NEXT_EDICT(sv.edicts);
1315 	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
1316 	{
1317 		if (check->free)
1318 			continue;
1319 		if (check->v.owner == pl)
1320 			continue;
1321 		if (check->v.solid == SOLID_BSP
1322 			|| check->v.solid == SOLID_BBOX
1323 			|| check->v.solid == SOLID_SLIDEBOX)
1324 		{
1325 			if (check == sv_player)
1326 				continue;
1327 
1328 			for (i=0 ; i<3 ; i++)
1329 				if (check->v.absmin[i] > pmove_maxs[i]
1330 				|| check->v.absmax[i] < pmove_mins[i])
1331 					break;
1332 			if (i != 3)
1333 				continue;
1334 			pe = &pmove.physents[pmove.numphysent];
1335 
1336 			VectorCopy (check->v.origin, pe->origin);
1337 			pmove.physents[pmove.numphysent].info = e;
1338 			if (check->v.solid == SOLID_BSP)
1339 				pe->model = sv.models[(int)(check->v.modelindex)];
1340 			else
1341 			{
1342 				pe->model = NULL;
1343 				VectorCopy (check->v.mins, pe->mins);
1344 				VectorCopy (check->v.maxs, pe->maxs);
1345 			}
1346 
1347 			if (++pmove.numphysent == MAX_PHYSENTS)
1348 				break;
1349 		}
1350 	}
1351 }
1352 
1353 /*
1354 ===========
1355 SV_PreRunCmd
1356 ===========
1357 Done before running a player command.  Clears the touch array
1358 */
1359 byte playertouch[(MAX_EDICTS+7)/8];
1360 
SV_PreRunCmd(void)1361 void SV_PreRunCmd(void)
1362 {
1363 	memset(playertouch, 0, sizeof(playertouch));
1364 }
1365 
1366 /*
1367 ===========
1368 SV_RunCmd
1369 ===========
1370 */
SV_RunCmd(usercmd_t * ucmd)1371 void SV_RunCmd (usercmd_t *ucmd)
1372 {
1373 	edict_t		*ent;
1374 	int			i, n;
1375 	int			oldmsec;
1376 
1377 	cmd = *ucmd;
1378 
1379 	// chop up very long commands
1380 	if (cmd.msec > 50)
1381 	{
1382 		oldmsec = ucmd->msec;
1383 		cmd.msec = oldmsec/2;
1384 		SV_RunCmd (&cmd);
1385 		cmd.msec = oldmsec/2;
1386 		cmd.impulse = 0;
1387 		SV_RunCmd (&cmd);
1388 		return;
1389 	}
1390 
1391 	if (!sv_player->v.fixangle)
1392 		VectorCopy (ucmd->angles, sv_player->v.v_angle);
1393 
1394 	sv_player->v.button0 = ucmd->buttons & 1;
1395 	sv_player->v.button2 = (ucmd->buttons & 2)>>1;
1396 	if (ucmd->impulse)
1397 		sv_player->v.impulse = ucmd->impulse;
1398 
1399 //
1400 // angles
1401 // show 1/3 the pitch angle and all the roll angle
1402 	if (sv_player->v.health > 0)
1403 	{
1404 		if (!sv_player->v.fixangle)
1405 		{
1406 			sv_player->v.angles[PITCH] = -sv_player->v.v_angle[PITCH]/3;
1407 			sv_player->v.angles[YAW] = sv_player->v.v_angle[YAW];
1408 		}
1409 		sv_player->v.angles[ROLL] =
1410 			V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
1411 	}
1412 
1413 	host_frametime = ucmd->msec * 0.001;
1414 	if (host_frametime > 0.1)
1415 		host_frametime = 0.1;
1416 
1417 	if (!host_client->spectator)
1418 	{
1419 		pr_global_struct->frametime = host_frametime;
1420 
1421 		pr_global_struct->time = sv.time;
1422 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
1423 		PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
1424 
1425 		SV_RunThink (sv_player);
1426 	}
1427 
1428 	for (i=0 ; i<3 ; i++)
1429 		pmove.origin[i] = sv_player->v.origin[i] + (sv_player->v.mins[i] - player_mins[i]);
1430 	VectorCopy (sv_player->v.velocity, pmove.velocity);
1431 	VectorCopy (sv_player->v.v_angle, pmove.angles);
1432 
1433 	pmove.spectator = host_client->spectator;
1434 	pmove.waterjumptime = sv_player->v.teleport_time;
1435 	pmove.numphysent = 1;
1436 	pmove.physents[0].model = sv.worldmodel;
1437 	pmove.cmd = *ucmd;
1438 	pmove.dead = sv_player->v.health <= 0;
1439 	pmove.oldbuttons = host_client->oldbuttons;
1440 
1441 	movevars.entgravity = host_client->entgravity;
1442 	movevars.maxspeed = host_client->maxspeed;
1443 
1444 	for (i=0 ; i<3 ; i++)
1445 	{
1446 		pmove_mins[i] = pmove.origin[i] - 256;
1447 		pmove_maxs[i] = pmove.origin[i] + 256;
1448 	}
1449 #if 1
1450 	AddLinksToPmove ( sv_areanodes );
1451 #else
1452 	AddAllEntsToPmove ();
1453 #endif
1454 
1455 #if 0
1456 {
1457 	int before, after;
1458 
1459 before = PM_TestPlayerPosition (pmove.origin);
1460 	PlayerMove ();
1461 after = PM_TestPlayerPosition (pmove.origin);
1462 
1463 if (sv_player->v.health > 0 && before && !after )
1464 	Con_Printf ("player %s got stuck in playermove!!!!\n", host_client->name);
1465 }
1466 #else
1467 	PlayerMove ();
1468 #endif
1469 
1470 	host_client->oldbuttons = pmove.oldbuttons;
1471 	sv_player->v.teleport_time = pmove.waterjumptime;
1472 	sv_player->v.waterlevel = waterlevel;
1473 	sv_player->v.watertype = watertype;
1474 	if (onground != -1)
1475 	{
1476 		sv_player->v.flags = (int)sv_player->v.flags | FL_ONGROUND;
1477 		sv_player->v.groundentity = EDICT_TO_PROG(EDICT_NUM(pmove.physents[onground].info));
1478 	}
1479 	else
1480 		sv_player->v.flags = (int)sv_player->v.flags & ~FL_ONGROUND;
1481 	for (i=0 ; i<3 ; i++)
1482 		sv_player->v.origin[i] = pmove.origin[i] - (sv_player->v.mins[i] - player_mins[i]);
1483 
1484 #if 0
1485 	// truncate velocity the same way the net protocol will
1486 	for (i=0 ; i<3 ; i++)
1487 		sv_player->v.velocity[i] = (int)pmove.velocity[i];
1488 #else
1489 	VectorCopy (pmove.velocity, sv_player->v.velocity);
1490 #endif
1491 
1492 	VectorCopy (pmove.angles, sv_player->v.v_angle);
1493 
1494 	if (!host_client->spectator)
1495 	{
1496 		// link into place and touch triggers
1497 		SV_LinkEdict (sv_player, true);
1498 
1499 		// touch other objects
1500 		for (i=0 ; i<pmove.numtouch ; i++)
1501 		{
1502 			n = pmove.physents[pmove.touchindex[i]].info;
1503 			ent = EDICT_NUM(n);
1504 			if (!ent->v.touch || (playertouch[n/8]&(1<<(n%8))))
1505 				continue;
1506 			pr_global_struct->self = EDICT_TO_PROG(ent);
1507 			pr_global_struct->other = EDICT_TO_PROG(sv_player);
1508 			PR_ExecuteProgram (ent->v.touch);
1509 			playertouch[n/8] |= 1 << (n%8);
1510 		}
1511 	}
1512 }
1513 
1514 /*
1515 ===========
1516 SV_PostRunCmd
1517 ===========
1518 Done after running a player command.
1519 */
SV_PostRunCmd(void)1520 void SV_PostRunCmd(void)
1521 {
1522 	// run post-think
1523 
1524 	if (!host_client->spectator) {
1525 		pr_global_struct->time = sv.time;
1526 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
1527 		PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
1528 		SV_RunNewmis ();
1529 	} else if (SpectatorThink) {
1530 		pr_global_struct->time = sv.time;
1531 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
1532 		PR_ExecuteProgram (SpectatorThink);
1533 	}
1534 }
1535 
1536 
1537 /*
1538 ===================
1539 SV_ExecuteClientMessage
1540 
1541 The current net_message is parsed for the given client
1542 ===================
1543 */
SV_ExecuteClientMessage(client_t * cl)1544 void SV_ExecuteClientMessage (client_t *cl)
1545 {
1546 	int		c;
1547 	char	*s;
1548 	usercmd_t	oldest, oldcmd, newcmd;
1549 	client_frame_t	*frame;
1550 	vec3_t o;
1551 	qboolean	move_issued = false; //only allow one move command
1552 	int		checksumIndex;
1553 	byte	checksum, calculatedChecksum;
1554 	int		seq_hash;
1555 
1556 	// calc ping time
1557 	frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
1558 	frame->ping_time = realtime - frame->senttime;
1559 
1560 	// make sure the reply sequence number matches the incoming
1561 	// sequence number
1562 	if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
1563 		cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
1564 	else
1565 		cl->send_message = false;	// don't reply, sequences have slipped
1566 
1567 	// save time for ping calculations
1568 	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
1569 	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
1570 
1571 	host_client = cl;
1572 	sv_player = host_client->edict;
1573 
1574 //	seq_hash = (cl->netchan.incoming_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
1575 	seq_hash = cl->netchan.incoming_sequence;
1576 
1577 	// mark time so clients will know how much to predict
1578 	// other players
1579  	cl->localtime = sv.time;
1580 	cl->delta_sequence = -1;	// no delta unless requested
1581 	while (1)
1582 	{
1583 		if (msg_badread)
1584 		{
1585 			Con_Printf ("SV_ReadClientMessage: badread\n");
1586 			SV_DropClient (cl);
1587 			return;
1588 		}
1589 
1590 		c = MSG_ReadByte ();
1591 		if (c == -1)
1592 			break;
1593 
1594 		switch (c)
1595 		{
1596 		default:
1597 			Con_Printf ("SV_ReadClientMessage: unknown command char\n");
1598 			SV_DropClient (cl);
1599 			return;
1600 
1601 		case clc_nop:
1602 			break;
1603 
1604 		case clc_delta:
1605 			cl->delta_sequence = MSG_ReadByte ();
1606 			break;
1607 
1608 		case clc_move:
1609 			if (move_issued)
1610 				return;		// someone is trying to cheat...
1611 
1612 			move_issued = true;
1613 
1614 			checksumIndex = MSG_GetReadCount();
1615 			checksum = (byte)MSG_ReadByte ();
1616 
1617 			// read loss percentage
1618 			cl->lossage = MSG_ReadByte();
1619 
1620 			MSG_ReadDeltaUsercmd (&nullcmd, &oldest);
1621 			MSG_ReadDeltaUsercmd (&oldest, &oldcmd);
1622 			MSG_ReadDeltaUsercmd (&oldcmd, &newcmd);
1623 
1624 			if ( cl->state != cs_spawned )
1625 				break;
1626 
1627 			// if the checksum fails, ignore the rest of the packet
1628 			calculatedChecksum = COM_BlockSequenceCRCByte(
1629 				net_message.data + checksumIndex + 1,
1630 				MSG_GetReadCount() - checksumIndex - 1,
1631 				seq_hash);
1632 
1633 			if (calculatedChecksum != checksum)
1634 			{
1635 				Con_DPrintf ("Failed command checksum for %s(%d) (%d != %d)\n",
1636 					cl->name, cl->netchan.incoming_sequence, checksum, calculatedChecksum);
1637 				return;
1638 			}
1639 
1640 			if (!sv.paused) {
1641 				SV_PreRunCmd();
1642 
1643 				if (net_drop < 20)
1644 				{
1645 					while (net_drop > 2)
1646 					{
1647 						SV_RunCmd (&cl->lastcmd);
1648 						net_drop--;
1649 					}
1650 					if (net_drop > 1)
1651 						SV_RunCmd (&oldest);
1652 					if (net_drop > 0)
1653 						SV_RunCmd (&oldcmd);
1654 				}
1655 				SV_RunCmd (&newcmd);
1656 
1657 				SV_PostRunCmd();
1658 			}
1659 
1660 			cl->lastcmd = newcmd;
1661 			cl->lastcmd.buttons = 0; // avoid multiple fires on lag
1662 			break;
1663 
1664 
1665 		case clc_stringcmd:
1666 			s = MSG_ReadString ();
1667 			SV_ExecuteUserCommand (s);
1668 			break;
1669 
1670 		case clc_tmove:
1671 			o[0] = MSG_ReadCoord();
1672 			o[1] = MSG_ReadCoord();
1673 			o[2] = MSG_ReadCoord();
1674 			// only allowed by spectators
1675 			if (host_client->spectator) {
1676 				VectorCopy(o, sv_player->v.origin);
1677 				SV_LinkEdict(sv_player, false);
1678 			}
1679 			break;
1680 
1681 		case clc_upload:
1682 			SV_NextUpload();
1683 			break;
1684 
1685 		}
1686 	}
1687 }
1688 
1689 /*
1690 ==============
1691 SV_UserInit
1692 ==============
1693 */
SV_UserInit(void)1694 void SV_UserInit (void)
1695 {
1696 	Cvar_RegisterVariable (&cl_rollspeed);
1697 	Cvar_RegisterVariable (&cl_rollangle);
1698 	Cvar_RegisterVariable (&sv_spectalk);
1699 	Cvar_RegisterVariable (&sv_mapcheck);
1700 }
1701 
1702 
1703