649 lines · 14.0 KB · C
RawDownload
// sv_user.c -- server code for moving users #include <u.h>#include <libc.h>#include <stdio.h>#include "dat.h"#include "fns.h" edict_t	*sv_player; /*============================================================ USER STRINGCMD EXECUTION sv_client and sv_player will be valid.============================================================*/ /*==================SV_BeginDemoServer==================*/void SV_BeginDemoserver (void){	char		name[MAX_OSPATH]; 	Com_sprintf (name, sizeof(name), "demos/%s", sv.name);	FS_FOpenFile (name, &sv.demofile);	if (!sv.demofile)		Com_Error (ERR_DROP, "Couldn't open %s\n", name);} /*================SV_New_f Sends the first message from the server to a connected client.This will be sent on the initial connection and upon each server load.================*/void SV_New_f (void){	char		*gamedir;	int			playernum;	edict_t		*ent; 	Com_DPrintf ("New() from %s\n", sv_client->name); 	if (sv_client->state != cs_connected)	{		Com_Printf ("New not valid -- already spawned\n");		return;	} 	// demo servers just dump the file message	if (sv.state == ss_demo)	{		SV_BeginDemoserver ();		return;	} 	//	// serverdata needs to go over for all types of servers	// to make sure the protocol is right, and to set the gamedir	//	gamedir = Cvar_VariableString ("gamedir"); 	// send the serverdata	MSG_WriteByte (&sv_client->netchan.message, svc_serverdata);	MSG_WriteLong (&sv_client->netchan.message, PROTOCOL_VERSION);	MSG_WriteLong (&sv_client->netchan.message, svs.spawncount);	MSG_WriteByte (&sv_client->netchan.message, sv.attractloop);	MSG_WriteString (&sv_client->netchan.message, gamedir); 	if (sv.state == ss_cinematic || sv.state == ss_pic)		playernum = -1;	else		playernum = sv_client - svs.clients;	MSG_WriteShort (&sv_client->netchan.message, playernum); 	// send full levelname	MSG_WriteString (&sv_client->netchan.message, sv.configstrings[CS_NAME]); 	//	// game server	// 	if (sv.state == ss_game)	{		// set up the entity for the client		ent = EDICT_NUM(playernum+1);		ent->s.number = playernum+1;		sv_client->edict = ent;		memset (&sv_client->lastcmd, 0, sizeof(sv_client->lastcmd)); 		// begin fetching configstrings		MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);		MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i 0\n",svs.spawncount) );	} } /*==================SV_Configstrings_f==================*/void SV_Configstrings_f (void){	int			start; 	Com_DPrintf ("Configstrings() from %s\n", sv_client->name); 	if (sv_client->state != cs_connected)	{		Com_Printf ("configstrings not valid -- already spawned\n");		return;	} 	// handle the case of a level changing while a client was connecting	if ( atoi(Cmd_Argv(1)) != svs.spawncount )	{		Com_Printf ("SV_Configstrings_f from different level\n");		SV_New_f ();		return;	}		start = atoi(Cmd_Argv(2)); 	// write a packet full of data 	while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 		&& start < MAX_CONFIGSTRINGS)	{		if (sv.configstrings[start][0])		{			MSG_WriteByte (&sv_client->netchan.message, svc_configstring);			MSG_WriteShort (&sv_client->netchan.message, start);			MSG_WriteString (&sv_client->netchan.message, sv.configstrings[start]);		}		start++;	} 	// send next command 	if (start == MAX_CONFIGSTRINGS)	{		MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);		MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i 0\n",svs.spawncount) );	}	else	{		MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);		MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i %i\n",svs.spawncount, start) );	}} /*==================SV_Baselines_f==================*/void SV_Baselines_f (void){	int		start;	entity_state_t	nullstate;	entity_state_t	*base; 	Com_DPrintf ("Baselines() from %s\n", sv_client->name); 	if (sv_client->state != cs_connected)	{		Com_Printf ("baselines not valid -- already spawned\n");		return;	}		// handle the case of a level changing while a client was connecting	if ( atoi(Cmd_Argv(1)) != svs.spawncount )	{		Com_Printf ("SV_Baselines_f from different level\n");		SV_New_f ();		return;	}		start = atoi(Cmd_Argv(2)); 	memset (&nullstate, 0, sizeof(nullstate)); 	// write a packet full of data 	while ( sv_client->netchan.message.cursize <  MAX_MSGLEN/2		&& start < MAX_EDICTS)	{		base = &sv.baselines[start];		if (base->modelindex || base->sound || base->effects)		{			MSG_WriteByte (&sv_client->netchan.message, svc_spawnbaseline);			MSG_WriteDeltaEntity (&nullstate, base, &sv_client->netchan.message, true, true);		}		start++;	} 	// send next command 	if (start == MAX_EDICTS)	{		MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);		MSG_WriteString (&sv_client->netchan.message, va("precache %i\n", svs.spawncount) );	}	else	{		MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);		MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i %i\n",svs.spawncount, start) );	}} /*==================SV_Begin_f==================*/void SV_Begin_f (void){	Com_DPrintf ("Begin() from %s\n", sv_client->name); 	// handle the case of a level changing while a client was connecting	if ( atoi(Cmd_Argv(1)) != svs.spawncount )	{		Com_Printf ("SV_Begin_f from different level\n");		SV_New_f ();		return;	} 	sv_client->state = cs_spawned; 	// call the game begin function	ge->ClientBegin (sv_player); 	Cbuf_InsertFromDefer ();} //============================================================================= /*==================SV_NextDownload_f==================*/void SV_NextDownload_f (void){	int		r;	int		percent;	int		size; 	if (!sv_client->download)		return; 	r = sv_client->downloadsize - sv_client->downloadcount;	if (r > 1024)		r = 1024; 	MSG_WriteByte (&sv_client->netchan.message, svc_download);	MSG_WriteShort (&sv_client->netchan.message, r); 	sv_client->downloadcount += r;	size = sv_client->downloadsize;	if (!size)		size = 1;	percent = sv_client->downloadcount*100/size;	MSG_WriteByte (&sv_client->netchan.message, percent);	SZ_Write (&sv_client->netchan.message,		sv_client->download + sv_client->downloadcount - r, r); 	if (sv_client->downloadcount != sv_client->downloadsize)		return; 	FS_FreeFile (sv_client->download);	sv_client->download = NULL;} /*==================SV_BeginDownload_f==================*/void SV_BeginDownload_f(void){	char	*name;	extern	cvar_t *allow_download;	extern	cvar_t *allow_download_players;	extern	cvar_t *allow_download_models;	extern	cvar_t *allow_download_sounds;	extern	cvar_t *allow_download_maps;	extern	int		file_from_pak; // ZOID did file come from pak?	int offset = 0; 	name = Cmd_Argv(1); 	if (Cmd_Argc() > 2)		offset = atoi(Cmd_Argv(2)); // downloaded offset 	// hacked by zoid to allow more conrol over download	// first off, no .. or global allow check	if (strstr (name, "..") || !allow_download->value		// leading dot is no good		|| *name == '.' 		// leading slash bad as well, must be in subdir		|| *name == '/'		// next up, skin check		|| (strncmp(name, "players/", 6) == 0 && !allow_download_players->value)		// now models		|| (strncmp(name, "models/", 6) == 0 && !allow_download_models->value)		// now sounds		|| (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value)		// now maps (note special case for maps, must not be in pak)		|| (strncmp(name, "maps/", 6) == 0 && !allow_download_maps->value)		// MUST be in a subdirectory			|| !strstr (name, "/") )		{	// don't allow anything with .. path		MSG_WriteByte (&sv_client->netchan.message, svc_download);		MSG_WriteShort (&sv_client->netchan.message, -1);		MSG_WriteByte (&sv_client->netchan.message, 0);		return;	}  	if (sv_client->download)		FS_FreeFile (sv_client->download); 	sv_client->downloadsize = FS_LoadFile (name, (void **)&sv_client->download);	sv_client->downloadcount = offset; 	if (offset > sv_client->downloadsize)		sv_client->downloadcount = sv_client->downloadsize; 	if (!sv_client->download		// special check for maps, if it came from a pak file, don't allow		// download  ZOID		|| (strncmp(name, "maps/", 5) == 0 && file_from_pak))	{		Com_DPrintf ("Couldn't download %s to %s\n", name, sv_client->name);		if (sv_client->download) {			FS_FreeFile (sv_client->download);			sv_client->download = NULL;		} 		MSG_WriteByte (&sv_client->netchan.message, svc_download);		MSG_WriteShort (&sv_client->netchan.message, -1);		MSG_WriteByte (&sv_client->netchan.message, 0);		return;	} 	SV_NextDownload_f ();	Com_DPrintf ("Downloading %s to %s\n", name, sv_client->name);}   //============================================================================  /*=================SV_Disconnect_f The client is going to disconnect, so remove the connection immediately=================*/void SV_Disconnect_f (void){//	SV_EndRedirect ();	SV_DropClient (sv_client);	}  /*==================SV_ShowServerinfo_f Dumps the serverinfo info string==================*/void SV_ShowServerinfo_f (void){	Info_Print (Cvar_Serverinfo());}  void SV_Nextserver (void){	char	*v; 	//ZOID, ss_pic can be nextserver'd in coop mode	if (sv.state == ss_game || (sv.state == ss_pic && !Cvar_VariableValue("coop")))		return;		// can't nextserver while playing a normal game 	svs.spawncount++;	// make sure another doesn't sneak in	v = Cvar_VariableString ("nextserver");	if (!v[0])		Cbuf_AddText ("killserver\n");	else	{		Cbuf_AddText (v);		Cbuf_AddText ("\n");	}	Cvar_Set ("nextserver","");} /*==================SV_Nextserver_f A cinematic has completed or been aborted by a client, so moveto the next server,==================*/void SV_Nextserver_f (void){	if ( atoi(Cmd_Argv(1)) != svs.spawncount ) {		Com_DPrintf ("Nextserver() from wrong level, from %s\n", sv_client->name);		return;		// leftover from last server	} 	Com_DPrintf ("Nextserver() from %s\n", sv_client->name); 	SV_Nextserver ();} typedef struct{	char	*name;	void	(*func) (void);} ucmd_t; ucmd_t ucmds[] ={	// auto issued	{"new", SV_New_f},	{"configstrings", SV_Configstrings_f},	{"baselines", SV_Baselines_f},	{"begin", SV_Begin_f}, 	{"nextserver", SV_Nextserver_f}, 	{"disconnect", SV_Disconnect_f}, 	// issued by hand at client consoles		{"info", SV_ShowServerinfo_f}, 	{"download", SV_BeginDownload_f},	{"nextdl", SV_NextDownload_f}, 	{NULL, NULL}}; /*==================SV_ExecuteUserCommand==================*/void SV_ExecuteUserCommand (char *s){	ucmd_t	*u;		Cmd_TokenizeString (s, true);	sv_player = sv_client->edict; //	SV_BeginRedirect (RD_CLIENT); 	for (u=ucmds ; u->name ; u++)		if (!strcmp (Cmd_Argv(0), u->name) )		{			u->func ();			break;		} 	if (!u->name && sv.state == ss_game)		ge->ClientCommand (sv_player); //	SV_EndRedirect ();} /*=========================================================================== USER CMD EXECUTION ===========================================================================*/   void SV_ClientThink (client_t *cl, usercmd_t *cmd) {	cl->commandMsec -= cmd->msec; 	if (cl->commandMsec < 0 && sv_enforcetime->value )	{

Lines 1–500 of 649.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t