Beispiel #1
0
void Host_LoadStrings (void)
{
	int		i, count, start;
	signed char	newline_char;

	host_strings = (char *)FS_LoadHunkFile ("strings.txt", NULL);
	if (!host_strings)
		Host_Error ("%s: couldn't load strings.txt", __thisfunc__);

	newline_char = -1;

	for (i = count = 0; host_strings[i] != 0; i++)
	{
		if (host_strings[i] == '\r' || host_strings[i] == '\n')
		{
			if (newline_char == host_strings[i] || newline_char == -1)
			{
				newline_char = host_strings[i];
				count++;
			}
		}
	}

	if (!count)
	{
		Host_Error ("%s: no string lines found", __thisfunc__);
	}

	host_string_index = (int *)Hunk_AllocName ((count + 1)*sizeof(int), "string_index");

	for (i = count = start = 0; host_strings[i] != 0; i++)
	{
		if (host_strings[i] == '\r' || host_strings[i] == '\n')
		{
			if (newline_char == host_strings[i])
			{
				host_string_index[count] = start;
				start = i + 1;
				count++;
			}
			else
			{
				start++;
			}

			host_strings[i] = 0;
		}
#if defined(H2W)
		/* Hexenworld: translate '^' to
		 * '\n' for indexed prints */
		else if (host_strings[i] == '^')
		{
			host_strings[i] = '\n';
		}
#endif	/* H2W */
	}

	host_string_count = count;
	Con_DPrintf("Read in %d string lines\n", count);
}
Beispiel #2
0
/*
===============
Cmd_Exec_f
===============
*/
void Cmd_Exec_f (void)
{
	char	*f;
	int		mark;

	if (Cmd_Argc () != 2)
	{
		Con_Printf ("exec <filename> : execute a script file\n");
		return;
	}

	// FIXME: is this safe freeing the hunk here???
	mark = Hunk_LowMark ();
	f = (char *)FS_LoadHunkFile (Cmd_Argv(1), NULL);
	if (!f)
	{
		Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
		return;
	}

	Con_Printf ("execing %s\n",Cmd_Argv(1));

	Cbuf_InsertText (f);
	Hunk_FreeToLowMark (mark);
}
Beispiel #3
0
static unsigned SV_CheckModel(char *mdl)
{
	unsigned char *buf;
	unsigned short crc;
	int filesize;
	int mark;

	mark = Hunk_LowMark ();
	buf = (byte *) FS_LoadHunkFile (mdl, &filesize);
	if (!buf)
	{
		if (!strcmp (mdl, "progs/player.mdl"))
			return 33168;
		else if (!strcmp (mdl, "progs/newplayer.mdl"))
			return 62211;
		else if (!strcmp (mdl, "progs/eyes.mdl"))
			return 6967;
		else
			SV_Error ("SV_CheckModel: could not load %s\n", mdl);
	}

	crc = CRC_Block (buf, filesize);
	Hunk_FreeToLowMark (mark);

	return crc;
}
Beispiel #4
0
/*
===============
Cmd_Exec_f
===============
*/
void Cmd_Exec_f (void)
{
	char	*f;
	int		mark;
	char	name[MAX_OSPATH];

	if (Cmd_Argc () != 2)
	{
		Com_Printf ("exec <filename> : execute a script file\n");
		return;
	}

	strlcpy (name, Cmd_Argv(1), sizeof(name) - 4);
	mark = Hunk_LowMark ();
	f = (char *)FS_LoadHunkFile (name);
	if (!f)
	{
		char *p;

		p = COM_SkipPath (name);
		if (!strchr (p, '.')) {
			// no extension, so try the default (.cfg)
			strcat (name, ".cfg");
			f = (char *)FS_LoadHunkFile (name);
		}

		if (!f) {
			Com_Printf ("couldn't exec %s\n", Cmd_Argv(1));
			return;
		}
	}
	if (cl_warncmd.value || developer.value)
		Com_Printf ("execing %s\n", name);

#ifndef SERVERONLY
	if (cbuf_current == &cbuf_svc) {
		Cbuf_AddText (f);
		Cbuf_AddText ("\n");
	}
	else
#endif
	{
		Cbuf_InsertText ("\n");
		Cbuf_InsertText (f);
	}
	Hunk_FreeToLowMark (mark);
}
Beispiel #5
0
void PR_LoadProgs (void)
{
	int	i;
	char num[32];
	char name[MAX_OSPATH];
	int filesize;

	// flush the non-C variable lookup cache
	for (i = 0; i < GEFV_CACHESIZE; i++)
		gefvCache[i].field[0] = 0;

	// clear pr_newstrtbl
	PF_clear_strtbl();

	snprintf(name, sizeof(name), "%s.dat", sv_progsname.string);
	progs = (dprograms_t *)FS_LoadHunkFile (name, &filesize);
	if (!progs)
		progs = (dprograms_t *)FS_LoadHunkFile ("qwprogs.dat", &filesize);
	if (!progs)
		progs = (dprograms_t *)FS_LoadHunkFile ("spprogs.dat", &filesize);
#ifdef WITH_NQPROGS
	pr_nqprogs = false;
	if (!progs || Cvar_Value("sv_forcenqprogs")) {
		progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat", &filesize);
		if (progs)
			pr_nqprogs = true;
	}
#endif
	if (!progs)
		SV_Error ("PR_LoadProgs: couldn't load progs.dat");
	Con_DPrintf ("Programs occupy %iK.\n", filesize/1024);

	// add prog crc to the serverinfo
	snprintf (num, sizeof(num), "%i", CRC_Block ((byte *)progs, filesize));
#ifdef USE_PR2
	Info_SetStar( &_localinfo_, "*qvm", "DAT" );
	//	Info_SetValueForStarKey (svs.info, "*qvm", "DAT", MAX_SERVERINFO_STRING);
#endif
	Info_SetValueForStarKey (svs.info, "*progs", num, MAX_SERVERINFO_STRING);

	// byte swap the header
	for (i = 0; i < (int) sizeof(*progs) / 4 ; i++)
		((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );

	if (progs->version != PROG_VERSION)
		SV_Error ("qwprogs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
	if (progs->crc != (pr_nqprogs ? NQ_PROGHEADER_CRC : PROGHEADER_CRC))
		SV_Error ("You must have the qwprogs.dat from QuakeWorld installed");

	pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
	pr_strings = (char *)progs + progs->ofs_strings;
	pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
	pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
	pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);

	num_prstr = 0;

	pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
	pr_globals = (float *)pr_global_struct;

	pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);

	// byte swap the lumps
	for (i = 0; i < progs->numstatements; i++)
	{
		pr_statements[i].op = LittleShort(pr_statements[i].op);
		pr_statements[i].a = LittleShort(pr_statements[i].a);
		pr_statements[i].b = LittleShort(pr_statements[i].b);
		pr_statements[i].c = LittleShort(pr_statements[i].c);
	}

	for (i = 0; i < progs->numfunctions; i++)
	{
		pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
		pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
		pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
		pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
		pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
		pr_functions[i].locals = LittleLong (pr_functions[i].locals);
	}

	for (i = 0; i < progs->numglobaldefs; i++)
	{
		pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
		pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
		pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
	}

	for (i = 0; i < progs->numfielddefs; i++)
	{
		pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
		if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
			SV_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
		pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
		pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
	}

	for (i = 0; i < progs->numglobals; i++)
		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);

