core/smn_timers.cpp
author David Anderson <dvander@alliedmods.net>
Wed Aug 01 02:12:47 2007 +0000 (2007-08-01)
changeset 1231 17badaf66ce4
parent 1008 57988eb475a1
child 1330 ab94316bb52b
permissions -rw-r--r--
updated more header files (mostly internal now)
faluco@612
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@1231
     3
 * ================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1231
     6
 * ================================================================
ds@653
     7
 *
dvander@1231
     8
 * This program is free software; you can redistribute it and/or 
dvander@1231
     9
 * modify it under the terms of the GNU General Public License, 
dvander@1231
    10
 * version 3.0, as published by the Free Software Foundation.
dvander@1231
    11
 * 
dvander@1231
    12
 * This program is distributed in the hope that it will be useful,
dvander@1231
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1231
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dvander@1231
    15
 * GNU General Public License for more details.
dvander@1231
    16
 *
dvander@1231
    17
 * You should have received a copy of the GNU General Public License
dvander@1231
    18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
dvander@1231
    20
 * As a special exception, AlliedModders LLC gives you permission to 
dvander@1231
    21
 * link the code of this program (as well as its derivative works) to 
dvander@1231
    22
 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
dvander@1231
    23
 * Game MODs that run on software by the Valve Corporation.  You must 
dvander@1231
    24
 * obey the GNU General Public License in all respects for all other 
dvander@1231
    25
 * code used. Additionally, AlliedModders LLC grants this exception 
dvander@1231
    26
 * to all derivative works. AlliedModders LLC defines further 
dvander@1231
    27
 * exceptions, found in LICENSE.txt (as of this writing, version 
dvander@1231
    28
 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
ds@653
    29
 *
ds@653
    30
 * Version: $Id$
ds@653
    31
 */
faluco@612
    32
faluco@612
    33
#include "HandleSys.h"
faluco@612
    34
#include "TimerSys.h"
faluco@612
    35
#include "Logger.h"
faluco@612
    36
faluco@612
    37
#define TIMER_HNDL_CLOSE	(1<<9)
faluco@612
    38
faluco@612
    39
HandleType_t g_TimerType;
faluco@612
    40
faluco@612
    41
struct TimerInfo 
faluco@612
    42
{
faluco@612
    43
	ITimer *Timer;
faluco@612
    44
	IPluginFunction *Hook;
faluco@612
    45
	IPluginContext *pContext;
faluco@612
    46
	Handle_t TimerHandle;
faluco@612
    47
	int UserData;
faluco@612
    48
	int Flags;
faluco@612
    49
};
faluco@612
    50
faluco@612
    51
class TimerNatives :
faluco@612
    52
	public SMGlobalClass,
faluco@612
    53
	public IHandleTypeDispatch,
faluco@612
    54
	public ITimedEvent
faluco@612
    55
{
faluco@641
    56
public:
faluco@641
    57
	~TimerNatives();
faluco@612
    58
public: //ITimedEvent
faluco@612
    59
	ResultType OnTimer(ITimer *pTimer, void *pData);
faluco@612
    60
	void OnTimerEnd(ITimer *pTimer, void *pData);
faluco@612
    61
public: //IHandleTypeDispatch
faluco@612
    62
	void OnHandleDestroy(HandleType_t type, void *object);
faluco@612
    63
public: //SMGlobalClass
faluco@612
    64
	void OnSourceModAllInitialized();
faluco@612
    65
	void OnSourceModShutdown();
faluco@612
    66
public:
faluco@612
    67
	TimerInfo *CreateTimerInfo();
faluco@612
    68
	void DeleteTimerInfo(TimerInfo *pInfo);
faluco@612
    69
private:
faluco@612
    70
	CStack<TimerInfo *> m_FreeTimers;
faluco@612
    71
};
faluco@612
    72
faluco@641
    73
TimerNatives::~TimerNatives()
faluco@641
    74
{
faluco@641
    75
	CStack<TimerInfo *>::iterator iter;
faluco@641
    76
	for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++)
faluco@641
    77
	{
faluco@641
    78
		delete (*iter);
faluco@641
    79
	}
faluco@641
    80
	m_FreeTimers.popall();
faluco@641
    81
}
faluco@641
    82
faluco@612
    83
void TimerNatives::OnSourceModAllInitialized()
faluco@612
    84
{
faluco@612
    85
	HandleAccess sec;
faluco@612
    86
	sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
faluco@612
    87
faluco@612
    88
	g_TimerType = g_HandleSys.CreateType("Timer", this, 0, NULL, &sec, g_pCoreIdent, NULL);
faluco@612
    89
}
faluco@612
    90
faluco@612
    91
