Esempio n. 1
0
/*
==================
SV_Frame

Player movement occurs as a result of packet events, which
happen before SV_Frame is called
==================
*/
void SV_Frame( int msec ) {
	int frameMsec;
	int startTime;

	// the menu kills the server with this cvar
	if ( sv_killserver->integer ) {
		SV_Shutdown( "Server was killed.\n" );
		Cvar_Set( "sv_killserver", "0" );
		return;
	}

	if ( !com_sv_running->integer ) {
		return;
	}

	// allow pause if only the local client is connected
	if ( SV_CheckPaused() ) {
		return;
	}

	// if it isn't time for the next frame, do nothing
	if ( sv_fps->integer < 1 ) {
		Cvar_Set( "sv_fps", "10" );
	}
	frameMsec = 1000 / sv_fps->integer ;

	sv.timeResidual += msec;

	if ( !com_dedicated->integer ) {
		SV_BotFrame( sv.time + sv.timeResidual );
	}

	if ( com_dedicated->integer && sv.timeResidual < frameMsec ) {
		// NET_Sleep will give the OS time slices until either get a packet
		// or time enough for a server frame has gone by
		NET_Sleep( frameMsec - sv.timeResidual );
		return;
	}

	// if time is about to hit the 32nd bit, kick all clients
	// and clear sv.time, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if ( svs.time > 0x70000000 ) {
		SV_Shutdown( "Restarting server due to time wrapping" );
		Cbuf_AddText( "vstr nextmap\n" );
		return;
	}
	// this can happen considerably earlier when lots of clients play and the map doesn't change
	if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
		SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
		Cbuf_AddText( "vstr nextmap\n" );
		return;
	}

	if ( sv.restartTime && sv.time >= sv.restartTime ) {
		sv.restartTime = 0;
		Cbuf_AddText( "map_restart 0\n" );
		return;
	}

	// update infostrings if anything has been changed
	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString_Big( CVAR_SYSTEMINFO ) );
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}

	if ( com_speeds->integer ) {
		startTime = Sys_Milliseconds();
	} else {
		startTime = 0;  // quite a compiler warning
	}

	// update ping based on the all received frames
	SV_CalcPings();

	if ( com_dedicated->integer ) {
		SV_BotFrame( sv.time );
	}

	// run the game simulation in chunks
	while ( sv.timeResidual >= frameMsec ) {
		sv.timeResidual -= frameMsec;
		svs.time += frameMsec;
		sv.time += frameMsec;

		// let everything in the world think and move
		VM_Call( gvm, GAME_RUN_FRAME, sv.time );
	}

	if ( com_speeds->integer ) {
		time_game = Sys_Milliseconds() - startTime;
	}

	// check timeouts
	SV_CheckTimeouts();

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

	// send a heartbeat to the master if needed
	SV_MasterHeartbeat();
}
Esempio n. 2
0
void SV_Frame( int msec,float fractionMsec ) {
	int		frameMsec;
	int		startTime=0;

	// the menu kills the server with this cvar
	if ( sv_killserver->integer ) {
		SV_Shutdown ("Server was killed.\n");
		Cvar_Set( "sv_killserver", "0" );
		return;
	}

	if ( !com_sv_running->integer ) {
		return;
	}

 	extern void SE_CheckForLanguageUpdates(void);
	SE_CheckForLanguageUpdates();	// will fast-return else load different language if menu changed it

	// allow pause if only the local client is connected
	if ( SV_CheckPaused() ) {
		return;
	}

	// go ahead and let time slip if the server really hitched badly
	if ( msec > 1000 ) {
		Com_DPrintf( "SV_Frame: Truncating msec of %i to 1000\n", msec );
		msec = 1000;
	}

	// if it isn't time for the next frame, do nothing
	if ( sv_fps->integer < 1 ) {
		Cvar_Set( "sv_fps", "10" );
	}
	frameMsec = 1000 / sv_fps->integer ;

	sv.timeResidual += msec;
	sv.timeResidualFraction+=fractionMsec;
	if (sv.timeResidualFraction>=1.0f)
	{
		sv.timeResidualFraction-=1.0f;
		if (cl_newClock&&cl_newClock->integer)
		{
			sv.timeResidual++;
		}
	}
	if ( sv.timeResidual < frameMsec ) {
		return;
	}

	// if time is about to hit the 32nd bit, restart the
	// level, which will force the time back to zero, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if ( sv.time > 0x70000000 ) {
		SV_Shutdown( "Restarting server due to time wrapping" );
		Com_Printf("You win.  if you can play this long and not die, you deserve to win.\n");
		return;
	}

	// update infostrings if anything has been changed
	if ( cvar_modifiedFlags & CVAR_SERVERINFO ) {
		SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if ( cvar_modifiedFlags & CVAR_SYSTEMINFO ) {
		SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) );
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}

	if ( com_speeds->integer ) {
		startTime = Sys_Milliseconds ();
	}

