attempted fix for amb243, timers now simulate ticks if gameframe doesn't give changed curtimes

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40733
This commit is contained in:
David Anderson 2007-05-02 22:35:51 +00:00
parent 9219fbb96c
commit b8d3ea5196
3 changed files with 97 additions and 8 deletions

View File

@ -15,6 +15,17 @@
#include "TimerSys.h" #include "TimerSys.h"
TimerSystem g_Timers; TimerSystem g_Timers;
TickInfo g_SimTicks;
inline float GetSimulatedTime()
{
if (g_SimTicks.ticking)
{
return gpGlobals->curtime;
} else {
return g_SimTicks.ticktime;
}
}
void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags) void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
{ {
@ -52,10 +63,11 @@ void TimerSystem::RunFrame()
ITimer *pTimer; ITimer *pTimer;
TimerIter iter; TimerIter iter;
float curtime = GetSimulatedTime();
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); ) for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
{ {
pTimer = (*iter); pTimer = (*iter);
if (gpGlobals->curtime >= pTimer->m_ToExec) if (curtime >= pTimer->m_ToExec)
{ {
pTimer->m_InExec = true; pTimer->m_InExec = true;
pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData); pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
@ -71,7 +83,7 @@ void TimerSystem::RunFrame()
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); ) for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
{ {
pTimer = (*iter); pTimer = (*iter);
if (gpGlobals->curtime >= pTimer->m_ToExec) if (curtime >= pTimer->m_ToExec)
{ {
pTimer->m_InExec = true; pTimer->m_InExec = true;
res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData); res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
@ -83,19 +95,19 @@ void TimerSystem::RunFrame()
continue; continue;
} }
pTimer->m_InExec = false; pTimer->m_InExec = false;
pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval; pTimer->m_ToExec = curtime + pTimer->m_Interval;
} }
iter++; iter++;
} }
m_LastExecTime = gpGlobals->curtime; m_LastExecTime = curtime;
} }
ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags) ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
{ {
ITimer *pTimer; ITimer *pTimer;
TimerIter iter; TimerIter iter;
float to_exec = gpGlobals->curtime + fInterval; float to_exec = GetSimulatedTime() + fInterval;
if (m_FreeTimers.empty()) if (m_FreeTimers.empty())
{ {
@ -160,7 +172,7 @@ void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
{ {
if (delayExec) if (delayExec)
{ {
pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval; pTimer->m_ToExec = GetSimulatedTime() + pTimer->m_Interval;
} }
pTimer->m_InExec = false; pTimer->m_InExec = false;
return; return;
@ -203,12 +215,14 @@ void TimerSystem::MapChange()
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++) for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
{ {
pTimer = (*iter); pTimer = (*iter);
pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime; pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + GetSimulatedTime();
} }
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++) for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
{ {
pTimer = (*iter); pTimer = (*iter);
pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime; pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + GetSimulatedTime();
} }
m_LastExecTime = GetSimulatedTime();
} }

View File

@ -27,6 +27,13 @@ using namespace SourceMod;
typedef List<ITimer *> TimerList; typedef List<ITimer *> TimerList;
typedef List<ITimer *>::iterator TimerIter; typedef List<ITimer *>::iterator TimerIter;
struct TickInfo
{
bool ticking; /* true=game is ticking, false=we're ticking */
unsigned int tickcount; /* number of simulated ticks we've done */
float ticktime; /* tick time we're maintaining */
};
class SourceMod::ITimer class SourceMod::ITimer
{ {
public: public:
@ -64,5 +71,6 @@ private:
}; };
extern TimerSystem g_Timers; extern TimerSystem g_Timers;
extern TickInfo g_SimTicks;
#endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_ #endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_

View File

@ -47,6 +47,8 @@ float g_LastAuthCheck = 0.0f;
IForward *g_pOnGameFrame = NULL; IForward *g_pOnGameFrame = NULL;
IForward *g_pOnMapEnd = NULL; IForward *g_pOnMapEnd = NULL;
bool g_Loaded = false; bool g_Loaded = false;
int g_StillFrames = 0;
float g_StillTime = 0.0f;
typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *); typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
typedef unsigned int (*GETEXPORTCOUNT)(); typedef unsigned int (*GETEXPORTCOUNT)();
@ -263,6 +265,10 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
m_ExecPluginReload = true; m_ExecPluginReload = true;
g_LastTime = 0.0f; g_LastTime = 0.0f;
g_LastAuthCheck = 0.0f; g_LastAuthCheck = 0.0f;
g_SimTicks.ticking = true;
g_SimTicks.tickcount = 0;
g_StillTime = 0.0f;
g_StillFrames = 0;
/* Notify! */ /* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head; SMGlobalClass *pBase = SMGlobalClass::head;
@ -297,6 +303,27 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
void StartTickSimulation()
{
g_SimTicks.ticking = false;
g_SimTicks.tickcount = 0;
g_SimTicks.ticktime = gpGlobals->curtime;
}
void StopTickSimulation()
{
g_SimTicks.ticking = true;
g_Timers.MapChange();
g_StillFrames = 0;
g_LastTime = gpGlobals->curtime;
}
void SimulateTick()
{
g_SimTicks.tickcount++;
g_SimTicks.ticktime = g_StillTime + (g_SimTicks.tickcount * gpGlobals->interval_per_tick);
}
void SourceModBase::GameFrame(bool simulating) void SourceModBase::GameFrame(bool simulating)
{ {
/** /**
@ -304,6 +331,46 @@ void SourceModBase::GameFrame(bool simulating)
* precious CPU cycles. * precious CPU cycles.
*/ */
float curtime = gpGlobals->curtime; float curtime = gpGlobals->curtime;
int framecount = gpGlobals->framecount;
/* Verify that we're still ticking */
if (g_SimTicks.ticking)
{
if (g_StillFrames == 0)
{
g_StillFrames = framecount;
g_StillTime = curtime;
} else {
/* Try to detect when we've stopped ticking.
* We do this once 10 frames pass and there have been no ticks.
*/
if (g_StillTime == curtime)
{
if (framecount - g_StillFrames >= 5)
{
StartTickSimulation();
return;
}
} else {
/* We're definitely ticking we get here,
* but update everything as a precaution */
g_StillFrames = framecount;
g_StillTime = curtime;
}
}
} else {
/* We need to make sure we should still be simulating. */
if (g_StillTime != curtime)
{
/* Wow, we're ticking again! It's time to revert. */
StopTickSimulation();
return;
}
/* Nope, not ticking. Simulate! */
SimulateTick();
curtime = g_SimTicks.ticktime;
}
if (curtime - g_LastTime >= 0.1f) if (curtime - g_LastTime >= 0.1f)
{ {
if (m_CheckingAuth if (m_CheckingAuth