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 +