1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/CTimerSys.cpp Sat Mar 10 13:16:19 2007 +0000
1.3 @@ -0,0 +1,199 @@
1.4 +/**
1.5 +* vim: set ts=4 :
1.6 +* ===============================================================
1.7 +* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.8 +* ===============================================================
1.9 +*
1.10 +* This file is not open source and may not be copied without explicit
1.11 +* written permission of AlliedModders LLC. This file may not be redistributed
1.12 +* in whole or significant part.
1.13 +* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
1.14 +*
1.15 +* Version: $Id$
1.16 +*/
1.17 +
1.18 +#include "CTimerSys.h"
1.19 +
1.20 +CTimerSystem g_Timers;
1.21 +
1.22 +void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
1.23 +{
1.24 + m_Listener = pCallbacks;
1.25 + m_Interval = fInterval;
1.26 + m_ToExec = fToExec;
1.27 + m_pData = pData;
1.28 + m_Flags = flags;
1.29 + m_InExec = false;
1.30 + m_KillMe = false;
1.31 +}
1.32 +
1.33 +void CTimerSystem::OnSourceModAllInitialized()
1.34 +{
1.35 + g_ShareSys.AddInterface(NULL, this);
1.36 +}
1.37 +
1.38 +void CTimerSystem::RunFrame()
1.39 +{
1.40 + ITimer *pTimer;
1.41 + TimerIter iter;
1.42 +
1.43 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
1.44 + {
1.45 + pTimer = (*iter);
1.46 + if (gpGlobals->curtime >= pTimer->m_ToExec)
1.47 + {
1.48 + pTimer->m_InExec = true;
1.49 + pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.50 + if (pTimer->m_KillMe)
1.51 + {
1.52 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.53 + }
1.54 + iter = m_SingleTimers.erase(iter);
1.55 + m_FreeTimers.push(pTimer);
1.56 + } else {
1.57 + break;
1.58 + }
1.59 + }
1.60 +
1.61 + ResultType res;
1.62 + for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
1.63 + {
1.64 + pTimer = (*iter);
1.65 + if (gpGlobals->curtime >= pTimer->m_ToExec)
1.66 + {
1.67 + pTimer->m_InExec = true;
1.68 + res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.69 + if (pTimer->m_KillMe || (res == Pl_Stop))
1.70 + {
1.71 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.72 + iter = m_LoopTimers.erase(iter);
1.73 + m_FreeTimers.push(pTimer);
1.74 + continue;
1.75 + }
1.76 + pTimer->m_InExec = false;
1.77 + pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.78 + }
1.79 + iter++;
1.80 + }
1.81 +
1.82 + m_LastExecTime = gpGlobals->curtime;
1.83 +}
1.84 +
1.85 +ITimer *CTimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
1.86 +{
1.87 + ITimer *pTimer;
1.88 + TimerIter iter;
1.89 + float to_exec = gpGlobals->curtime + fInterval;
1.90 +
1.91 + if (m_FreeTimers.empty())
1.92 + {
1.93 + pTimer = new ITimer;
1.94 + } else {
1.95 + pTimer = m_FreeTimers.front();
1.96 + m_FreeTimers.pop();
1.97 + }
1.98 +
1.99 + pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
1.100 +
1.101 + if (flags & TIMER_FLAG_REPEAT)
1.102 + {
1.103 + m_LoopTimers.push_back(pTimer);
1.104 + goto return_timer;
1.105 + }
1.106 +
1.107 + if (m_SingleTimers.size() >= 1)
1.108 + {
1.109 + iter = --m_SingleTimers.end();
1.110 + if ((*iter)->m_ToExec <= to_exec)
1.111 + {
1.112 + goto insert_end;
1.113 + }
1.114 + }
1.115 +
1.116 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
1.117 + {
1.118 + if ((*iter)->m_ToExec >= to_exec)
1.119 + {
1.120 + m_SingleTimers.insert(iter, pTimer);
1.121 + goto return_timer;
1.122 + }
1.123 + }
1.124 +
1.125 +insert_end:
1.126 + m_SingleTimers.push_back(pTimer);
1.127 +
1.128 +return_timer:
1.129 + return pTimer;
1.130 +}
1.131 +
1.132 +void CTimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
1.133 +{
1.134 + ResultType res;
1.135 +
1.136 + if (pTimer->m_InExec)
1.137 + {
1.138 + return;
1.139 + }
1.140 +
1.141 + pTimer->m_InExec = true;
1.142 + res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.143 +
1.144 + if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
1.145 + {
1.146 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.147 + m_SingleTimers.remove(pTimer);
1.148 + m_FreeTimers.push(pTimer);
1.149 + } else {
1.150 + if (delayExec && (res != Pl_Stop) && !pTimer->m_KillMe)
1.151 + {
1.152 + pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.153 + pTimer->m_InExec = false;
1.154 + return;
1.155 + }
1.156 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.157 + m_LoopTimers.remove(pTimer);
1.158 + m_FreeTimers.push(pTimer);
1.159 + }
1.160 +}
1.161 +
1.162 +void CTimerSystem::KillTimer(ITimer *pTimer)
1.163 +{
1.164 + TimerList *pList;
1.165 +
1.166 + if (pTimer->m_KillMe)
1.167 + {
1.168 + return;
1.169 + }
1.170 +
1.171 + if (pTimer->m_InExec)
1.172 + {
1.173 + pTimer->m_KillMe = true;
1.174 + return;
1.175 + }
1.176 +
1.177 + pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
1.178 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.179 +
1.180 + pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
1.181 +
1.182 + pList->remove(pTimer);
1.183 + m_FreeTimers.push(pTimer);
1.184 +}
1.185 +
1.186 +void CTimerSystem::MapChange()
1.187 +{
1.188 + ITimer *pTimer;
1.189 + TimerIter iter;
1.190 +
1.191 + for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
1.192 + {
1.193 + pTimer = (*iter);
1.194 + pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
1.195 + }
1.196 +
1.197 + for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
1.198 + {
1.199 + pTimer = (*iter);
1.200 + pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
1.201 + }
1.202 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/core/CTimerSys.h Sat Mar 10 13:16:19 2007 +0000
2.3 @@ -0,0 +1,65 @@
2.4 +/**
2.5 +* vim: set ts=4 :
2.6 +* ===============================================================
2.7 +* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
2.8 +* ===============================================================
2.9 +*
2.10 +* This file is not open source and may not be copied without explicit
2.11 +* written permission of AlliedModders LLC. This file may not be redistributed
2.12 +* in whole or significant part.
2.13 +* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
2.14 +*
2.15 +* Version: $Id$
2.16 +*/
2.17 +
2.18 +#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
2.19 +#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
2.20 +
2.21 +#include "ShareSys.h"
2.22 +#include <ITimerSystem.h>
2.23 +#include <sh_stack.h>
2.24 +#include <sh_list.h>
2.25 +#include "sourcemm_api.h"
2.26 +
2.27 +using namespace SourceHook;
2.28 +using namespace SourceMod;
2.29 +
2.30 +typedef List<ITimer *> TimerList;
2.31 +typedef List<ITimer *>::iterator TimerIter;
2.32 +
2.33 +class SourceMod::ITimer
2.34 +{
2.35 +public:
2.36 + void Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags);
2.37 + ITimedEvent *m_Listener;
2.38 + void *m_pData;
2.39 + float m_Interval;
2.40 + float m_ToExec;
2.41 + int m_Flags;
2.42 + bool m_InExec;
2.43 + bool m_KillMe;
2.44 +};
2.45 +
2.46 +class CTimerSystem :
2.47 + public ITimerSystem,
2.48 + public SMGlobalClass
2.49 +{
2.50 +public: //SMGlobalClass
2.51 + void OnSourceModAllInitialized();
2.52 +public: //ITimerSystem
2.53 + ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
2.54 + void KillTimer(ITimer *pTimer);
2.55 + void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
2.56 +public:
2.57 + void RunFrame();
2.58 + void MapChange();
2.59 +private:
2.60 + List<ITimer *> m_SingleTimers;
2.61 + List<ITimer *> m_LoopTimers;
2.62 + CStack<ITimer *> m_FreeTimers;
2.63 + float m_LastExecTime;
2.64 +};
2.65 +
2.66 +extern CTimerSystem g_Timers;
2.67 +
2.68 +#endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_
3.1 --- a/core/msvc8/sourcemod_mm.vcproj Sat Mar 10 05:52:51 2007 +0000
3.2 +++ b/core/msvc8/sourcemod_mm.vcproj Sat Mar 10 13:16:19 2007 +0000
3.3 @@ -1,7 +1,7 @@
3.4 <?xml version="1.0" encoding="Windows-1252"?>
3.5 <VisualStudioProject
3.6 ProjectType="Visual C++"
3.7 - Version="8.00"
3.8 + Version="8,00"
3.9 Name="sourcemod_mm"
3.10 ProjectGUID="{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
3.11 RootNamespace="sourcemod_mm"
3.12 @@ -220,6 +220,10 @@
3.13 >
3.14 </File>
3.15 <File
3.16 + RelativePath="..\CTimerSys.cpp"
3.17 + >
3.18 + </File>
3.19 + <File
3.20 RelativePath="..\CTranslator.cpp"
3.21 >
3.22 </File>
3.23 @@ -314,6 +318,10 @@
3.24 >
3.25 </File>
3.26 <File
3.27 + RelativePath="..\CTimerSys.h"
3.28 + >
3.29 + </File>
3.30 + <File
3.31 RelativePath="..\CTranslator.h"
3.32 >
3.33 </File>
3.34 @@ -422,6 +430,10 @@
3.35 >
3.36 </File>
3.37 <File
3.38 + RelativePath="..\..\public\ITimerSystem.h"
3.39 + >
3.40 + </File>
3.41 + <File
3.42 RelativePath="..\..\public\IUserMessages.h"
3.43 >
3.44 </File>
4.1 --- a/core/sourcemod.cpp Sat Mar 10 05:52:51 2007 +0000
4.2 +++ b/core/sourcemod.cpp Sat Mar 10 13:16:19 2007 +0000
4.3 @@ -26,6 +26,7 @@
4.4 #include "CPlayerManager.h"
4.5 #include "CTranslator.h"
4.6 #include "ForwardSys.h"
4.7 +#include "CTimerSys.h"
4.8
4.9 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
4.10 SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
4.11 @@ -193,6 +194,7 @@
4.12 g_LastAuthCheck = 0.0f;
4.13
4.14 g_Logger.MapChange(pMapName);
4.15 + g_Timers.MapChange();
4.16
4.17 /* Refresh language stuff */
4.18 char path[PLATFORM_MAX_PATH];
4.19 @@ -221,7 +223,7 @@
4.20 * precious CPU cycles.
4.21 */
4.22 float curtime = gpGlobals->curtime;
4.23 - if (curtime - g_LastTime > 0.1f)
4.24 + if (curtime - g_LastTime >= 0.1f)
4.25 {
4.26 if (m_CheckingAuth
4.27 && (gpGlobals->curtime - g_LastAuthCheck > 0.7f))
4.28 @@ -229,9 +231,11 @@
4.29 g_LastAuthCheck = gpGlobals->curtime;
4.30 g_Players.RunAuthChecks();
4.31 }
4.32 +
4.33 + g_Timers.RunFrame();
4.34 g_LastTime = curtime;
4.35 }
4.36 -
4.37 +
4.38 if (g_pOnGameFrame && g_pOnGameFrame->GetFunctionCount())
4.39 {
4.40 g_pOnGameFrame->Execute(NULL);
5.1 --- a/public/ITimerSystem.h Sat Mar 10 05:52:51 2007 +0000
5.2 +++ b/public/ITimerSystem.h Sat Mar 10 13:16:19 2007 +0000
5.3 @@ -20,11 +20,10 @@
5.4 #define _INCLUDE_SOURCEMOD_TIMER_SYSTEM_H_
5.5
5.6 #include <IShareSys.h>
5.7 +#include <IForwardSys.h>
5.8
5.9 -//:TODO: this is a placeholder and not yet implemented
5.10 -//remove these lines and uncomment once we're done!
5.11 -//#define SMINTERFACE_TIMERSYS_NAME "ITimerSys"
5.12 -//#define SMINTERFACE_TIMERSYS_VERSION 1
5.13 +#define SMINTERFACE_TIMERSYS_NAME "ITimerSys"
5.14 +#define SMINTERFACE_TIMERSYS_VERSION 1
5.15
5.16 namespace SourceMod
5.17 {
5.18 @@ -41,9 +40,7 @@
5.19 *
5.20 * @param pTimer Pointer to the timer instance.
5.21 * @param pData Private pointer passed from host.
5.22 - * @return Pl_Handle to stop timer, Pl_Continue to continue.
5.23 - * Passing Pl_Continue when a timer's repeat count
5.24 - * has been exhausted will not extend it.
5.25 + * @return Pl_Stop to stop timer, Pl_Continue to continue.
5.26 */
5.27 virtual ResultType OnTimer(ITimer *pTimer, void *pData) =0;
5.28
5.29 @@ -53,7 +50,7 @@
5.30 * @param pTimer Pointer to the timer instance.
5.31 * @param pData Private data pointer passed from host.
5.32 */
5.33 - virtual void OnTimerEnd() =0;
5.34 + virtual void OnTimerEnd(ITimer *pTimer, void *pData) =0;
5.35 };
5.36
5.37 #define TIMER_FLAG_REPEAT (1<<0)