core/smn_timers.cpp
author David Anderson <dvander@alliedmods.net>
Mon Mar 19 01:44:09 2007 +0000 (2007-03-19)
changeset 647 1e29dcc9ca97
parent 641 ce1f369ba889
child 653 ef60870067ff
permissions -rw-r--r--
fixed a potential bug with kicking players during authorization
faluco@612
     1
/**
faluco@612
     2
* ===============================================================
faluco@612
     3
* SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
faluco@612
     4
* ===============================================================
faluco@612
     5
*
faluco@612
     6
* This file is not open source and may not be copied without explicit
faluco@612
     7
* written permission of AlliedModders LLC.  This file may not be redistributed 
faluco@612
     8
* in whole or significant part.
faluco@612
     9
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
faluco@612
    10
*
faluco@612
    11
* Version: $Id$
faluco@612
    12
*/
faluco@612
    13
faluco@612
    14
#include "HandleSys.h"
faluco@612
    15
#include "TimerSys.h"
faluco@612
    16
#include "Logger.h"
faluco@612
    17
faluco@612
    18
#define TIMER_HNDL_CLOSE	(1<<9)
faluco@612
    19
faluco@612
    20
HandleType_t g_TimerType;
faluco@612
    21
faluco@612
    22
struct TimerInfo 
faluco@612
    23
{
faluco@612
    24
	ITimer *Timer;
faluco@612
    25
	IPluginFunction *Hook;
faluco@612
    26
	IPluginContext *pContext;
faluco@612
    27
	Handle_t TimerHandle;
faluco@612
    28
	int UserData;
faluco@612
    29
	int Flags;
faluco@612
    30
};
faluco@612
    31
faluco@612
    32
class TimerNatives :
faluco@612
    33
	public SMGlobalClass,
faluco@612
    34
	public IHandleTypeDispatch,
faluco@612
    35
	public ITimedEvent
faluco@612
    36
{
faluco@641
    37
public:
faluco@641
    38
	~TimerNatives();
faluco@612
    39
public: //ITimedEvent
faluco@612
    40
	ResultType OnTimer(ITimer *pTimer, void *pData);
faluco@612
    41
	void OnTimerEnd(ITimer *pTimer, void *pData);
faluco@612
    42
public: //IHandleTypeDispatch
faluco@612
    43
	void OnHandleDestroy(HandleType_t type, void *object);
faluco@612
    44
public: //SMGlobalClass
faluco@612
    45
	void OnSourceModAllInitialized();
faluco@612
    46
	void OnSourceModShutdown();
faluco@612
    47
public:
faluco@612
    48
	TimerInfo *CreateTimerInfo();
faluco@612
    49
	void DeleteTimerInfo(TimerInfo *pInfo);
faluco@612
    50
private:
faluco@612
    51
	CStack<TimerInfo *> m_FreeTimers;
faluco@612
    52
};
faluco@612
    53
faluco@641
    54
TimerNatives::~TimerNatives()
faluco@641
    55
{
faluco@641
    56
	CStack<TimerInfo *>::iterator iter;
faluco@641
    57
	for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++)
faluco@641
    58
	{
faluco@641
    59
		delete (*iter);
faluco@641
    60
	}
faluco@641
    61
	m_FreeTimers.popall();
faluco@641
    62
}
faluco@641
    63
faluco@612
    64
void TimerNatives::OnSourceModAllInitialized()
faluco@612
    65
{
faluco@612
    66
	HandleAccess sec;
faluco@612
    67
	sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
faluco@612
    68
faluco@612
    69
	g_TimerType = g_HandleSys.CreateType("Timer", this, 0, NULL, &sec, g_pCoreIdent, NULL);
faluco@612
    70
}
faluco@612
    71
faluco@612
    72
void TimerNatives::OnSourceModShutdown()
faluco@612
    73
{
faluco@612
    74
	g_HandleSys.RemoveType(g_TimerType, g_pCoreIdent);
faluco@612
    75
	g_TimerType = 0;
faluco@612
    76
}
faluco@612
    77
