core/smn_timers.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1231 17badaf66ce4
child 1397 c105f054c72e
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

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