void TimerNatives::OnSourceModShutdown()
faluco@612
    92
{
faluco@612
    93
	g_HandleSys.RemoveType(g_TimerType, g_pCoreIdent);
faluco@612
    94
	g_TimerType = 0;
faluco@612
    95
}
faluco@612
    96
faluco@612
    97
void TimerNatives::OnHandleDestroy(HandleType_t type, void *object)
faluco@612
    98
{
faluco@612
    99
	TimerInfo *pTimer = reinterpret_cast<TimerInfo *>(object);
faluco@612
   100
faluco@612
   101
	g_Timers.KillTimer(pTimer->Timer);
faluco@612
   102
}
faluco@612
   103
faluco@612
   104
TimerInfo *TimerNatives::CreateTimerInfo()
faluco@612
   105
{
faluco@612
   106
	TimerInfo *pInfo;
faluco@612
   107
faluco@612
   108
	if (m_FreeTimers.empty())
faluco@612
   109
	{
faluco@612
   110
		pInfo = new TimerInfo;
faluco@612
   111
	} else {
faluco@612
   112
		pInfo = m_FreeTimers.front();
faluco@612
   113
		m_FreeTimers.pop();
faluco@612
   114
	}
faluco@612
   115
faluco@612
   116
	return pInfo;
faluco@612
   117
}
faluco@612
   118
faluco@612
   119
void TimerNatives::DeleteTimerInfo(TimerInfo *pInfo)
faluco@612
   120
{
faluco@612
   121
	m_FreeTimers.push(pInfo);
faluco@612
   122
}
faluco@612
   123
faluco@612
   124
ResultType TimerNatives::OnTimer(ITimer *pTimer, void *pData)
faluco@612
   125
{
faluco@612
   126
	TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
faluco@612
   127
	IPluginFunction *pFunc = pInfo->Hook;
faluco@612
   128
	cell_t res = static_cast<ResultType>(Pl_Continue);
faluco@612
   129
faluco@612
   130
	pFunc->PushCell(pInfo->TimerHandle);
faluco@612
   131
	pFunc->PushCell(pInfo->UserData);
faluco@612
   132
	pFunc->Execute(&res);
faluco@612
   133
faluco@612
   134
	return static_cast<ResultType>(res);
faluco@612
   135
}
faluco@612
   136
faluco@612
   137
void TimerNatives::OnTimerEnd(ITimer *pTimer, void *pData)
faluco@612
   138
{
faluco@612
   139
	HandleSecurity sec;
faluco@612
   140
	HandleError herr;
faluco@612
   141
	TimerInfo *pInfo = reinterpret_cast<TimerInfo *>(pData);
faluco@612
   142
	Handle_t usrhndl = static_cast<Handle_t>(pInfo->UserData);
faluco@612
   143
faluco@612
   144
	sec.pOwner = pInfo->pContext->GetIdentity();
faluco@612
   145
	sec.pIdentity = g_pCoreIdent;
faluco@612
   146
faluco@612
   147
	if (pInfo->Flags & TIMER_HNDL_CLOSE)
faluco@612
   148
	{
faluco@612
   149
		if ((herr=g_HandleSys.FreeHandle(usrhndl, &sec)) != HandleError_None)
faluco@612
   150
		{
faluco@612
   151
			g_Logger.LogError("Invalid data handle %x (error %d) passed during timer end", usrhndl, herr);
faluco@612
   152
		}
faluco@612
   153
	}
faluco@612
   154
faluco@612
   155
	g_HandleSys.FreeHandle(pInfo->TimerHandle, &sec);
faluco@613
   156
	DeleteTimerInfo(pInfo);
faluco@612
   157
}
faluco@612
   158
faluco@612
   159
/*******************************
faluco@612
   160
*                              *
faluco@612
   161
* TIMER NATIVE IMPLEMENTATIONS *
faluco@612
   162
*                              *
faluco@612
   163
********************************/
faluco@612
   164
faluco@612
   165
static TimerNatives s_TimerNatives;
faluco@612
   166
faluco@612
   167