#ifdef WITH_NQPROGS
	PR_InitPatchTables();
#endif

	// find optional QC-exported functions
	SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect");
	SpectatorThink = ED_FindFunctionOffset ("SpectatorThink");
	SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect");
	ChatMessage = ED_FindFunctionOffset ("ChatMessage");
	UserInfo_Changed = ED_FindFunctionOffset ("UserInfo_Changed");
	mod_ConsoleCmd = ED_FindFunctionOffset ("ConsoleCmd");
	mod_UserCmd = ED_FindFunctionOffset ("UserCmd");
	localinfoChanged = ED_FindFunctionOffset ("localinfoChanged");
	GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand");
	GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic");
	GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause");

	CheckKTPro ();
}
Beispiel #6
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.

This is only called from the SV_Map_f() function.
================
*/
void SV_SpawnServer (char *mapname, qbool devmap, char* entityfile)
{
	extern func_t ED_FindFunctionOffset (char *name);

	edict_t *ent;
	int i;

	extern cvar_t sv_loadentfiles, sv_loadentfiles_dir;
	char *entitystring;
	char oldmap[MAP_NAME_LEN];
	extern qbool	sv_allow_cheats;
	extern cvar_t	sv_cheats, sv_paused, sv_bigcoords;
#ifndef SERVERONLY
	extern void CL_ClearState (void);
#endif

	// store old map name
	snprintf (oldmap, MAP_NAME_LEN, "%s", sv.mapname);

	Con_DPrintf ("SpawnServer: %s\n",mapname);

#ifndef SERVERONLY
	// As client+server we do it here.
	// As serveronly we do it in NET_Init().
	NET_InitServer();
#endif

	SV_SaveSpawnparms ();
	SV_LoadAccounts();

#ifdef USE_PR2
	// remove bot clients
	for (i = 0; i < MAX_CLIENTS; i++)
	{
		if( sv_vm && svs.clients[i].isBot )
		{
			svs.clients[i].old_frags = 0;
			svs.clients[i].edict->v.frags = 0.0;
			svs.clients[i].name[0] = 0;
			svs.clients[i].state = cs_free;
			Info_RemoveAll(&svs.clients[i]._userinfo_ctx_);
			Info_RemoveAll(&svs.clients[i]._userinfoshort_ctx_);
			SV_FullClientUpdate(&svs.clients[i], &sv.reliable_datagram);
			svs.clients[i].isBot = 0;
		}
	}

#endif

	// Shutdown game.
	PR_GameShutDown();
	PR_UnLoadProgs();

	svs.spawncount++; // any partially connected client will be restarted

#ifndef SERVERONLY
	com_serveractive = false;
#endif
	sv.state = ss_dead;
	sv.paused = false;
	Cvar_SetROM(&sv_paused, "0");

	Host_ClearMemory();

#ifdef FTE_PEXT_FLOATCOORDS
	if (sv_bigcoords.value)
	{
		msg_coordsize = 4;
		msg_anglesize = 2;
	}
	else
	{
		msg_coordsize = 2;
		msg_anglesize = 1;
	}
#endif

	if ((int)coop.value)
		Cvar_Set (&deathmatch, "0");
	current_skill = (int) (skill.value + 0.5);
	if (current_skill < 0)
		current_skill = 0;
	Cvar_Set (&skill, va("%d", current_skill));
	if (current_skill > 3)
		current_skill = 3;

	if ((sv_cheats.value || devmap) && !sv_allow_cheats) {
		sv_allow_cheats = true;
		Info_SetValueForStarKey (svs.info, "*cheats", "ON", MAX_SERVERINFO_STRING);
	}
	else if ((!sv_cheats.value && !devmap) && sv_allow_cheats) {
		sv_allow_cheats = false;
		Info_SetValueForStarKey (svs.info, "*cheats", "", MAX_SERVERINFO_STRING);
	}


	// wipe the entire per-level structure
	// NOTE: this also set sv.mvdrecording to false, so calling SV_MVD_Record() at end of function
	memset (&sv, 0, sizeof(sv));


	sv.datagram.maxsize = sizeof(sv.datagram_buf);
	sv.datagram.data = sv.datagram_buf;
	sv.datagram.allowoverflow = true;

	sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
	sv.reliable_datagram.data = sv.reliable_datagram_buf;

	sv.multicast.maxsize = sizeof(sv.multicast_buf);
	sv.multicast.data = sv.multicast_buf;

	sv.signon.maxsize = sizeof(sv.signon_buffers[0]);
	sv.signon.data = sv.signon_buffers[0];
	sv.num_signon_buffers = 1;

	sv.time = 1.0;

	// load progs to get entity field count
	// which determines how big each edict is
	// and allocate edicts

	PR_LoadProgs ();
#ifdef WITH_NQPROGS
	PR_InitPatchTables();
#endif
	PR_InitProg();

	for (i = 0; i < MAX_EDICTS; i++)
	{
		ent = EDICT_NUM(i);
		ent->e = &sv.sv_edicts[i]; // assigning ->e field in each edict_t
		ent->e->entnum = i;
		ent->e->area.ed = ent; // yeah, pretty funny, but this help to find which edict_t own this area (link_t)
	}

	fofs_items2 = ED_FindFieldOffset ("items2"); // ZQ_ITEMS2 extension
	fofs_maxspeed = ED_FindFieldOffset ("maxspeed");
	fofs_gravity = ED_FindFieldOffset ("gravity");
	fofs_movement = ED_FindFieldOffset ("movement");
	fofs_vw_index = ED_FindFieldOffset ("vw_index");
	fofs_hideentity = ED_FindFieldOffset ("hideentity");
	fofs_trackent = ED_FindFieldOffset ("trackent");

	// find optional QC-exported functions.
	// we have it here, so we set it to NULL in case of PR2 progs.
	mod_SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect");
	mod_SpectatorThink = ED_FindFunctionOffset ("SpectatorThink");
	mod_SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect");
	mod_ChatMessage = ED_FindFunctionOffset ("ChatMessage");
	mod_UserInfo_Changed = ED_FindFunctionOffset ("UserInfo_Changed");
	mod_ConsoleCmd = ED_FindFunctionOffset ("ConsoleCmd");
	mod_UserCmd = ED_FindFunctionOffset ("UserCmd");
	mod_localinfoChanged = ED_FindFunctionOffset ("localinfoChanged");
	GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand");
	GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic");
	GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause");

	// leave slots at start for clients only
	sv.num_edicts = MAX_CLIENTS+1;
	for (i=0 ; i<MAX_CLIENTS ; i++)
	{
		ent = EDICT_NUM(i+1);
		// restore client name.
		ent->v.netname = PR_SetString(svs.clients[i].name);
		// reserve edict.
		svs.clients[i].edict = ent;
		//ZOID - make sure we update frags right
		svs.clients[i].old_frags = 0;
	}

	// fill sv.mapname and sv.modelname with new map name
	strlcpy (sv.mapname, mapname, sizeof(sv.mapname));
	snprintf (sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", sv.mapname);
#ifndef SERVERONLY
	// set cvar
	Cvar_ForceSet (&host_mapname, mapname);
#endif

	if (!(sv.worldmodel = CM_LoadMap (sv.modelname, false, &sv.map_checksum, &sv.map_checksum2))) // true if bad map
	{
		Con_Printf ("Cant load map %s, falling back to %s\n", mapname, oldmap);

		// fill mapname, sv.mapname and sv.modelname with old map name
		strlcpy (sv.mapname, oldmap, sizeof(sv.mapname)); 
		snprintf (sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", sv.mapname);
		mapname = oldmap;

		// and re-load old map
		sv.worldmodel = CM_LoadMap (sv.modelname, false, &sv.map_checksum, &sv.map_checksum2);

		// this should never happen
		if (!sv.worldmodel)
			SV_Error ("CM_LoadMap: bad map");
	}
	
	sv.map_checksum2 = Com_TranslateMapChecksum (sv.mapname, sv.map_checksum2);

	SV_ClearWorld (); // clear physics interaction links

#ifdef USE_PR2
	if ( sv_vm )
	{
		sv.sound_precache[0] = "";
		sv.model_precache[0] = "";
	}
	else
#endif

	{
		sv.sound_precache[0] = pr_strings;
		sv.model_precache[0] = pr_strings;
	}
	sv.model_precache[1] = sv.modelname;
	sv.models[1] = sv.worldmodel;
	for (i=1 ; i< CM_NumInlineModels() ; i++)
	{
		sv.model_precache[1+i] = localmodels[i];
		sv.models[i+1] =  CM_InlineModel (localmodels[i]);
	}

	//check player/eyes models for hacks
	sv.model_player_checksum = SV_CheckModel("progs/player.mdl");
	sv.model_newplayer_checksum = SV_CheckModel("progs/newplayer.mdl");
	sv.eyes_player_checksum = SV_CheckModel("progs/eyes.mdl");

	//
	// spawn the rest of the entities on the map
	//

	// precache and static commands can be issued during
	// map initialization
	sv.state = ss_loading;
#ifndef SERVERONLY
	com_serveractive = true;
#endif

	ent = EDICT_NUM(0);
	ent->e->free = false;
	ent->v.model = PR_SetString(sv.modelname);
	ent->v.modelindex = 1;		// world model
	ent->v.solid = SOLID_BSP;
	ent->v.movetype = MOVETYPE_PUSH;

	// information about the server
	ent->v.netname = PR_SetString(VersionStringFull());
	ent->v.targetname = PR_SetString(SERVER_NAME);
	ent->v.impulse = VERSION_NUM;
	ent->v.items = pr_numbuiltins - 1;

	PR_GLOBAL(mapname) = PR_SetString(sv.mapname);
	// serverflags are for cross level information (sigils)
	PR_GLOBAL(serverflags) = svs.serverflags;
	if (pr_nqprogs)
	{
		pr_globals[35] = deathmatch.value;
		pr_globals[36] = coop.value;
		pr_globals[37] = teamplay.value;
		NQP_Reset ();
	}

	if (pr_nqprogs)
	{
		// register the cvars that NetQuake provides for mod use
		const char **var, *nqcvars[] = {"gamecfg", "scratch1", "scratch2", "scratch3", "scratch4",
			"saved1", "saved2", "saved3", "saved4", "savedgamecfg", "temp1", NULL};
		for (var = nqcvars; *var; var++)
			Cvar_Create((char *)/*stupid const warning*/ *var, "0", 0);
	}

	// run the frame start qc function to let progs check cvars
	if (!pr_nqprogs)
		SV_ProgStartFrame ();

	// ********* External Entity support (.ent file(s) in gamedir/maps) pinched from ZQuake *********
	// load and spawn all other entities
	entitystring = NULL;
	if ((int)sv_loadentfiles.value)
	{
		char ent_path[1024] = {0};

		if (!entityfile || !entityfile[0])
			entityfile = sv.mapname;

		// first try maps/sv_loadentfiles_dir/
		if (sv_loadentfiles_dir.string[0])
		{
			snprintf(ent_path, sizeof(ent_path), "maps/%s/%s.ent", sv_loadentfiles_dir.string, entityfile);
			entitystring = (char *) FS_LoadHunkFile(ent_path, NULL);
		}

		// try maps/ if not loaded yet.
		if (!entitystring)
		{
			snprintf(ent_path, sizeof(ent_path), "maps/%s.ent", entityfile);
			entitystring = (char *) FS_LoadHunkFile(ent_path, NULL);
		}

		if (entitystring) {
			Con_DPrintf ("Using entfile %s\n", ent_path);
		}
	}

	if (!entitystring) {
		entitystring = CM_EntityString();
	}
	
	PR_LoadEnts(entitystring);
	// ********* End of External Entity support code *********

	// look up some model indexes for specialized message compression
	SV_FindModelNumbers ();

	// all spawning is completed, any further precache statements
	// or prog writes to the signon message are errors
	sv.state = ss_active;

	// run two frames to allow everything to settle
	SV_Physics ();
	sv.time += 0.1;
	SV_Physics ();
	sv.time += 0.1;
	sv.old_time = sv.time;

	// save movement vars
	SV_SetMoveVars();

	// create a baseline for more efficient communications
	SV_CreateBaseline ();
	sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize;

	Info_SetValueForKey (svs.info, "map", sv.mapname, MAX_SERVERINFO_STRING);

	// calltimeofday.
	{
		extern void PF_calltimeofday (void);
		pr_global_struct->time = sv.time;
		pr_global_struct->self = 0;

		PF_calltimeofday();
	}

	Con_DPrintf ("Server spawned.\n");

	// we change map - clear whole demo struct and sent initial state to all dest if any (for QTV only I thought)
	SV_MVD_Record(NULL, true);

#ifndef SERVERONLY
	CL_ClearState ();
#endif
}
Beispiel #7
0
/*
===============
PR_LoadProgs
===============
*/
void PR_LoadProgs (void)
{
	int	i;
	char	num[32];
	static int lumpsize[6] = { sizeof(dstatement_t), sizeof(ddef_t),
		sizeof(ddef_t), sizeof(dfunction_t), 4, 4 };
	int	filesize = 0;
	const char	*progsname;

	progs = NULL;

	// decide whether to load qwprogs.dat, progs.dat or spprogs.dat

#ifdef WITH_NQPROGS
	if (Cvar_Value("sv_forcenqprogs"))
		goto use_progs;
#endif

	if (!deathmatch.value)
	{
		if (Q_stricmp(com_gamedirfile, "qw") && 
			strcmp(com_gamedirfile, ""))
		{
			// if we're using a custom mod, anything
			// in gamedir is preferred to stock *progs.dat
			qbool check;
			check = FS_FindFile ("spprogs.dat");
			if (check && file_from_gamedir)
				goto use_spprogs;
#ifdef WITH_NQPROGS
			check = FS_FindFile ("progs.dat");
			if (check && file_from_gamedir)
				goto use_progs;
#endif
			check = FS_FindFile ("qwprogs.dat");
			if (check && file_from_gamedir)
				goto use_qwprogs;
		}

use_spprogs:
		progs = (dprograms_t *) FS_LoadHunkFile ("spprogs.dat");
		progsname = "spprogs.dat";
		pr_nqprogs = false;

		if (!progs) {
#ifdef WITH_NQPROGS
use_progs:
			progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat");
			progsname = "progs.dat";
			pr_nqprogs = true;
		}
#endif
		if (!progs) {
use_qwprogs:
			progs = (dprograms_t *)FS_LoadHunkFile ("qwprogs.dat");
			progsname = "qwprogs.dat";
			pr_nqprogs = false;
		}
	}
	else	// deathmatch
	{
		if (Q_stricmp(com_gamedirfile, "qw") && 
			strcmp(com_gamedirfile, ""))
		{
			qbool check;
			check = FS_FindFile ("qwprogs.dat");
			if (check && file_from_gamedir)
				goto dm_use_qwprogs;
#ifdef WITH_NQPROGS
			check = FS_FindFile ("progs.dat");
			if (check && file_from_gamedir)
				goto dm_use_progs;
#endif
		}

dm_use_qwprogs:
		progs = (dprograms_t *) FS_LoadHunkFile ("qwprogs.dat");
		progsname = "qwprogs.dat";
		pr_nqprogs = false;

		if (!progs) {
#ifdef WITH_NQPROGS
dm_use_progs:
			progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat");
			progsname = "progs.dat";
			pr_nqprogs = true;
		}
#endif
	}

	if (!progs)
		Host_Error ("PR_LoadProgs: couldn't load progs.dat");

	filesize = fs_filesize;

	if (filesize < (int)sizeof(*progs))
		Host_Error("%s is corrupt", progsname);

	Com_DPrintf ("Using %s (%i bytes).\n", progsname, filesize);

// add prog crc to the serverinfo
	sprintf (num, "%i", CRC_Block ((byte *)progs, filesize));
	svs.info.set("*progs", num);

// byte swap the header
	for (i = 0; i < sizeof(*progs)/4; i++)
		((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );		

	if (progs->version != PROG_VERSION)
		Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
	if (progs->crc != (pr_nqprogs ? NQ_PROGHEADER_CRC : PROGHEADER_CRC))
		Host_Error ("You must have the qwprogs.dat from QuakeWorld installed");

// check lump offsets and sizes
	for (i = 0; i < 6; i ++) {
		if (((int *)progs)[i*2 + 2] < sizeof(*progs)
			|| ((int *)progs)[i*2 + 2] + ((int *)progs)[i*2 + 3]*lumpsize[i] > filesize)
		Host_Error("progs.dat is corrupt");
	}

	pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
	pr_strings = (char *)progs + progs->ofs_strings;
	pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
	pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
	pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
	pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);

	pr_globals = (float *)pr_global_struct;

	PR_InitStrings ();

	pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
	
// byte swap the lumps
	for (i=0 ; i<progs->numstatements ; i++)
	{
		pr_statements[i].op = LittleShort(pr_statements[i].op);
		pr_statements[i].a = LittleShort(pr_statements[i].a);
		pr_statements[i].b = LittleShort(pr_statements[i].b);
		pr_statements[i].c = LittleShort(pr_statements[i].c);
	}

	for (i=0 ; i<progs->numfunctions; i++)
	{
	pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
	pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
	pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
	pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
	pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
	pr_functions[i].locals = LittleLong (pr_functions[i].locals);
	}	

	for (i=0 ; i<progs->numglobaldefs ; i++)
	{
		pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
		pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs);
		pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
	}

	for (i=0 ; i<progs->numfielddefs ; i++)
	{
		pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
		if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
			Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
		pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
		pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
	}


	for (i=0 ; i<progs->numglobals ; i++)
		((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);


#ifdef WITH_NQPROGS
	if (pr_nqprogs) {
		memcpy (pr_globaloffsetpatch, pr_globaloffsetpatch_nq, sizeof(pr_globaloffsetpatch));
		for (i = 0; i < 106; i++) {
			pr_fieldoffsetpatch[i] = (i < 8) ? i : (i < 25) ? i + 1 :
				(i < 28) ? i + (102 - 25) : (i < 73) ? i - 2 :
				(i < 74) ? i + (105 - 73) : (i < 105) ? i - 3 : /* (i == 105) */ 8;
		}

		for (i=0 ; i<progs->numfielddefs ; i++)
			pr_fielddefs[i].ofs = PR_FIELDOFS(pr_fielddefs[i].ofs);
	}
	else
	{
		memset (pr_globaloffsetpatch, 0, sizeof(pr_globaloffsetpatch));

		for (i = 0; i < 106; i++)
			pr_fieldoffsetpatch[i] = i;
	}
#endif

	// find optional QC-exported functions
	SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect");
	SpectatorThink = ED_FindFunctionOffset ("SpectatorThink");
	SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect");
	GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand");
	GE_ConsoleCommand = ED_FindFunctionOffset ("GE_ConsoleCommand");
	GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic");
	GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause");

	// find optional QC-exported fields
	fofs_maxspeed = ED_FindFieldOffset ("maxspeed");
	fofs_gravity = ED_FindFieldOffset ("gravity");
	fofs_items2 = ED_FindFieldOffset ("items2");
	fofs_movement = ED_FindFieldOffset ("movement");
	fofs_vw_index = ED_FindFieldOffset ("vw_index");
	for (i = 3; i < 8; i++)
		fofs_buttonX[i-3] = ED_FindFieldOffset(va("button%i", i));

	// reset stuff like ZQ_CLIENTCOMMAND, progs must enable it explicitly
	memset (&pr_ext_enabled, sizeof(pr_ext_enabled), 0);

	PR_Exec_Init ();
}
Beispiel #8
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.

This is only called from the SV_Map_f() function.
================
*/
void SV_SpawnServer (char *mapname, qbool devmap)
{
	char *entitystring;
	edict_t *ent;
	int i;
	extern qbool sv_allow_cheats;
	extern cvar_t sv_cheats;

	Com_DPrintf ("SpawnServer: %s\n", mapname);

	NET_InitServer();

	SV_SaveSpawnparms ();

	svs.spawncount++; // any partially connected client will be restarted

	sv.state = ss_dead;
	com_serveractive = false;
	Cvar_ForceSet (&sv_paused, "0");

	Host_ClearMemory();

	if (deathmatch.value)
		Cvar_Set (&coop, "0");
	current_skill = (int)(skill.value + 0.5);
	if (current_skill < 0)
		current_skill = 0;
	if (current_skill > 3)
		current_skill = 3;
	Cvar_Set (&skill, va("%d", (int)current_skill));

	if ((sv_cheats.value || devmap) && !sv_allow_cheats) {
		sv_allow_cheats = true;
		Info_SetValueForStarKey (svs.info, "*cheats", "ON", MAX_SERVERINFO_STRING);
	} else if ((!sv_cheats.value && !devmap) && sv_allow_cheats) {
		sv_allow_cheats = false;
		Info_SetValueForStarKey (svs.info, "*cheats", "", MAX_SERVERINFO_STRING);
	}

	// wipe the entire per-level structure
	memset (&sv, 0, sizeof(sv));

	SZ_Init (&sv.datagram, sv.datagram_buf, sizeof(sv.datagram_buf));
	sv.datagram.allowoverflow = true;

	SZ_Init (&sv.reliable_datagram, sv.reliable_datagram_buf, sizeof(sv.reliable_datagram_buf));

	SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));

	SZ_Init (&sv.signon, sv.signon_buffers[0], sizeof(sv.signon_buffers[0]));
	sv.num_signon_buffers = 1;

	// load progs to get entity field count
	// which determines how big each edict is
	PR_LoadProgs ();

	// allocate edicts
	sv.edicts = (edict_t *) Hunk_AllocName (SV_MAX_EDICTS*pr_edict_size, "edicts");

	// leave slots at start for clients only
	sv.num_edicts = MAX_CLIENTS+1;
	for (i = 0; i < MAX_CLIENTS; i++) {
		ent = EDICT_NUM(i+1);
		svs.clients[i].edict = ent;
		svs.clients[i].old_frags = 0; //ZOID - make sure we update frags right
	}

	sv.time = 1.0;

#ifndef SERVERONLY
	{
		void R_PreMapLoad (char *mapname);
		R_PreMapLoad (mapname);
	}
#endif

	strlcpy (sv.mapname, mapname, sizeof(sv.mapname));
	Cvar_ForceSet (&host_mapname, mapname);
	snprintf (sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", mapname);

	sv.worldmodel = CM_LoadMap (sv.modelname, false, &sv.map_checksum, &sv.map_checksum2);

	// clear physics interaction links
	SV_ClearWorld ();

	sv.sound_precache[0] = pr_strings;

	sv.model_precache[0] = pr_strings;
	sv.model_precache[1] = sv.modelname;
	sv.models[1] = sv.worldmodel;
	for (i = 1; i < CM_NumInlineModels(); i++) {
		sv.model_precache[1+i] = localmodels[i];
		sv.models[i + 1] = CM_InlineModel (localmodels[i]);
	}

	//check player/eyes models for hacks
	sv.model_player_checksum = SV_CheckModel("progs/player.mdl");
	sv.eyes_player_checksum = SV_CheckModel("progs/eyes.mdl");

	// spawn the rest of the entities on the map

	// precache and static commands can be issued during map initialization
	sv.state = ss_loading;
	com_serveractive = true;

	ent = EDICT_NUM(0);
	ent->free = false;
	ent->v.model = PR_SetString(sv.modelname);
	ent->v.modelindex = 1;		// world model
	ent->v.solid = SOLID_BSP;
	ent->v.movetype = MOVETYPE_PUSH;

	pr_global_struct->mapname = PR_SetString(sv.mapname);
	// serverflags are for cross level information (sigils)
	pr_global_struct->serverflags = svs.serverflags;

	// run the frame start qc function to let progs check cvars
	SV_ProgStartFrame ();

	// load and spawn all other entities
	entitystring = NULL;
	if ((int) sv_loadentfiles.value) {
		int filesize;
		entitystring = (char *)FS_LoadHunkFile (va("maps/%s.ent", sv.mapname), &filesize);
		if (entitystring) {
			Com_DPrintf ("Using entfile maps/%s.ent\n", sv.mapname);
			Info_SetValueForStarKey (svs.info, "*entfile", va("%i",
				CRC_Block((byte *)entitystring, filesize)), MAX_SERVERINFO_STRING);
		}
	}

	if (!entitystring) {
		Info_SetValueForStarKey (svs.info,  "*entfile", "", MAX_SERVERINFO_STRING);
		entitystring = CM_EntityString();
	}
	ED_LoadFromFile (entitystring);

	// look up some model indexes for specialized message compression
	SV_FindModelNumbers ();

	// all spawning is completed, any further precache statements
	// or prog writes to the signon message are errors
	sv.state = ss_active;

	// run two frames to allow everything to settle
	SV_Physics ();
	sv.time += 0.1;
	SV_Physics ();
	sv.time += 0.1;
	sv.old_time = sv.time;

	// save movement vars
	SV_SetMoveVars();

	// create a baseline for more efficient communications
	SV_CreateBaseline ();
	sv.signon_buffer_size[sv.num_signon_buffers - 1] = sv.signon.cursize;

	Info_SetValueForKey (svs.info, "map", sv.mapname, MAX_SERVERINFO_STRING);
	Com_DPrintf ("Server spawned.\n");

#ifndef SERVERONLY
	if (!dedicated)
	{
		void CL_ClearState (void);
		CL_ClearState ();
	}
#endif
}