faluco@612
    78
void TimerNatives::OnHandleDestroy(HandleType_t type, void *object)
faluco@612
    79
{
faluco@612
    80
	TimerInfo *pTimer = reinterpret_cast<TimerInfo *>(object);
faluco@612
    81
faluco@612
    82
	g_Timers.KillTimer(pTimer->Timer);
faluco@612
    83
}
faluco@612
    84
faluco@612
    85
TimerInfo *TimerNatives::CreateTimerInfo()
faluco@612
    86
{
faluco@612
    87
	TimerInfo *pInfo;
faluco@612
    88
faluco@612
    89
	if (m_FreeTimers.empty())
faluco@612
    90
	{
faluco@612
    91
		pInfo = new TimerInfo;
faluco@612
    92
	} else {
faluco@612
    93
		pInfo = m_FreeTimers.front();
faluco@612
    94
		m_FreeTimers.pop();
faluco@612
    95
	}
faluco@612
    96
faluco@612
    97
	return pInfo;
faluco@612
    98
}
faluco@612
    99
faluco@612
   100
void TimerNatives::DeleteTimerInfo(TimerInfo *pInfo)
faluco@612
   101
{
faluco@612
   102
	m_FreeTimers.push(pInfo);
faluco@612
   103
}
faluco@612
   104
faluco@612
   105
ResultType TimerNatives::OnTimer(ITimer *pTimer, void *pData)
faluco@612
   106
{
faluco@612
   107
	TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
faluco@612
   108
	IPluginFunction *pFunc = pInfo->Hook;
faluco@612
   109
	cell_t res = static_cast<ResultType>(Pl_Continue);
faluco@612
   110
faluco@612
   111
	pFunc->PushCell(pInfo->TimerHandle);
faluco@612
   112
	pFunc->PushCell(pInfo->UserData);
faluco@612
   113
	pFunc->Execute(&res);
faluco@612
   114
faluco@612
   115
	return static_cast<ResultType>(res);
faluco@612
   116
}
faluco@612
   117
faluco@612
   118
void TimerNatives::OnTimerEnd(ITimer *pTimer, void *pData)
faluco@612
   119
{
faluco@612
   120
	HandleSecurity sec;
faluco@612
   121
	HandleError herr;
faluco@612
   122
	TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
faluco@612
   123
	Handle_t usrhndl = static_cast<Handle_t>(pInfo->UserData);
faluco@612
   124
faluco@612
   125
	sec.pOwner = pInfo->pContext->GetIdentity();
faluco@612
   126
	sec.pIdentity = g_pCoreIdent;
faluco@612
   127
faluco@612
   128
	if (pInfo->Flags & TIMER_HNDL_CLOSE)
faluco@612
   129
	{
faluco@612
   130
		if ((herr=g_HandleSys.FreeHandle(usrhndl, &sec)) != HandleError_None)
faluco@612
   131
		{
faluco@612
   132
			g_Logger.LogError("Invalid data handle %x (error %d) passed during timer end", usrhndl, herr);
faluco@612
   133
		}
faluco@612
   134
	}
faluco@612
   135
faluco@612
   136
	g_HandleSys.FreeHandle(pInfo->TimerHandle, &sec);
faluco@613
   137
	DeleteTimerInfo(pInfo);
faluco@612
   138
}
faluco@612
   139
faluco@612
   140
/*******************************
faluco@612
   141
*                              *
faluco@612
   142
* TIMER NATIVE IMPLEMENTATIONS *
faluco@612
   143
*                              *
faluco@612
   144
********************************/
faluco@612
   145
faluco@612
   146
static TimerNatives s_TimerNatives;
faluco@612
   147
faluco@612
   148