//	SV_BotFrame( sv.time );

	// run the game simulation in chunks
	while ( sv.timeResidual >= frameMsec ) {
		sv.timeResidual -= frameMsec;
		sv.time += frameMsec;
		re.G2API_SetTime(sv.time,G2T_SV_TIME);

		// let everything in the world think and move
		ge->RunFrame( sv.time );
	}

	if ( com_speeds->integer ) {
		time_game = Sys_Milliseconds () - startTime;
	}

	SG_TestSave();	// returns immediately if not active, used for fake-save-every-cycle to test (mainly) Icarus disk code

	// check timeouts
	SV_CheckTimeouts ();

	// update ping based on the last known frame from all clients
	SV_CalcPings ();

	// send messages back to the clients
	SV_SendClientMessages ();
}
Esempio n. 3
0
/*
==================
SV_Frame

Player movement occurs as a result of packet events, which
happen before SV_Frame is called
==================
*/
void SV_Frame(int msec) {
	int             frameMsec, startTime, frameStartTime = 0, frameEndTime;
	char            mapname[MAX_QPATH];
	// Dushan
	static int      start, end;

	start = Sys_Milliseconds ();
	svs.stats.idle += (double)(start - end) / 1000;

	// the menu kills the server with this cvar
	if(sv_killserver->integer) {
		SV_Shutdown("Server was killed.\n");
		Cvar_Set("sv_killserver", "0");
		return;
	}

	if(!com_sv_running->integer) {
		// Running as a server, but no map loaded
#if defined (DEDICATED)
		// Block until something interesting happens
		Sys_Sleep(-1);
#endif
		return;
	}

	// allow pause if only the local client is connected
	if(SV_CheckPaused()) {
		return;
	}

	if(com_dedicated->integer) {
		frameStartTime = Sys_Milliseconds();
	}

	// if it isn't time for the next frame, do nothing
	if(sv_fps->integer < 1) {
		Cvar_Set("sv_fps", "10");
	}

	frameMsec = 1000 / sv_fps->integer * com_timescale->value;
	// don't let it scale below 1ms
	if(frameMsec < 1) {
		Cvar_Set("timescale", va("%f", sv_fps->integer / 1000.0f));
		frameMsec = 1;
	}

	sv.timeResidual += msec;

	if(!com_dedicated->integer) {
		SV_BotFrame(svs.time + sv.timeResidual);
	}

	if(com_dedicated->integer && sv.timeResidual < frameMsec) {
		// NET_Sleep will give the OS time slices until either get a packet
		// or time enough for a server frame has gone by
		NET_Sleep(frameMsec - sv.timeResidual);
		return;
	}

	// if time is about to hit the 32nd bit, kick all clients
	// and clear sv.time, rather
	// than checking for negative time wraparound everywhere.
	// 2giga-milliseconds = 23 days, so it won't be too often
	if(svs.time > 0x70000000) {
		Q_strncpyz(mapname, sv_mapname->string, MAX_QPATH);
		SV_Shutdown("Restarting server due to time wrapping");
		// TTimo
		// show_bug.cgi?id=388
		// there won't be a map_restart if you have shut down the server
		// since it doesn't restart a non-running server
		// instead, re-run the current map
		Cbuf_AddText(va("map %s\n", mapname));
		return;
	}
	// this can happen considerably earlier when lots of clients play and the map doesn't change
	if(svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities) {
		Q_strncpyz(mapname, sv_mapname->string, MAX_QPATH);
		SV_Shutdown("Restarting server due to numSnapshotEntities wrapping");
		// TTimo see above
		Cbuf_AddText(va("map %s\n", mapname));
		return;
	}

	if(sv.restartTime && svs.time >= sv.restartTime) {
		sv.restartTime = 0;
		Cbuf_AddText("map_restart 0\n");
		return;
	}

	// update infostrings if anything has been changed
	if(cvar_modifiedFlags & CVAR_SERVERINFO) {
		SV_SetConfigstring(CS_SERVERINFO, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE));
		cvar_modifiedFlags &= ~CVAR_SERVERINFO;
	}
	if(cvar_modifiedFlags & CVAR_SERVERINFO_NOUPDATE) {
		SV_SetConfigstringNoUpdate(CS_SERVERINFO, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE));
		cvar_modifiedFlags &= ~CVAR_SERVERINFO_NOUPDATE;
	}
	if(cvar_modifiedFlags & CVAR_SYSTEMINFO) {
		SV_SetConfigstring(CS_SYSTEMINFO, Cvar_InfoString_Big(CVAR_SYSTEMINFO));
		cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;
	}
	// NERVE - SMF
	if(cvar_modifiedFlags & CVAR_WOLFINFO) {
		SV_SetConfigstring(CS_WOLFINFO, Cvar_InfoString(CVAR_WOLFINFO));
		cvar_modifiedFlags &= ~CVAR_WOLFINFO;
	}

	if(com_speeds->integer) {
		startTime = Sys_Milliseconds();
	} else {
		startTime = 0;			// quite a compiler warning
	}

	// update ping based on the all received frames
	SV_CalcPings();

	if(com_dedicated->integer) {
		SV_BotFrame(svs.time);
	}

	// run the game simulation in chunks
	while(sv.timeResidual >= frameMsec) {
		sv.timeResidual -= frameMsec;
		svs.time += frameMsec;

		// let everything in the world think and move
#if !defined (UPDATE_SERVER)
		VM_Call(gvm, GAME_RUN_FRAME, svs.time);
#endif
		
#ifdef USE_PHYSICS
        CMod_PhysicsUpdate(svs.time, 1.0f / sv_fps->integer);
#endif
	}

	if(com_speeds->integer) {
		time_game = Sys_Milliseconds() - startTime;
	}

	// check timeouts
	SV_CheckTimeouts();

	// check user info buffer thingy
	SV_CheckClientUserinfoTimer();

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

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

	if(com_dedicated->integer) {
		frameEndTime = Sys_Milliseconds();

		svs.totalFrameTime += (frameEndTime - frameStartTime);
		svs.currentFrameIndex++;

		//if( svs.currentFrameIndex % 50 == 0 )
		//  Com_Printf( "currentFrameIndex: %i\n", svs.currentFrameIndex );

		if(svs.currentFrameIndex == SERVER_PERFORMANCECOUNTER_FRAMES) {
			int averageFrameTime;

			averageFrameTime = svs.totalFrameTime / SERVER_PERFORMANCECOUNTER_FRAMES;

			svs.sampleTimes[svs.currentSampleIndex % SERVER_PERFORMANCECOUNTER_SAMPLES] = averageFrameTime;
			svs.currentSampleIndex++;

			if(svs.currentSampleIndex > SERVER_PERFORMANCECOUNTER_SAMPLES) {
				int totalTime, i;

				totalTime = 0;
				for(i = 0; i < SERVER_PERFORMANCECOUNTER_SAMPLES; i++) {
					totalTime += svs.sampleTimes[i];
				}

				if(!totalTime) {
					totalTime = 1;
				}

				averageFrameTime = totalTime / SERVER_PERFORMANCECOUNTER_SAMPLES;

				svs.serverLoad = (averageFrameTime / (float)frameMsec) * 100;
			}

			//Com_Printf( "serverload: %i (%i/%i)\n", svs.serverLoad, averageFrameTime, frameMsec );

			svs.totalFrameTime = 0;
			svs.currentFrameIndex = 0;
		}
	} else {
		svs.serverLoad = -1;
	}

	// collect timing statistics
	end = Sys_Milliseconds ();
	svs.stats.active += ((double) (end-start)) / 1000;
	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;
	}
}
Esempio n. 4
0
/*
* SV_RunGameFrame
*/
static qboolean SV_RunGameFrame( int msec )
{
	static unsigned int accTime = 0;
	qboolean refreshSnapshot;
	qboolean refreshGameModule;
	qboolean sentFragments;

	accTime += msec;

	refreshSnapshot = qfalse;
	refreshGameModule = qfalse;

	sentFragments = SV_SendClientsFragments();

	// see if it's time to run a new game frame
	if( accTime >= WORLDFRAMETIME )
		refreshGameModule = qtrue;

	// see if it's time for a new snapshot
	if( !sentFragments && svs.gametime >= sv.nextSnapTime )
	{
		refreshSnapshot = qtrue;
		refreshGameModule = qtrue;
	}

	// if there aren't pending packets to be sent, we can sleep
	if( dedicated->integer && !sentFragments && !refreshSnapshot )
	{
		int sleeptime = min( WORLDFRAMETIME - ( accTime + 1 ), sv.nextSnapTime - ( svs.gametime + 1 ) );

		if( sleeptime > 0 )
		{
			socket_t *sockets [] = { &svs.socket_udp, &svs.socket_udp6 };
			socket_t *opened_sockets [sizeof( sockets ) / sizeof( sockets[0] ) + 1 ];
			size_t sock_ind, open_ind;

			// Pass only the opened sockets to the sleep function
			open_ind = 0;
			for ( sock_ind = 0; sock_ind < sizeof( sockets ) / sizeof( sockets[0] ); sock_ind++)
			{
				socket_t *sock = sockets[sock_ind];
				if ( sock->open )
				{
					opened_sockets[open_ind] = sock;
					open_ind++;
				}
			}
			opened_sockets[open_ind] = NULL;

			NET_Sleep( sleeptime, opened_sockets );
		}
	}

	if( refreshGameModule )
	{
		unsigned int moduleTime;

		// update ping based on the last known frame from all clients
		SV_CalcPings();

		if( accTime >= WORLDFRAMETIME )
		{
			moduleTime = WORLDFRAMETIME;
			accTime -= WORLDFRAMETIME;
			if( accTime >= WORLDFRAMETIME ) // don't let it accumulate more than 1 frame
				accTime = WORLDFRAMETIME - 1;
		}
		else
		{
			moduleTime = accTime;
			accTime = 0;
		}

		if( host_speeds->integer )
			time_before_game = Sys_Milliseconds();

		ge->RunFrame( moduleTime, svs.gametime );

		if( host_speeds->integer )
			time_after_game = Sys_Milliseconds();
	}

	// if we don't have to send a snapshot we are done here
	if( refreshSnapshot )
	{
		int extraSnapTime;

		// set up for sending a snapshot
		sv.framenum++;
		ge->SnapFrame();

		// set time for next snapshot
		extraSnapTime = (int)( svs.gametime - sv.nextSnapTime );
		if( extraSnapTime > svc.snapFrameTime * 0.5 ) // don't let too much time be accumulated
			extraSnapTime = svc.snapFrameTime * 0.5;

		sv.nextSnapTime = svs.gametime + ( svc.snapFrameTime - extraSnapTime );

		return qtrue;
	}

	return qfalse;
}
Esempio n. 5
0
void SV_Frame(float msec)
{
	guard(SV_Frame);

	time_before_game = time_after_game = 0;

	// if server is not active, do nothing
	if (!svs.initialized)
		return;

//	SV_DrawTextLeft(va("time: %10d rf: %10.5f d: %10.4f ri:%10d", sv.time, svs.realtimef, msec, svs.realtime));//!!
	svs.realtimef += msec;
	svs.realtime = appFloor(svs.realtimef);

	if (!sv.attractloop)
	{
		// check timeouts
		SV_CheckTimeouts();
	}
	// get packets from clients
	SV_ReadPackets();
	if (sv.state == ss_dead) return;	// server was killed from one of packet (e.g. "rcon killserver")

	int frameTime = 100;	// (sv_fps->integer > 10) ? (1000 / sv_fps->integer) : 100;

	// move autonomous things around if enough time has passed
	if (svs.realtime < sv.time)
	{
		// never let the time get too far off
		if (sv.time - svs.realtime > frameTime)
		{
			if (sv_showclamp->integer)
				appPrintf("sv lowclamp s:%d -- r:%d -> %d\n", sv.time, svs.realtime, sv.time - frameTime);
			svs.realtime  = sv.time - frameTime;
			svs.realtimef = svs.realtime;
		}
		return;
	}

	SV_ClearTexts();

	if (!sv.attractloop)
	{
		// update ping based on the last known frame from all clients
		SV_CalcPings();
		// give the clients some timeslices
		SV_GiveMsec();
	}

	// let everything in the world think and move
	/*-------- SV_RunGameFrame() ---------------*/
	// we always need to bump framenum, even if we
	// don't run the world, otherwise the delta
	// compression can get confused when a client
	// has the "current" frame
	sv.framenum++;
	sv.time += frameTime;	//  = sv.framenum*100; ??

	// don't run if paused
	if (!sv_paused->integer || sv_maxclients->integer > 1)
	{
		time_before_game = appCycles();

		guardGame(ge.RunFrame);
		ge->RunFrame();
		unguardGame;


		// never get more than one tic behind
		if (sv.time < svs.realtime)
		{
			if (sv_showclamp->integer)
				appPrintf("sv highclamp s:%d r:%d -> %d\n", sv.time, svs.realtime, sv.time);
			svs.realtime  = sv.time;
			svs.realtimef = sv.time;
		}
		time_after_game = appCycles();
	}

	// if extended protocol used, recalculate footstep sounds, mdx/mdl/md3 frames etc.
	if (sv_extProtocol->integer && !sv.attractloop)
		SV_PostprocessFrame();

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

	// save the entire world state if recording a serverdemo
	SV_RecordDemoMessage();

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

	// clear teleport flags, etc for next frame
	SV_PrepWorldFrame();

	unguard;
}