Exemplo n.º 1
0
void Host_ServerFrame (void)
{
// run the world state
    pr_global_struct->frametime = host_frametime;

// set the time and clear the general datagram
    SV_ClearDatagram ();

// check for new clients
    SV_CheckForNewClients ();

// read client messages
    SV_RunClients ();

// move things around and think
// always pause in single player if in console or menus
    if (!SV_IsPaused ())
    {
        SV_Physics ();
        // Vladimir CondSleep (0);
    }

// send all messages to the clients
    SV_SendClientMessages ();
}
Exemplo n.º 2
0
void
Host_ServerFrame(void)
{
    /* run the world state */
    pr_global_struct->frametime = host_frametime;

    /* set the time and clear the general datagram */
    SV_ClearDatagram();

    /* check for new clients */
    SV_CheckForNewClients();

    /* read client messages */
    SV_RunClients();

    /*
     * Move things around and think. Always pause in single player if in
     * console or menus
     */
    if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game))
	SV_Physics();

    /* send all messages to the clients */
    SV_SendClientMessages();
}
Exemplo n.º 3
0
/*
==================
Host_ServerFrame

==================
*/
void Host_ServerFrame (void)
{
// JPG 3.00 - stuff the port number into the server console once every minute
	static double port_time = 0;

	if (port_time > sv.time + 1 || port_time < sv.time - 60)
	{
		port_time = sv.time;
		Cmd_ExecuteString(va("port %d\n", net_hostport), src_command);
	}

// run the world state
	pr_global_struct->frametime = host_frametime;

// set the time and clear the general datagram
	SV_ClearDatagram ();

// check for new clients
	SV_CheckForNewClients ();

// read client messages
	SV_RunClients ();

// move things around and think
	if (!sv.paused)
		SV_Physics ();

// send all messages to the clients
	SV_SendClientMessages ();
}
Exemplo n.º 4
0
void Host_ServerFrame (void)
{

	static double port_time = 0;

	if (port_time > sv.time + 1 || port_time < sv.time - 60)
	{
		port_time = sv.time;
		Cmd_ExecuteString(va("port %d\n", net_hostport), src_command);
	}

// run the world state
	pr_global_struct->frametime = host_frametime;

// set the time and clear the general datagram
	SV_ClearDatagram ();

// check for new clients
	SV_CheckForNewClients ();

// read client messages
	SV_RunClients ();

// move things around and think
// always pause in single player if in console or menus
	if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
		SV_Physics ();

// send all messages to the clients
	SV_SendClientMessages ();
}
Exemplo n.º 5
0
/*
=================
SV_RunGameFrame
=================
*/
void SV_RunGameFrame( void )
{
	if( !SV_IsSimulating( )) return;

	SV_Physics();

	sv.time += host.frametime;
}
Exemplo n.º 6
0
/*
==================
SV_Frame

==================
*/
void SV_Frame (float time)
{
	static double	start, end;

	start = Sys_DoubleTime ();
	svs.stats.idle += start - end;

// keep the random time dependent
	rand ();

// decide the simulation time
	realtime += time;
	sv.time += time;

// check timeouts
	SV_CheckTimeouts ();

// toggle the log buffer if full
	SV_CheckLog ();

// move autonomous things around if enough time has passed
	SV_Physics ();

// get packets
	SV_ReadPackets ();

// check for commands typed to the host
	SV_GetConsoleCommands ();

// process console commands
	Cbuf_Execute ();

	SV_CheckVars ();

// send messages back to the clients that had packets read this frame
	SV_SendClientMessages ();

// send a heartbeat to the master if needed
	Master_Heartbeat ();

// collect timing statistics
	end = Sys_DoubleTime ();
	svs.stats.active += end-start;
	if (++svs.stats.count == STATFRAMES)
	{
		svs.stats.latched_active = svs.stats.active;
		svs.stats.latched_idle = svs.stats.idle;
		svs.stats.latched_packets = svs.stats.packets;
		svs.stats.active = 0;
		svs.stats.idle = 0;
		svs.stats.packets = 0;
		svs.stats.count = 0;
	}
}
Exemplo n.º 7
0
void _Host_ServerFrame (void)
{
// run the world state	
	pr_global_struct->frametime = host_frametime;

// read client messages
	SV_RunClients ();
	
// move things around and think
// always pause in single player if in console or menus
	if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
		SV_Physics ();
}
Exemplo n.º 8
0
void _Host_ServerFrame (void)
{
// run the world state
    pr_global_struct->frametime = host_frametime;

// read client messages
    SV_RunClients ();

// move things around and think
// always pause in single player if in console or menus
    if (!SV_IsPaused ())
        SV_Physics ();
}
Exemplo n.º 9
0
/*
==================
Host_ServerFrame
==================
*/
void Host_ServerFrame (void)
{
	int		i, active; //johnfitz
	edict_t	*ent; //johnfitz

// run the world state
	pr_global_struct->frametime = host_frametime;

// set the time and clear the general datagram
	SV_ClearDatagram ();

// check for new clients
	SV_CheckForNewClients ();

// read client messages
	SV_RunClients ();

// move things around and think
// always pause in single player if in console or menus
	if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
		SV_Physics ();

//johnfitz -- devstats
	if (cls.signon == SIGNONS)
	{
		for (i=0, active=0; i<sv.num_edicts; i++)
		{
			ent = EDICT_NUM(i);
			if (!ent->free)
				active++;
		}
		if (active > 600 && dev_peakstats.edicts <= 600)
			Con_DWarning ("%i edicts exceeds standard limit of 600.\n", active);
		dev_stats.edicts = active;
		dev_peakstats.edicts = q_max(active, dev_peakstats.edicts);
	}
//johnfitz

// send all messages to the clients
	SV_SendClientMessages ();
}
Exemplo n.º 10
0
void Host_Main(void)
{
	double time1 = 0;
	double time2 = 0;
	double time3 = 0;
	double cl_timer = 0, sv_timer = 0;
	double clframetime, deltacleantime, olddirtytime, dirtytime;
	double wait;
	int pass1, pass2, pass3, i;
	char vabuf[1024];
	qboolean playing;

	Host_Init();

	realtime = 0;
	host_dirtytime = Sys_DirtyTime();
	for (;;)
	{
		if (setjmp(host_abortframe))
		{
			SCR_ClearLoadingScreen(false);
			continue;			// something bad happened, or the server disconnected
		}

		olddirtytime = host_dirtytime;
		dirtytime = Sys_DirtyTime();
		deltacleantime = dirtytime - olddirtytime;
		if (deltacleantime < 0)
		{
			// warn if it's significant
			if (deltacleantime < -0.01)
				Con_Printf("Host_Mingled: time stepped backwards (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime);
			deltacleantime = 0;
		}
		else if (deltacleantime >= 1800)
		{
			Con_Printf("Host_Mingled: time stepped forward (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime);
			deltacleantime = 0;
		}
		realtime += deltacleantime;
		host_dirtytime = dirtytime;

		cl_timer += deltacleantime;
		sv_timer += deltacleantime;

		if (!svs.threaded)
		{
			svs.perf_acc_realtime += deltacleantime;

			// Look for clients who have spawned
			playing = false;
			for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
				if(host_client->begun)
					if(host_client->netconnection)
						playing = true;
			if(sv.time < 10)
			{
				// don't accumulate time for the first 10 seconds of a match
				// so things can settle
				svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
			}
			else if(svs.perf_acc_realtime > 5)
			{
				svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime;
				svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime;
				if(svs.perf_acc_offset_samples > 0)
				{
					svs.perf_offset_max = svs.perf_acc_offset_max;
					svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples;
					svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg);
				}
				if(svs.perf_lost > 0 && developer_extra.integer)
					if(playing) // only complain if anyone is looking
						Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
				svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0;
			}
		}

		if (slowmo.value < 0.00001 && slowmo.value != 0)
			Cvar_SetValue("slowmo", 0);
		if (host_framerate.value < 0.00001 && host_framerate.value != 0)
			Cvar_SetValue("host_framerate", 0);

		// keep the random time dependent, but not when playing demos/benchmarking
		if(!*sv_random_seed.string && !cls.demoplayback)
			rand();

		// get new key events
		Key_EventQueue_Unblock();
		SndSys_SendKeyEvents();
		Sys_SendKeyEvents();

		NetConn_UpdateSockets();

		Log_DestBuffer_Flush();

		// receive packets on each main loop iteration, as the main loop may
		// be undersleeping due to select() detecting a new packet
		if (sv.active && !svs.threaded)
			NetConn_ServerFrame();

		Curl_Run();

		// check for commands typed to the host
		Host_GetConsoleCommands();

		// when a server is running we only execute console commands on server frames
		// (this mainly allows frikbot .way config files to work properly by staying in sync with the server qc)
		// otherwise we execute them on client frames
		if (sv.active ? sv_timer > 0 : cl_timer > 0)
		{
			// process console commands
//			R_TimeReport("preconsole");
			CL_VM_PreventInformationLeaks();
			Cbuf_Frame();
//			R_TimeReport("console");
		}

		//Con_Printf("%6.0f %6.0f\n", cl_timer * 1000000.0, sv_timer * 1000000.0);

		// if the accumulators haven't become positive yet, wait a while
		if (cls.state == ca_dedicated)
			wait = sv_timer * -1000000.0;
		else if (!sv.active || svs.threaded)
			wait = cl_timer * -1000000.0;
		else
			wait = max(cl_timer, sv_timer) * -1000000.0;

		if (!cls.timedemo && wait >= 1)
		{
			double time0, delta;

			if(host_maxwait.value <= 0)
				wait = min(wait, 1000000.0);
			else
				wait = min(wait, host_maxwait.value * 1000.0);
			if(wait < 1)
				wait = 1; // because we cast to int

			time0 = Sys_DirtyTime();
			if (sv_checkforpacketsduringsleep.integer && !sys_usenoclockbutbenchmark.integer && !svs.threaded) {
				NetConn_SleepMicroseconds((int)wait);
				if (cls.state != ca_dedicated)
					NetConn_ClientFrame(); // helps server browser get good ping values
				// TODO can we do the same for ServerFrame? Probably not.
			}
			else
				Sys_Sleep((int)wait);
			delta = Sys_DirtyTime() - time0;
			if (delta < 0 || delta >= 1800) delta = 0;
			if (!svs.threaded)
				svs.perf_acc_sleeptime += delta;
//			R_TimeReport("sleep");
			continue;
		}

		// limit the frametime steps to no more than 100ms each
		if (cl_timer > 0.1)
			cl_timer = 0.1;
		if (sv_timer > 0.1)
		{
			if (!svs.threaded)
				svs.perf_acc_lost += (sv_timer - 0.1);
			sv_timer = 0.1;
		}

		R_TimeReport("---");

	//-------------------
	//
	// server operations
	//
	//-------------------

		// limit the frametime steps to no more than 100ms each
		if (sv.active && sv_timer > 0 && !svs.threaded)
		{
			// execute one or more server frames, with an upper limit on how much
			// execution time to spend on server frames to avoid freezing the game if
			// the server is overloaded, this execution time limit means the game will
			// slow down if the server is taking too long.
			int framecount, framelimit = 1;
			double advancetime, aborttime = 0;
			float offset;
			prvm_prog_t *prog = SVVM_prog;

			// run the world state
			// don't allow simulation to run too fast or too slow or logic glitches can occur

			// stop running server frames if the wall time reaches this value
			if (sys_ticrate.value <= 0)
				advancetime = sv_timer;
			else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer)
			{
				// synchronize to the client frametime, but no less than 10ms and no more than 100ms
				advancetime = bound(0.01, cl_timer, 0.1);
			}
			else
			{
				advancetime = sys_ticrate.value;
				// listen servers can run multiple server frames per client frame
				framelimit = cl_maxphysicsframesperserverframe.integer;
				aborttime = Sys_DirtyTime() + 0.1;
			}
			if(slowmo.value > 0 && slowmo.value < 1)
				advancetime = min(advancetime, 0.1 / slowmo.value);
			else
				advancetime = min(advancetime, 0.1);

			if(advancetime > 0)
			{
				offset = Sys_DirtyTime() - dirtytime;if (offset < 0 || offset >= 1800) offset = 0;
				offset += sv_timer;
				++svs.perf_acc_offset_samples;
				svs.perf_acc_offset += offset;
				svs.perf_acc_offset_squared += offset * offset;
				if(svs.perf_acc_offset_max < offset)
					svs.perf_acc_offset_max = offset;
			}

			// only advance time if not paused
			// the game also pauses in singleplayer when menu or console is used
			sv.frametime = advancetime * slowmo.value;
			if (host_framerate.value)
				sv.frametime = host_framerate.value;
			if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
				sv.frametime = 0;

			for (framecount = 0;framecount < framelimit && sv_timer > 0;framecount++)
			{
				sv_timer -= advancetime;

				// move things around and think unless paused
				if (sv.frametime)
					SV_Physics();

				// if this server frame took too long, break out of the loop
				if (framelimit > 1 && Sys_DirtyTime() >= aborttime)
					break;
			}
			R_TimeReport("serverphysics");

			// send all messages to the clients
			SV_SendClientMessages();

			if (sv.paused == 1 && realtime > sv.pausedstart && sv.pausedstart > 0) {
				prog->globals.fp[OFS_PARM0] = realtime - sv.pausedstart;
				PRVM_serverglobalfloat(time) = sv.time;
				prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing");
			}

			// send an heartbeat if enough time has passed since the last one
			NetConn_Heartbeat(0);
			R_TimeReport("servernetwork");
		}
		else if (!svs.threaded)
		{
			// don't let r_speeds display jump around
			R_TimeReport("serverphysics");
			R_TimeReport("servernetwork");
		}

	//-------------------
	//
	// client operations
	//
	//-------------------

		if (cls.state != ca_dedicated && (cl_timer > 0 || cls.timedemo || ((vid_activewindow ? cl_maxfps : cl_maxidlefps).value < 1)))
		{
			R_TimeReport("---");
			Collision_Cache_NewFrame();
			R_TimeReport("photoncache");
			// decide the simulation time
			if (cls.capturevideo.active)
			{
				//***
				if (cls.capturevideo.realtime)
					clframetime = cl.realframetime = max(cl_timer, 1.0 / cls.capturevideo.framerate);
				else
				{
					clframetime = 1.0 / cls.capturevideo.framerate;
					cl.realframetime = max(cl_timer, clframetime);
				}
			}
			else if (vid_activewindow && cl_maxfps.value >= 1 && !cls.timedemo)
			{
				clframetime = cl.realframetime = max(cl_timer, 1.0 / cl_maxfps.value);
				// when running slow, we need to sleep to keep input responsive
				wait = bound(0, cl_maxfps_alwayssleep.value * 1000, 100000);
				if (wait > 0)
					Sys_Sleep((int)wait);
			}
			else if (!vid_activewindow && cl_maxidlefps.value >= 1 && !cls.timedemo)
				clframetime = cl.realframetime = max(cl_timer, 1.0 / cl_maxidlefps.value);
			else
				clframetime = cl.realframetime = cl_timer;

			// apply slowmo scaling
			clframetime *= cl.movevars_timescale;
			// scale playback speed of demos by slowmo cvar
			if (cls.demoplayback)
			{
				clframetime *= slowmo.value;
				// if demo playback is paused, don't advance time at all
				if (cls.demopaused)
					clframetime = 0;
			}
			else
			{
				// host_framerate overrides all else
				if (host_framerate.value)
					clframetime = host_framerate.value;

				if (cl.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused)))
					clframetime = 0;
			}

			if (cls.timedemo)
				clframetime = cl.realframetime = cl_timer;

			// deduct the frame time from the accumulator
			cl_timer -= cl.realframetime;

			cl.oldtime = cl.time;
			cl.time += clframetime;

			// update video
			if (host_speeds.integer)
				time1 = Sys_DirtyTime();
			R_TimeReport("pre-input");

			// Collect input into cmd
			CL_Input();

			R_TimeReport("input");

			// check for new packets
			NetConn_ClientFrame();

			// read a new frame from a demo if needed
			CL_ReadDemoMessage();
			R_TimeReport("clientnetwork");

			// now that packets have been read, send input to server
			CL_SendMove();
			R_TimeReport("sendmove");

			// update client world (interpolate entities, create trails, etc)
			CL_UpdateWorld();
			R_TimeReport("lerpworld");

			CL_Video_Frame();

			R_TimeReport("client");

			CL_UpdateScreen();
			CL_MeshEntities_Reset();
			R_TimeReport("render");

			if (host_speeds.integer)
				time2 = Sys_DirtyTime();

			// update audio
			if(cl.csqc_usecsqclistener)
			{
				S_Update(&cl.csqc_listenermatrix);
				cl.csqc_usecsqclistener = false;
			}
			else
				S_Update(&r_refdef.view.matrix);

			CDAudio_Update();
			R_TimeReport("audio");

			// reset gathering of mouse input
			in_mouse_x = in_mouse_y = 0;

			if (host_speeds.integer)
			{
				pass1 = (int)((time1 - time3)*1000000);
				time3 = Sys_DirtyTime();
				pass2 = (int)((time2 - time1)*1000000);
				pass3 = (int)((time3 - time2)*1000000);
				Con_Printf("%6ius total %6ius server %6ius gfx %6ius snd\n",
							pass1+pass2+pass3, pass1, pass2, pass3);
			}
		}