static cell_t smn_CreateTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   149
{
faluco@612
   150
	IPluginFunction *pFunc;
faluco@612
   151
	TimerInfo *pInfo;
faluco@612
   152
	ITimer *pTimer;
faluco@612
   153
	Handle_t hndl;
faluco@612
   154
	int flags = params[4];
faluco@612
   155
faluco@612
   156
	pFunc = pCtx->GetFunctionById(params[2]);
faluco@612
   157
	if (!pFunc)
faluco@612
   158
	{
faluco@612
   159
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@612
   160
	}
faluco@612
   161
faluco@612
   162
	pInfo = s_TimerNatives.CreateTimerInfo();
faluco@612
   163
	pTimer = g_Timers.CreateTimer(&s_TimerNatives, sp_ctof(params[1]), pInfo, flags);
faluco@612
   164
	hndl = g_HandleSys.CreateHandle(g_TimerType, pInfo, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@612
   165
faluco@612
   166
	pInfo->UserData = params[3];
faluco@612
   167
	pInfo->Flags = flags;
faluco@612
   168
	pInfo->TimerHandle = hndl;
faluco@612
   169
	pInfo->Hook = pFunc;
faluco@612
   170
	pInfo->Timer = pTimer;
faluco@612
   171
	pInfo->pContext = pCtx;
faluco@612
   172
faluco@612
   173
	return hndl;
faluco@612
   174
}
faluco@612
   175
faluco@612
   176
static cell_t smn_KillTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   177
{
faluco@612
   178
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@612
   179
	HandleError herr;
faluco@612
   180
	HandleSecurity sec;
faluco@612
   181
	TimerInfo *pInfo;
faluco@612
   182
faluco@612
   183
	sec.pOwner = NULL;
faluco@612
   184
	sec.pIdentity = g_pCoreIdent;
faluco@612
   185
faluco@612
   186
	if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
faluco@612
   187
		!= HandleError_None)
faluco@612
   188
	{
faluco@612
   189
		return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
faluco@612
   190
	}
faluco@612
   191
faluco@612
   192
	g_Timers.KillTimer(pInfo->Timer);
faluco@612
   193
faluco@612
   194
	if (params[2] && !(pInfo->Flags & TIMER_HNDL_CLOSE))
faluco@612
   195
	{
faluco@612
   196
		sec.pOwner = pInfo->pContext->GetIdentity();
faluco@612
   197
		sec.pIdentity = g_pCoreIdent;
faluco@612
   198
faluco@612
   199
		if ((herr=g_HandleSys.FreeHandle(static_cast<Handle_t>(pInfo->UserData), &sec)) != HandleError_None)
faluco@612
   200
		{
faluco@612
   201
			return pCtx->ThrowNativeError("Invalid data handle %x (error %d)", hndl, herr);
faluco@612
   202
		}
faluco@612
   203
	}
faluco@612
   204
faluco@612
   205
	return 1;
faluco@612
   206
}
faluco@612
   207
faluco@612
   208
static cell_t smn_TriggerTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   209
{
faluco@612
   210
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@612
   211
	HandleError herr;
faluco@612
   212
	HandleSecurity sec;
faluco@612
   213
	TimerInfo *pInfo;
faluco@612
   214
faluco@612
   215
	sec.pOwner = NULL;
faluco@612
   216
	sec.pIdentity = g_pCoreIdent;
faluco@612
   217
faluco@612
   218
	if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
faluco@612
   219
		!= HandleError_None)
faluco@612
   220
	{
faluco@612
   221
		return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
faluco@612
   222
	}
faluco@612
   223
faluco@612
   224
	g_Timers.FireTimerOnce(pInfo->Timer, params[2] ? true : false);
faluco@612
   225
faluco@612
   226
	return 1;
faluco@612
   227
}
faluco@612
   228
faluco@612
   229
REGISTER_NATIVES(timernatives)
faluco@612
   230
{
faluco@612
   231
	{"CreateTimer",				smn_CreateTimer},
faluco@612
   232
	{"KillTimer",				smn_KillTimer},
faluco@612
   233
	{"TriggerTimer",			smn_TriggerTimer},
faluco@612
   234
	{NULL,						NULL}
faluco@612
   235
};