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