removed tick simulator and added api to help with mapchanges
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401413
This commit is contained in:
parent
017da078ef
commit
293705f63f
@ -34,7 +34,6 @@
|
||||
#include "sourcemm_api.h"
|
||||
|
||||
TimerSystem g_Timers;
|
||||
TickInfo g_SimTicks;
|
||||
|
||||
ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds");
|
||||
|
||||
@ -50,12 +49,7 @@ time_t GetAdjustedTime(time_t *buf)
|
||||
|
||||
inline float GetSimulatedTime()
|
||||
{
|
||||
if (g_SimTicks.ticking)
|
||||
{
|
||||
return gpGlobals->curtime;
|
||||
} else {
|
||||
return g_SimTicks.ticktime;
|
||||
}
|
||||
return engine->Time();
|
||||
}
|
||||
|
||||
void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
|
||||
@ -110,6 +104,25 @@ void TimerSystem::RunFrame()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_fnTimeLeft != NULL && m_MapEndTimers.size())
|
||||
{
|
||||
float time_left = m_fnTimeLeft();
|
||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end();)
|
||||
{
|
||||
pTimer = (*iter);
|
||||
if ((*iter)->m_Interval < time_left)
|
||||
{
|
||||
pTimer->m_InExec = true;
|
||||
pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||
iter = m_MapEndTimers.erase(iter);
|
||||
m_FreeTimers.push(pTimer);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResultType res;
|
||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
|
||||
{
|
||||
@ -156,26 +169,40 @@ ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void
|
||||
goto return_timer;
|
||||
}
|
||||
|
||||
if (m_SingleTimers.size() >= 1)
|
||||
if (flags & TIMER_FLAG_BEFORE_MAP_END)
|
||||
{
|
||||
iter = --m_SingleTimers.end();
|
||||
if ((*iter)->m_ToExec <= to_exec)
|
||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
|
||||
{
|
||||
goto insert_end;
|
||||
if (fInterval >= (*iter)->m_Interval)
|
||||
{
|
||||
m_MapEndTimers.insert(iter, pTimer);
|
||||
goto return_timer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
||||
{
|
||||
if ((*iter)->m_ToExec >= to_exec)
|
||||
m_MapEndTimers.push_back(pTimer);
|
||||
} else {
|
||||
if (m_SingleTimers.size() >= 1)
|
||||
{
|
||||
m_SingleTimers.insert(iter, pTimer);
|
||||
goto return_timer;
|
||||
iter = --m_SingleTimers.end();
|
||||
if ((*iter)->m_ToExec <= to_exec)
|
||||
{
|
||||
goto normal_insert_end;
|
||||
}
|
||||
}
|
||||
|
||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
||||
{
|
||||
if ((*iter)->m_ToExec >= to_exec)
|
||||
{
|
||||
m_SingleTimers.insert(iter, pTimer);
|
||||
goto return_timer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insert_end:
|
||||
m_SingleTimers.push_back(pTimer);
|
||||
normal_insert_end:
|
||||
m_SingleTimers.push_back(pTimer);
|
||||
}
|
||||
|
||||
return_timer:
|
||||
return pTimer;
|
||||
@ -196,7 +223,12 @@ void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
|
||||
if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
|
||||
{
|
||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||
m_SingleTimers.remove(pTimer);
|
||||
if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END)
|
||||
{
|
||||
m_MapEndTimers.remove(pTimer);
|
||||
} else {
|
||||
m_SingleTimers.remove(pTimer);
|
||||
}
|
||||
m_FreeTimers.push(pTimer);
|
||||
} else {
|
||||
if ((res != Pl_Stop) && !pTimer->m_KillMe)
|
||||
@ -232,7 +264,14 @@ void TimerSystem::KillTimer(ITimer *pTimer)
|
||||
pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
|
||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||
|
||||
pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
|
||||
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
||||
{
|
||||
m_LoopTimers.remove(pTimer);
|
||||
} else if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END) {
|
||||
m_MapEndTimers.remove(pTimer);
|
||||
} else {
|
||||
m_SingleTimers.remove(pTimer);
|
||||
}
|
||||
|
||||
pList->remove(pTimer);
|
||||
m_FreeTimers.push(pTimer);
|
||||
@ -266,6 +305,15 @@ void TimerSystem::MapChange(bool real_mapchange)
|
||||
}
|
||||
}
|
||||
|
||||
if (real_mapchange)
|
||||
{
|
||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
|
||||
{
|
||||
pTimer = (*iter);
|
||||
s_tokill.push(pTimer);
|
||||
}
|
||||
}
|
||||
|
||||
while (!s_tokill.empty())
|
||||
{
|
||||
KillTimer(s_tokill.front());
|
||||
@ -274,3 +322,11 @@ void TimerSystem::MapChange(bool real_mapchange)
|
||||
|
||||
m_LastExecTime = GetSimulatedTime();
|
||||
}
|
||||
|
||||
SM_TIMELEFT_FUNCTION TimerSystem::SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn)
|
||||
{
|
||||
SM_TIMELEFT_FUNCTION old = m_fnTimeLeft;
|
||||
m_fnTimeLeft = fn;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
@ -44,13 +44,6 @@ using namespace SourceMod;
|
||||
typedef List<ITimer *> TimerList;
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -77,19 +70,22 @@ public: //ITimerSystem
|
||||
ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
|
||||
void KillTimer(ITimer *pTimer);
|
||||
void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
|
||||
SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn);
|
||||
public:
|
||||
void RunFrame();
|
||||
void MapChange(bool real_mapchange);
|
||||
private:
|
||||
List<ITimer *> m_SingleTimers;
|
||||
List<ITimer *> m_LoopTimers;
|
||||
List<ITimer *> m_MapEndTimers;
|
||||
CStack<ITimer *> m_FreeTimers;
|
||||
float m_LastExecTime;
|
||||
SM_TIMELEFT_FUNCTION m_fnTimeLeft;
|
||||
};
|
||||
|
||||
time_t GetAdjustedTime(time_t *buf = NULL);
|
||||
|
||||
extern TimerSystem g_Timers;
|
||||
extern TickInfo g_SimTicks;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
||||
|
||||
|
@ -248,12 +248,7 @@ static cell_t smn_TriggerTimer(IPluginContext *pCtx, const cell_t *params)
|
||||
|
||||
static cell_t smn_GetTickedTime(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *simulating;
|
||||
pContext->LocalToPhysAddr(params[1], &simulating);
|
||||
|
||||
*simulating = g_SimTicks.ticking ? 0 : 1;
|
||||
|
||||
float t = g_SimTicks.ticking ? gpGlobals->curtime : g_SimTicks.ticktime;
|
||||
float t = engine->Time();
|
||||
return sp_ftoc(t);
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,6 @@ float g_LastAuthCheck = 0.0f;
|
||||
IForward *g_pOnGameFrame = NULL;
|
||||
IForward *g_pOnMapEnd = NULL;
|
||||
bool g_Loaded = false;
|
||||
int g_StillFrames = 0;
|
||||
float g_StillTime = 0.0f;
|
||||
IExtension *g_pGameExt = NULL;
|
||||
|
||||
typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
|
||||
@ -335,10 +333,6 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
|
||||
g_LastTime = 0.0f;
|
||||
g_LastMenuTime = 0.0f;
|
||||
g_LastAuthCheck = 0.0f;
|
||||
g_SimTicks.ticking = true;
|
||||
g_SimTicks.tickcount = 0;
|
||||
g_StillTime = 0.0f;
|
||||
g_StillFrames = 0;
|
||||
|
||||
/* Notify! */
|
||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||
@ -375,27 +369,6 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
|
||||
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(false);
|
||||
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)
|
||||
{
|
||||
g_DBMan.RunFrame();
|
||||
@ -405,46 +378,7 @@ void SourceModBase::GameFrame(bool simulating)
|
||||
* Note: This is all hardcoded rather than delegated to save
|
||||
* precious CPU cycles.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
float curtime = engine->Time();
|
||||
|
||||
if (curtime - g_LastTime >= 0.1f)
|
||||
{
|
||||
@ -459,7 +393,7 @@ void SourceModBase::GameFrame(bool simulating)
|
||||
g_LastTime = curtime;
|
||||
}
|
||||
|
||||
if (g_SimTicks.ticking && curtime - g_LastMenuTime >= 1.0f)
|
||||
if (gpGlobals->curtime - g_LastMenuTime >= 1.0f)
|
||||
{
|
||||
g_ValveMenuStyle.ProcessWatchList();
|
||||
g_RadioMenuStyle.ProcessWatchList();
|
||||
|
@ -48,6 +48,8 @@ namespace SourceMod
|
||||
{
|
||||
class ITimer;
|
||||
|
||||
typedef float (*SM_TIMELEFT_FUNCTION)();
|
||||
|
||||
/**
|
||||
* @brief Event callbacks for when a timer is executed.
|
||||
*/
|
||||
@ -74,6 +76,10 @@ namespace SourceMod
|
||||
|
||||
#define TIMER_FLAG_REPEAT (1<<0) /**< Timer will repeat until stopped */
|
||||
#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
|
||||
#define TIMER_FLAG_BEFORE_MAP_END (1<<2) /**< Timer will fire <interval> seconds before map end.
|
||||
This flag is cannot be used with REPEAT,
|
||||
and TIMER_FLAG_NO_MAPCHANGE is implied.
|
||||
*/
|
||||
|
||||
class ITimerSystem : public SMInterface
|
||||
{
|
||||
@ -95,7 +101,8 @@ namespace SourceMod
|
||||
* The smallest allowed interval is 0.1 seconds.
|
||||
* @param pData Private data to pass on to the timer.
|
||||
* @param flags Extra flags to pass on to the timer.
|
||||
* @return An ITimer pointer on success, NULL on failure.
|
||||
* @return An ITimer pointer on success, NULL on
|
||||
* failure.
|
||||
*/
|
||||
virtual ITimer *CreateTimer(ITimedEvent *pCallbacks,
|
||||
float fInterval,
|
||||
@ -116,11 +123,21 @@ namespace SourceMod
|
||||
*
|
||||
* @param pTimer Pointer to the ITimer structure.
|
||||
* @param delayExec If true, and the timer is repeating, the
|
||||
* next execution will be delayed by its interval.
|
||||
* next execution will be delayed by its
|
||||
* interval.
|
||||
* @return
|
||||
*/
|
||||
virtual void FireTimerOnce(ITimer *pTimer, bool delayExec=false) =0;
|
||||
|
||||
/**
|
||||
* @brief Sets the function which is used to find the time left in the map.
|
||||
*
|
||||
* @param fn Function that returns the time left in seconds.
|
||||
* @return The previous SM_TIMELEFT_FUNCTION pointer.
|
||||
*/
|
||||
virtual SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn) =0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TIMER_SYSTEM_H_
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user