1.1 --- a/core/TimerSys.cpp Wed Mar 14 07:54:54 2007 +0000
1.2 +++ b/core/TimerSys.cpp Wed Mar 14 11:34:03 2007 +0000
1.3 @@ -44,10 +44,7 @@
1.4 {
1.5 pTimer->m_InExec = true;
1.6 pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
1.7 - if (pTimer->m_KillMe)
1.8 - {
1.9 - pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.10 - }
1.11 + pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
1.12 iter = m_SingleTimers.erase(iter);
1.13 m_FreeTimers.push(pTimer);
1.14 } else {
1.15 @@ -144,9 +141,12 @@
1.16 m_SingleTimers.remove(pTimer);
1.17 m_FreeTimers.push(pTimer);
1.18 } else {
1.19 - if (delayExec && (res != Pl_Stop) && !pTimer->m_KillMe)
1.20 + if ((res != Pl_Stop) && !pTimer->m_KillMe)
1.21 {
1.22 - pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.23 + if (delayExec)
1.24 + {
1.25 + pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
1.26 + }
1.27 pTimer->m_InExec = false;
1.28 return;
1.29 }
2.1 --- a/core/msvc8/sourcemod_mm.vcproj Wed Mar 14 07:54:54 2007 +0000
2.2 +++ b/core/msvc8/sourcemod_mm.vcproj Wed Mar 14 11:34:03 2007 +0000
2.3 @@ -754,6 +754,10 @@
2.4 >
2.5 </File>
2.6 <File
2.7 + RelativePath="..\smn_timers.cpp"
2.8 + >
2.9 + </File>
2.10 + <File
2.11 RelativePath="..\smn_usermsgs.cpp"
2.12 >
2.13 </File>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/core/smn_timers.cpp Wed Mar 14 11:34:03 2007 +0000
3.3 @@ -0,0 +1,222 @@
3.4 +/**
3.5 +* ===============================================================
3.6 +* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
3.7 +* ===============================================================
3.8 +*
3.9 +* This file is not open source and may not be copied without explicit
3.10 +* written permission of AlliedModders LLC. This file may not be redistributed
3.11 +* in whole or significant part.
3.12 +* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
3.13 +*
3.14 +* Version: $Id$
3.15 +*/
3.16 +
3.17 +#include "HandleSys.h"
3.18 +#include "TimerSys.h"
3.19 +#include "Logger.h"
3.20 +
3.21 +#define TIMER_HNDL_CLOSE (1<<9)
3.22 +
3.23 +HandleType_t g_TimerType;
3.24 +
3.25 +struct TimerInfo
3.26 +{
3.27 + ITimer *Timer;
3.28 + IPluginFunction *Hook;
3.29 + IPluginContext *pContext;
3.30 + Handle_t TimerHandle;
3.31 + int UserData;
3.32 + int Flags;
3.33 +};
3.34 +
3.35 +class TimerNatives :
3.36 + public SMGlobalClass,
3.37 + public IHandleTypeDispatch,
3.38 + public ITimedEvent
3.39 +{
3.40 +public: //ITimedEvent
3.41 + ResultType OnTimer(ITimer *pTimer, void *pData);
3.42 + void OnTimerEnd(ITimer *pTimer, void *pData);
3.43 +public: //IHandleTypeDispatch
3.44 + void OnHandleDestroy(HandleType_t type, void *object);
3.45 +public: //SMGlobalClass
3.46 + void OnSourceModAllInitialized();
3.47 + void OnSourceModShutdown();
3.48 +public:
3.49 + TimerInfo *CreateTimerInfo();
3.50 + void DeleteTimerInfo(TimerInfo *pInfo);
3.51 +private:
3.52 + CStack<TimerInfo *> m_FreeTimers;
3.53 +};
3.54 +
3.55 +void TimerNatives::OnSourceModAllInitialized()
3.56 +{
3.57 + HandleAccess sec;
3.58 + sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
3.59 +
3.60 + g_TimerType = g_HandleSys.CreateType("Timer", this, 0, NULL, &sec, g_pCoreIdent, NULL);
3.61 +}
3.62 +
3.63 +void TimerNatives::OnSourceModShutdown()
3.64 +{
3.65 + g_HandleSys.RemoveType(g_TimerType, g_pCoreIdent);
3.66 + g_TimerType = 0;
3.67 +}
3.68 +
3.69 +void TimerNatives::OnHandleDestroy(HandleType_t type, void *object)
3.70 +{
3.71 + TimerInfo *pTimer = reinterpret_cast<TimerInfo *>(object);
3.72 +
3.73 + g_Timers.KillTimer(pTimer->Timer);
3.74 +}
3.75 +
3.76 +TimerInfo *TimerNatives::CreateTimerInfo()
3.77 +{
3.78 + TimerInfo *pInfo;
3.79 +
3.80 + if (m_FreeTimers.empty())
3.81 + {
3.82 + pInfo = new TimerInfo;
3.83 + } else {
3.84 + pInfo = m_FreeTimers.front();
3.85 + m_FreeTimers.pop();
3.86 + }
3.87 +
3.88 + return pInfo;
3.89 +}
3.90 +
3.91 +void TimerNatives::DeleteTimerInfo(TimerInfo *pInfo)
3.92 +{
3.93 + m_FreeTimers.push(pInfo);
3.94 +}
3.95 +
3.96 +ResultType TimerNatives::OnTimer(ITimer *pTimer, void *pData)
3.97 +{
3.98 + TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
3.99 + IPluginFunction *pFunc = pInfo->Hook;
3.100 + cell_t res = static_cast<ResultType>(Pl_Continue);
3.101 +
3.102 + pFunc->PushCell(pInfo->TimerHandle);
3.103 + pFunc->PushCell(pInfo->UserData);
3.104 + pFunc->Execute(&res);
3.105 +
3.106 + return static_cast<ResultType>(res);
3.107 +}
3.108 +
3.109 +void TimerNatives::OnTimerEnd(ITimer *pTimer, void *pData)
3.110 +{
3.111 + HandleSecurity sec;
3.112 + HandleError herr;
3.113 + TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
3.114 + Handle_t usrhndl = static_cast<Handle_t>(pInfo->UserData);
3.115 +
3.116 + sec.pOwner = pInfo->pContext->GetIdentity();
3.117 + sec.pIdentity = g_pCoreIdent;
3.118 +
3.119 + if (pInfo->Flags & TIMER_HNDL_CLOSE)
3.120 + {
3.121 + if ((herr=g_HandleSys.FreeHandle(usrhndl, &sec)) != HandleError_None)
3.122 + {
3.123 + g_Logger.LogError("Invalid data handle %x (error %d) passed during timer end", usrhndl, herr);
3.124 + }
3.125 + }
3.126 +
3.127 + g_HandleSys.FreeHandle(pInfo->TimerHandle, &sec);
3.128 +}
3.129 +
3.130 +/*******************************
3.131 +* *
3.132 +* TIMER NATIVE IMPLEMENTATIONS *
3.133 +* *
3.134 +********************************/
3.135 +
3.136 +static TimerNatives s_TimerNatives;
3.137 +
3.138 +static cell_t smn_CreateTimer(IPluginContext *pCtx, const cell_t *params)
3.139 +{
3.140 + IPluginFunction *pFunc;
3.141 + TimerInfo *pInfo;
3.142 + ITimer *pTimer;
3.143 + Handle_t hndl;
3.144 + int flags = params[4];
3.145 +
3.146 + pFunc = pCtx->GetFunctionById(params[2]);
3.147 + if (!pFunc)
3.148 + {
3.149 + return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
3.150 + }
3.151 +
3.152 + pInfo = s_TimerNatives.CreateTimerInfo();
3.153 + pTimer = g_Timers.CreateTimer(&s_TimerNatives, sp_ctof(params[1]), pInfo, flags);
3.154 + hndl = g_HandleSys.CreateHandle(g_TimerType, pInfo, pCtx->GetIdentity(), g_pCoreIdent, NULL);
3.155 +
3.156 + pInfo->UserData = params[3];
3.157 + pInfo->Flags = flags;
3.158 + pInfo->TimerHandle = hndl;
3.159 + pInfo->Hook = pFunc;
3.160 + pInfo->Timer = pTimer;
3.161 + pInfo->pContext = pCtx;
3.162 +
3.163 + return hndl;
3.164 +}
3.165 +
3.166 +static cell_t smn_KillTimer(IPluginContext *pCtx, const cell_t *params)
3.167 +{
3.168 + Handle_t hndl = static_cast<Handle_t>(params[1]);
3.169 + HandleError herr;
3.170 + HandleSecurity sec;
3.171 + TimerInfo *pInfo;
3.172 +
3.173 + sec.pOwner = NULL;
3.174 + sec.pIdentity = g_pCoreIdent;
3.175 +
3.176 + if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
3.177 + != HandleError_None)
3.178 + {
3.179 + return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
3.180 + }
3.181 +
3.182 + g_Timers.KillTimer(pInfo->Timer);
3.183 +
3.184 + if (params[2] && !(pInfo->Flags & TIMER_HNDL_CLOSE))
3.185 + {
3.186 + sec.pOwner = pInfo->pContext->GetIdentity();
3.187 + sec.pIdentity = g_pCoreIdent;
3.188 +
3.189 + if ((herr=g_HandleSys.FreeHandle(static_cast<Handle_t>(pInfo->UserData), &sec)) != HandleError_None)
3.190 + {
3.191 + return pCtx->ThrowNativeError("Invalid data handle %x (error %d)", hndl, herr);
3.192 + }
3.193 + }
3.194 +
3.195 + return 1;
3.196 +}
3.197 +
3.198 +static cell_t smn_TriggerTimer(IPluginContext *pCtx, const cell_t *params)
3.199 +{
3.200 + Handle_t hndl = static_cast<Handle_t>(params[1]);
3.201 + HandleError herr;
3.202 + HandleSecurity sec;
3.203 + TimerInfo *pInfo;
3.204 +
3.205 + sec.pOwner = NULL;
3.206 + sec.pIdentity = g_pCoreIdent;
3.207 +
3.208 + if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
3.209 + != HandleError_None)
3.210 + {
3.211 + return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
3.212 + }
3.213 +
3.214 + g_Timers.FireTimerOnce(pInfo->Timer, params[2] ? true : false);
3.215 +
3.216 + return 1;
3.217 +}
3.218 +
3.219 +REGISTER_NATIVES(timernatives)
3.220 +{
3.221 + {"CreateTimer", smn_CreateTimer},
3.222 + {"KillTimer", smn_KillTimer},
3.223 + {"TriggerTimer", smn_TriggerTimer},
3.224 + {NULL, NULL}
3.225 +};
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/plugins/include/timers.inc Wed Mar 14 11:34:03 2007 +0000
4.3 @@ -0,0 +1,107 @@
4.4 +/**
4.5 + * vim: set ts=4 :
4.6 + * ===============================================================
4.7 + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4.8 + * ===============================================================
4.9 + *
4.10 + * This file is part of the SourceMod/SourcePawn SDK. This file may only be used
4.11 + * or modified under the Terms and Conditions of its License Agreement, which is found
4.12 + * in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
4.13 + * may change at any time. To view the latest information, see:
4.14 + * http://www.sourcemod.net/license.php
4.15 + *
4.16 + * Version: $Id$
4.17 + */
4.18 +
4.19 +#if defined _timers_included
4.20 + #endinput
4.21 +#endif
4.22 +#define _timers_included
4.23 +
4.24 +#include <datapack>
4.25 +
4.26 +#define TIMER_REPEAT (1<<0) /**< Timer will repeat until it returns Plugin_Stop */
4.27 +#define TIMER_HNDL_CLOSE (1<<9) /**< Timer will automatically call CloseHandle() on its value when finished */
4.28 +
4.29 +/**
4.30 + * Any of the following prototypes will work for a timed function.
4.31 + */
4.32 +funcenum Timer
4.33 +{
4.34 + /**
4.35 + * Called when the timer interval has elapsed.
4.36 + *
4.37 + * @param timer Handle to the timer object.
4.38 + * @param hndl Handle passed when the timer was created.
4.39 + * @return Plugin_Stop to stop a repeating timer, any other value for
4.40 + * default behavior.
4.41 + */
4.42 + Action:public(Handle:timer, Handle:hndl),
4.43 +
4.44 + /**
4.45 + * Called when the timer interval has elapsed.
4.46 + *
4.47 + * @param timer Handle to the timer object.
4.48 + * @param value Value passed when the timer was created.
4.49 + * @return Plugin_Stop to stop a repeating timer, any other value for
4.50 + * default behavior.
4.51 + */
4.52 + Action:public(Handle:timer, value),
4.53 +
4.54 + /**
4.55 + * Called when the timer interval has elapsed.
4.56 + *
4.57 + * @param timer Handle to the timer object.
4.58 + * @return Plugin_Stop to stop a repeating timer, any other value for
4.59 + * default behavior.
4.60 + */
4.61 + Action:public(Handle:timer),
4.62 +};
4.63 +
4.64 +/**
4.65 + * Creates a basic timer. Calling CloseHandle() on a timer will end the timer.
4.66 + *
4.67 + * @param interval Interval from the current game time to execute the given function.
4.68 + * @param func Function to execute once the given interval has elapsed.
4.69 + * @param value Handle or value to give to the timer function.
4.70 + * @param flags Flags to set (such as repeatability or auto-Handle closing).
4.71 + * @return Handle to the timer object. You do not need to call CloseHandle().
4.72 + */
4.73 +native Handle:CreateTimer(Float:interval, Timer:func, {Handle,_}:value, flags);
4.74 +
4.75 +/**
4.76 + * Kills a timer. Use this instead of CloseHandle() if you need more options.
4.77 + *
4.78 + * @param autoClose If autoClose is true, the timer's value will be
4.79 + * closed as a handle if TIMER_HNDL_CLOSE was not specified.
4.80 + * @noreturn
4.81 + */
4.82 +native KillTimer(Handle:timer, bool:autoClose=false);
4.83 +
4.84 +/**
4.85 + * Manually triggers a timer so its function will be called.
4.86 + *
4.87 + * @param timer Timer Handle to trigger.
4.88 + * @param reset If reset is true, the elapsed time counter is reset
4.89 + * so the full interval must pass again.
4.90 + * @noreturn
4.91 + */
4.92 +native TriggerTimer(Handle:timer, bool:reset=false);
4.93 +
4.94 +/**
4.95 + * Creates a timer associated with a new data pack, and returns the datapack.
4.96 + * @note The datapack is automatically freed when the timer ends.
4.97 + * @note The position of the datapack is not reset or changed for the timer function.
4.98 + *
4.99 + * @param interval Interval from the current game time to execute the given function.
4.100 + * @param func Function to execute once the given interval has elapsed.
4.101 + * @param data The newly created datapack is passed though this by-reference parameter.
4.102 + * @param flags Timer flags.
4.103 + * @return Handle to the timer object. You do not need to call CloseHandle().
4.104 + */
4.105 +stock Handle:CreateDataTimer(Float:interval, Timer:func, &Handle:data, flags)
4.106 +{
4.107 + data = CreateDataPack();
4.108 + flags |= TIMER_HNDL_CLOSE;
4.109 + return CreateTimer(interval, func, data, flags);
4.110 +}