#if MEMPARANOIA
		Mem_CheckSentinelsGlobal();
#else
		if (developer_memorydebug.integer)
			Mem_CheckSentinelsGlobal();
#endif

		// if there is some time remaining from this frame, reset the timers
		if (cl_timer >= 0)
			cl_timer = 0;
		if (sv_timer >= 0)
		{
			if (!svs.threaded)
				svs.perf_acc_lost += sv_timer;
			sv_timer = 0;
		}

		host_framecount++;
	}
}
Exemplo n.º 11
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
}
Exemplo n.º 12
0
/*
================
SV_ActivateServer

activate server on changed map, run physics
================
*/
void SV_ActivateServer( void )
{
	int	i, numFrames;

	if( !svs.initialized )
		return;

	// custom muzzleflashes
	pfnPrecacheModel( "sprites/muzzleflash.spr" );
	pfnPrecacheModel( "sprites/muzzleflash1.spr" );
	pfnPrecacheModel( "sprites/muzzleflash2.spr" );
	pfnPrecacheModel( "sprites/muzzleflash3.spr" );

	// rocket flare
	pfnPrecacheModel( "sprites/animglow01.spr" );

	// ricochet sprite
	pfnPrecacheModel( "sprites/richo1.spr" );

	// Activate the DLL server code
	svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.numEntities, svgame.globals->maxClients );

	// create a baseline for more efficient communications
	SV_CreateBaseline();

	// check and count all files that marked by user as unmodified (typically is a player models etc)
	sv.num_consistency_resources = SV_TransferConsistencyInfo();

	// send serverinfo to all connected clients
	for( i = 0; i < sv_maxclients->integer; i++ )
	{
		if( svs.clients[i].state >= cs_connected )
		{
			Netchan_Clear( &svs.clients[i].netchan );
			svs.clients[i].delta_sequence = -1;
		}
	}

	numFrames = (sv.loadgame) ? 1 : 2;
	if( !sv.loadgame || svgame.globals->changelevel )
		host.frametime = 0.1f;			

	// GoldSrc rules
	// NOTE: this stuff is breaking sound from func_rotating in multiplayer
	// e.g. ambience\boomer.wav on snark_pit.bsp
	numFrames *= sv_maxclients->integer;

	// run some frames to allow everything to settle
	for( i = 0; i < numFrames; i++ )
	{
		SV_Physics();
	}

	// invoke to refresh all movevars
	Q_memset( &svgame.oldmovevars, 0, sizeof( movevars_t ));
	svgame.globals->changelevel = false; // changelevel ends here

	// setup hostflags
	sv.hostflags = 0;

	// tell what kind of server has been started.
	if( svgame.globals->maxClients > 1 )
	{
		MsgDev( D_INFO, "%i player server started\n", svgame.globals->maxClients );
		Cvar_Reset( "clockwindow" );
	}
	else
	{
		// clear the ugly moving delay in singleplayer
		Cvar_SetFloat( "clockwindow", 0.0f );
		MsgDev( D_INFO, "Game started\n" );
	}

	if( host.type == HOST_DEDICATED )
	{
		Mod_FreeUnused ();
	}

	sv.state = ss_active;
	physinfo->modified = true;
	sv.changelevel = false;
	sv.paused = false;

	Host_SetServerState( sv.state );

	if( sv_maxclients->integer > 1 && public_server->integer )
	{
		MsgDev( D_INFO, "Adding your server to master server list\n" );
		Master_Add( );
	}
}
Exemplo n.º 13
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
}