static cell_t smn_CreateTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   168
{
faluco@612
   169
	IPluginFunction *pFunc;
faluco@612
   170
	TimerInfo *pInfo;
faluco@612
   171
	ITimer *pTimer;
faluco@612
   172
	Handle_t hndl;
faluco@612
   173
	int flags = params[4];
faluco@612
   174
faluco@612
   175
	pFunc = pCtx->GetFunctionById(params[2]);
faluco@612
   176
	if (!pFunc)
faluco@612
   177
	{
faluco@612
   178
		return pCtx->ThrowNativeError("Invalid function id (%X)", params[2]);
faluco@612
   179
	}
faluco@612
   180
faluco@612
   181
	pInfo = s_TimerNatives.CreateTimerInfo();
faluco@612
   182
	pTimer = g_Timers.CreateTimer(&s_TimerNatives, sp_ctof(params[1]), pInfo, flags);
faluco@612
   183
	hndl = g_HandleSys.CreateHandle(g_TimerType, pInfo, pCtx->GetIdentity(), g_pCoreIdent, NULL);
faluco@612
   184
faluco@612
   185
	pInfo->UserData = params[3];
faluco@612
   186
	pInfo->Flags = flags;
faluco@612
   187
	pInfo->TimerHandle = hndl;
faluco@612
   188
	pInfo->Hook = pFunc;
faluco@612
   189
	pInfo->Timer = pTimer;
faluco@612
   190
	pInfo->pContext = pCtx;
faluco@612
   191
faluco@612
   192
	return hndl;
faluco@612
   193
}
faluco@612
   194
faluco@612
   195
static cell_t smn_KillTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   196
{
faluco@612
   197
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@612
   198
	HandleError herr;
faluco@612
   199
	HandleSecurity sec;
faluco@612
   200
	TimerInfo *pInfo;
faluco@612
   201
dvander@1008
   202
	sec.pOwner = pCtx->GetIdentity();
faluco@612
   203
	sec.pIdentity = g_pCoreIdent;
faluco@612
   204
faluco@612
   205
	if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
faluco@612
   206
		!= HandleError_None)
faluco@612
   207
	{
faluco@612
   208
		return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
faluco@612
   209
	}
faluco@612
   210
faluco@612
   211
	g_Timers.KillTimer(pInfo->Timer);
faluco@612
   212
faluco@612
   213
	if (params[2] && !(pInfo->Flags & TIMER_HNDL_CLOSE))
faluco@612
   214
	{
faluco@612
   215
		sec.pOwner = pInfo->pContext->GetIdentity();
faluco@612
   216
		sec.pIdentity = g_pCoreIdent;
faluco@612
   217
faluco@612
   218
		if ((herr=g_HandleSys.FreeHandle(static_cast<Handle_t>(pInfo->UserData), &sec)) != HandleError_None)
faluco@612
   219
		{
faluco@612
   220
			return pCtx->ThrowNativeError("Invalid data handle %x (error %d)", hndl, herr);
faluco@612
   221
		}
faluco@612
   222
	}
faluco@612
   223
faluco@612
   224
	return 1;
faluco@612
   225
}
faluco@612
   226
faluco@612
   227
static cell_t smn_TriggerTimer(IPluginContext *pCtx, const cell_t *params)
faluco@612
   228
{
faluco@612
   229
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@612
   230
	HandleError herr;
faluco@612
   231
	HandleSecurity sec;
faluco@612
   232
	TimerInfo *pInfo;
faluco@612
   233
faluco@612
   234
	sec.pOwner = NULL;
faluco@612
   235
	sec.pIdentity = g_pCoreIdent;
faluco@612
   236
faluco@612
   237
	if ((herr=g_HandleSys.ReadHandle(hndl, g_TimerType, &sec, (void **)&pInfo))
faluco@612
   238
		!= HandleError_None)
faluco@612
   239
	{
faluco@612
   240
		return pCtx->ThrowNativeError("Invalid timer handle %x (error %d)", hndl, herr);
faluco@612
   241
	}
faluco@612
   242
faluco@612
   243
	g_Timers.FireTimerOnce(pInfo->Timer, params[2] ? true : false);
faluco@612
   244
faluco@612
   245
	return 1;
faluco@612
   246
}
faluco@612
   247
dvander@822
   248
static cell_t smn_GetTickedTime(IPluginContext *pContext, const cell_t *params)
dvander@822
   249
{
dvander@822
   250
	cell_t *simulating;
dvander@822
   251
	pContext->LocalToPhysAddr(params[1], &simulating);
dvander@822
   252
dvander@822
   253
	*simulating = g_SimTicks.ticking ? 0 : 1;
dvander@822
   254
dvander@822
   255
	float t = g_SimTicks.ticking ? gpGlobals->curtime : g_SimTicks.ticktime;
dvander@822
   256
	return sp_ftoc(t);
dvander@822
   257
}
dvander@822
   258
faluco@612
   259
REGISTER_NATIVES(timernatives)
faluco@612
   260
{
faluco@612
   261
	{"CreateTimer",				smn_CreateTimer},
faluco@612
   262
	{"KillTimer",				smn_KillTimer},
faluco@612
   263
	{"TriggerTimer",			smn_TriggerTimer},
dvander@822
   264
	{"GetTickedTime",			smn_GetTickedTime},
faluco@612
   265
	{NULL,						NULL}
faluco@612
   266
};