removed tick simulator and added api to help with mapchanges
authorDavid Anderson <dvander@alliedmods.net>
Tue Sep 11 18:02:59 2007 +0000 (2007-09-11)
changeset 1407bb6516a50eea
parent 1406 f5c07ec3c052
child 1408 2fd63cc4bd9c
removed tick simulator and added api to help with mapchanges
core/TimerSys.cpp
core/TimerSys.h
core/smn_timers.cpp
core/sourcemod.cpp
public/ITimerSystem.h
     1.1 --- a/core/TimerSys.cpp	Tue Sep 11 15:10:18 2007 +0000
     1.2 +++ b/core/TimerSys.cpp	Tue Sep 11 18:02:59 2007 +0000
     1.3 @@ -34,7 +34,6 @@
     1.4  #include "sourcemm_api.h"
     1.5  
     1.6  TimerSystem g_Timers;
     1.7 -TickInfo g_SimTicks;
     1.8  
     1.9  ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds");
    1.10  
    1.11 @@ -50,12 +49,7 @@
    1.12  
    1.13  inline float GetSimulatedTime()
    1.14  {
    1.15 -	if (g_SimTicks.ticking)
    1.16 -	{
    1.17 -		return gpGlobals->curtime;
    1.18 -	} else {
    1.19 -		return g_SimTicks.ticktime;
    1.20 -	}
    1.21 +	return engine->Time();
    1.22  }
    1.23  
    1.24  void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
    1.25 @@ -110,6 +104,25 @@
    1.26  		}
    1.27  	}
    1.28  
    1.29 +	if (m_fnTimeLeft != NULL && m_MapEndTimers.size())
    1.30 +	{
    1.31 +		float time_left = m_fnTimeLeft();
    1.32 +		for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end();)
    1.33 +		{
    1.34 +			pTimer = (*iter);
    1.35 +			if ((*iter)->m_Interval < time_left)
    1.36 +			{
    1.37 +				pTimer->m_InExec = true;
    1.38 +				pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
    1.39 +				pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    1.40 +				iter = m_MapEndTimers.erase(iter);
    1.41 +				m_FreeTimers.push(pTimer);
    1.42 +			} else {
    1.43 +				break;
    1.44 +			}
    1.45 +		}
    1.46 +	}
    1.47 +
    1.48  	ResultType res;
    1.49  	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
    1.50  	{
    1.51 @@ -156,27 +169,41 @@
    1.52  		goto return_timer;
    1.53  	}
    1.54  
    1.55 -	if (m_SingleTimers.size() >= 1)
    1.56 +	if (flags & TIMER_FLAG_BEFORE_MAP_END)
    1.57  	{
    1.58 -		iter = --m_SingleTimers.end();
    1.59 -		if ((*iter)->m_ToExec <= to_exec)
    1.60 +		for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
    1.61  		{
    1.62 -			goto insert_end;
    1.63 +			if (fInterval >= (*iter)->m_Interval)
    1.64 +			{
    1.65 +				m_MapEndTimers.insert(iter, pTimer);
    1.66 +				goto return_timer;
    1.67 +			}
    1.68  		}
    1.69 -	}
    1.70  
    1.71 -	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
    1.72 -	{
    1.73 -		if ((*iter)->m_ToExec >= to_exec)
    1.74 +		m_MapEndTimers.push_back(pTimer);
    1.75 +	} else {
    1.76 +		if (m_SingleTimers.size() >= 1)
    1.77  		{
    1.78 -			m_SingleTimers.insert(iter, pTimer);
    1.79 -			goto return_timer;
    1.80 +			iter = --m_SingleTimers.end();
    1.81 +			if ((*iter)->m_ToExec <= to_exec)
    1.82 +			{
    1.83 +				goto normal_insert_end;
    1.84 +			}
    1.85  		}
    1.86 +	
    1.87 +		for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
    1.88 +		{
    1.89 +			if ((*iter)->m_ToExec >= to_exec)
    1.90 +			{
    1.91 +				m_SingleTimers.insert(iter, pTimer);
    1.92 +				goto return_timer;
    1.93 +			}
    1.94 +		}
    1.95 +
    1.96 +normal_insert_end:
    1.97 +		m_SingleTimers.push_back(pTimer);
    1.98  	}
    1.99  
   1.100 -insert_end:
   1.101 -	m_SingleTimers.push_back(pTimer);
   1.102 -
   1.103  return_timer:
   1.104  	return pTimer;
   1.105  }
   1.106 @@ -196,7 +223,12 @@
   1.107  	if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
   1.108  	{
   1.109  		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   1.110 -		m_SingleTimers.remove(pTimer);
   1.111 +		if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END)
   1.112 +		{
   1.113 +			m_MapEndTimers.remove(pTimer);
   1.114 +		} else {
   1.115 +			m_SingleTimers.remove(pTimer);
   1.116 +		}
   1.117  		m_FreeTimers.push(pTimer);
   1.118  	} else {
   1.119  		if ((res != Pl_Stop) && !pTimer->m_KillMe)
   1.120 @@ -232,7 +264,14 @@
   1.121  	pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
   1.122  	pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
   1.123  
   1.124 -	pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
   1.125 +	if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
   1.126 +	{
   1.127 +		m_LoopTimers.remove(pTimer);
   1.128 +	} else if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END) {
   1.129 +		m_MapEndTimers.remove(pTimer);
   1.130 +	} else {
   1.131 +		m_SingleTimers.remove(pTimer);
   1.132 +	}
   1.133  
   1.134  	pList->remove(pTimer);
   1.135  	m_FreeTimers.push(pTimer);
   1.136 @@ -266,6 +305,15 @@
   1.137  		}
   1.138  	}
   1.139  
   1.140 +	if (real_mapchange)
   1.141 +	{
   1.142 +		for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
   1.143 +		{
   1.144 +			pTimer = (*iter);
   1.145 +			s_tokill.push(pTimer);
   1.146 +		}
   1.147 +	}
   1.148 +
   1.149  	while (!s_tokill.empty())
   1.150  	{
   1.151  		KillTimer(s_tokill.front());
   1.152 @@ -274,3 +322,11 @@
   1.153  
   1.154  	m_LastExecTime = GetSimulatedTime();
   1.155  }
   1.156 +
   1.157 +SM_TIMELEFT_FUNCTION TimerSystem::SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn)
   1.158 +{
   1.159 +	SM_TIMELEFT_FUNCTION old = m_fnTimeLeft;
   1.160 +	m_fnTimeLeft = fn;
   1.161 +	return old;
   1.162 +}
   1.163 +
     2.1 --- a/core/TimerSys.h	Tue Sep 11 15:10:18 2007 +0000
     2.2 +++ b/core/TimerSys.h	Tue Sep 11 18:02:59 2007 +0000
     2.3 @@ -44,13 +44,6 @@
     2.4  typedef List<ITimer *> TimerList;
     2.5  typedef List<ITimer *>::iterator TimerIter;
     2.6  
     2.7 -struct TickInfo
     2.8 -{
     2.9 -	bool ticking;				/* true=game is ticking, false=we're ticking */
    2.10 -	unsigned int tickcount;		/* number of simulated ticks we've done */
    2.11 -	float ticktime;				/* tick time we're maintaining */
    2.12 -};
    2.13 -
    2.14  class SourceMod::ITimer
    2.15  {
    2.16  public:
    2.17 @@ -77,19 +70,22 @@
    2.18  	ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
    2.19  	void KillTimer(ITimer *pTimer);
    2.20  	void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
    2.21 +	SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn);
    2.22  public:
    2.23  	void RunFrame();
    2.24  	void MapChange(bool real_mapchange);
    2.25  private:
    2.26  	List<ITimer *> m_SingleTimers;
    2.27  	List<ITimer *> m_LoopTimers;
    2.28 +	List<ITimer *> m_MapEndTimers;
    2.29  	CStack<ITimer *> m_FreeTimers;
    2.30  	float m_LastExecTime;
    2.31 +	SM_TIMELEFT_FUNCTION m_fnTimeLeft;
    2.32  };
    2.33  
    2.34  time_t GetAdjustedTime(time_t *buf = NULL);
    2.35  
    2.36  extern TimerSystem g_Timers;
    2.37 -extern TickInfo g_SimTicks;
    2.38  
    2.39  #endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_
    2.40 +
     3.1 --- a/core/smn_timers.cpp	Tue Sep 11 15:10:18 2007 +0000
     3.2 +++ b/core/smn_timers.cpp	Tue Sep 11 18:02:59 2007 +0000
     3.3 @@ -248,12 +248,7 @@
     3.4  
     3.5  static cell_t smn_GetTickedTime(IPluginContext *pContext, const cell_t *params)
     3.6  {
     3.7 -	cell_t *simulating;
     3.8 -	pContext->LocalToPhysAddr(params[1], &simulating);
     3.9 -
    3.10 -	*simulating = g_SimTicks.ticking ? 0 : 1;
    3.11 -
    3.12 -	float t = g_SimTicks.ticking ? gpGlobals->curtime : g_SimTicks.ticktime;
    3.13 +	float t = engine->Time();
    3.14  	return sp_ftoc(t);
    3.15  }
    3.16  
     4.1 --- a/core/sourcemod.cpp	Tue Sep 11 15:10:18 2007 +0000
     4.2 +++ b/core/sourcemod.cpp	Tue Sep 11 18:02:59 2007 +0000
     4.3 @@ -71,8 +71,6 @@
     4.4  IForward *g_pOnGameFrame = NULL;
     4.5  IForward *g_pOnMapEnd = NULL;
     4.6  bool g_Loaded = false;
     4.7 -int g_StillFrames = 0;
     4.8 -float g_StillTime = 0.0f;
     4.9  IExtension *g_pGameExt = NULL;
    4.10  
    4.11  typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
    4.12 @@ -335,10 +333,6 @@
    4.13  	g_LastTime = 0.0f;
    4.14  	g_LastMenuTime = 0.0f;
    4.15  	g_LastAuthCheck = 0.0f;
    4.16 -	g_SimTicks.ticking = true;
    4.17 -	g_SimTicks.tickcount = 0;
    4.18 -	g_StillTime = 0.0f;
    4.19 -	g_StillFrames = 0;
    4.20  
    4.21  	/* Notify! */
    4.22  	SMGlobalClass *pBase = SMGlobalClass::head;
    4.23 @@ -375,27 +369,6 @@
    4.24  	RETURN_META_VALUE(MRES_IGNORED, true);
    4.25  }
    4.26  
    4.27 -void StartTickSimulation()
    4.28 -{
    4.29 -	g_SimTicks.ticking = false;
    4.30 -	g_SimTicks.tickcount = 0;
    4.31 -	g_SimTicks.ticktime = gpGlobals->curtime;
    4.32 -}
    4.33 -
    4.34 -void StopTickSimulation()
    4.35 -{
    4.36 -	g_SimTicks.ticking = true;
    4.37 -	g_Timers.MapChange(false);
    4.38 -	g_StillFrames = 0;
    4.39 -	g_LastTime = gpGlobals->curtime;
    4.40 -}
    4.41 -
    4.42 -void SimulateTick()
    4.43 -{
    4.44 -	g_SimTicks.tickcount++;
    4.45 -	g_SimTicks.ticktime = g_StillTime + (g_SimTicks.tickcount * gpGlobals->interval_per_tick);
    4.46 -}
    4.47 -
    4.48  void SourceModBase::GameFrame(bool simulating)
    4.49  {
    4.50  	g_DBMan.RunFrame();
    4.51 @@ -405,46 +378,7 @@
    4.52  	 * Note: This is all hardcoded rather than delegated to save
    4.53  	 * precious CPU cycles.
    4.54  	 */
    4.55 -	float curtime = gpGlobals->curtime;
    4.56 -	int framecount = gpGlobals->framecount;
    4.57 -
    4.58 -	/* Verify that we're still ticking */
    4.59 -	if (g_SimTicks.ticking)
    4.60 -	{
    4.61 -		if (g_StillFrames == 0)
    4.62 -		{
    4.63 -			g_StillFrames = framecount;
    4.64 -			g_StillTime = curtime;
    4.65 -		} else {
    4.66 -			/* Try to detect when we've stopped ticking.
    4.67 -			 * We do this once 10 frames pass and there have been no ticks.
    4.68 -			 */
    4.69 -			if (g_StillTime == curtime)
    4.70 -			{
    4.71 -				if (framecount - g_StillFrames >= 5)
    4.72 -				{
    4.73 -					StartTickSimulation();
    4.74 -					return;
    4.75 -				}
    4.76 -			} else {
    4.77 -				/* We're definitely ticking we get here, 
    4.78 -				 * but update everything as a precaution */
    4.79 -				g_StillFrames = framecount;
    4.80 -				g_StillTime = curtime;
    4.81 -			}
    4.82 -		}
    4.83 -	} else {
    4.84 -		/* We need to make sure we should still be simulating. */
    4.85 -		if (g_StillTime != curtime)
    4.86 -		{
    4.87 -			/* Wow, we're ticking again! It's time to revert. */
    4.88 -			StopTickSimulation();
    4.89 -			return;
    4.90 -		}
    4.91 -		/* Nope, not ticking.  Simulate! */
    4.92 -		SimulateTick();
    4.93 -		curtime = g_SimTicks.ticktime;
    4.94 -	}
    4.95 +	float curtime = engine->Time();
    4.96  
    4.97  	if (curtime - g_LastTime >= 0.1f)
    4.98  	{
    4.99 @@ -459,7 +393,7 @@
   4.100  		g_LastTime = curtime;
   4.101  	}
   4.102  
   4.103 -	if (g_SimTicks.ticking && curtime - g_LastMenuTime >= 1.0f)
   4.104 +	if (gpGlobals->curtime - g_LastMenuTime >= 1.0f)
   4.105  	{
   4.106  		g_ValveMenuStyle.ProcessWatchList();
   4.107  		g_RadioMenuStyle.ProcessWatchList();
     5.1 --- a/public/ITimerSystem.h	Tue Sep 11 15:10:18 2007 +0000
     5.2 +++ b/public/ITimerSystem.h	Tue Sep 11 18:02:59 2007 +0000
     5.3 @@ -48,6 +48,8 @@
     5.4  {
     5.5  	class ITimer;
     5.6  
     5.7 +	typedef float (*SM_TIMELEFT_FUNCTION)();
     5.8 +
     5.9  	/**
    5.10  	 * @brief Event callbacks for when a timer is executed.
    5.11  	 */
    5.12 @@ -74,6 +76,10 @@
    5.13  
    5.14  	#define TIMER_FLAG_REPEAT			(1<<0)		/**< Timer will repeat until stopped */
    5.15  	#define TIMER_FLAG_NO_MAPCHANGE		(1<<1)		/**< Timer will not carry over mapchanges */
    5.16 +	#define TIMER_FLAG_BEFORE_MAP_END	(1<<2)		/**< Timer will fire <interval> seconds before map end.
    5.17 +														 This flag is cannot be used with REPEAT, 
    5.18 +														 and TIMER_FLAG_NO_MAPCHANGE is implied.
    5.19 +														 */
    5.20  
    5.21  	class ITimerSystem : public SMInterface
    5.22  	{
    5.23 @@ -95,7 +101,8 @@
    5.24  		 *							The smallest allowed interval is 0.1 seconds.
    5.25  		 * @param pData				Private data to pass on to the timer.
    5.26  		 * @param flags				Extra flags to pass on to the timer.
    5.27 -		 * @return					An ITimer pointer on success, NULL on failure.
    5.28 +		 * @return					An ITimer pointer on success, NULL on 
    5.29 +		 *							failure.
    5.30  		 */
    5.31  		virtual ITimer *CreateTimer(ITimedEvent *pCallbacks, 
    5.32  										 float fInterval, 
    5.33 @@ -116,11 +123,21 @@
    5.34  		 *
    5.35  		 * @param pTimer			Pointer to the ITimer structure.
    5.36  		 * @param delayExec			If true, and the timer is repeating, the
    5.37 -		 *							next execution will be delayed by its interval.
    5.38 +		 *							next execution will be delayed by its 
    5.39 +		 *							interval.
    5.40  		 * @return
    5.41  		 */
    5.42  		virtual void FireTimerOnce(ITimer *pTimer, bool delayExec=false) =0;
    5.43 +
    5.44 +		/**
    5.45 +		 * @brief Sets the function which is used to find the time left in the map.
    5.46 +		 *
    5.47 +		 * @param fn				Function that returns the time left in seconds.
    5.48 +		 * @return					The previous SM_TIMELEFT_FUNCTION pointer.
    5.49 +		 */
    5.50 +		virtual SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn) =0;
    5.51  	};
    5.52  }
    5.53  
    5.54  #endif //_INCLUDE_SOURCEMOD_TIMER_SYSTEM_H_
    5.55 +