Add RequestFrame native for one-off frame actions (bug 5965, r=dvander).

This commit is contained in:
Kyle Sanderson 2013-10-29 22:10:40 -04:00
parent 0775976165
commit e01fc5e697
2 changed files with 77 additions and 0 deletions

View File

@ -33,6 +33,8 @@
#include <IPluginSys.h> #include <IPluginSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <IForwardSys.h> #include <IForwardSys.h>
#include <ISourceMod.h>
#include <am-utility.h>
HandleType_t g_GlobalFwdType = 0; HandleType_t g_GlobalFwdType = 0;
HandleType_t g_PrivateFwdType = 0; HandleType_t g_PrivateFwdType = 0;
@ -589,6 +591,63 @@ static cell_t sm_CallCancel(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
struct SMFrameActionData
{
SMFrameActionData(Handle_t handle, Handle_t ownerhandle, cell_t data) : handle(handle), ownerhandle(ownerhandle), data(data)
{
};
Handle_t handle;
Handle_t ownerhandle;
cell_t data;
};
static void PawnFrameAction(void *pData)
{
ke::AutoPtr<SMFrameActionData> frame(reinterpret_cast<SMFrameActionData *>(pData));
IPlugin *pPlugin = pluginsys->PluginFromHandle(frame->ownerhandle, NULL);
if (!pPlugin)
{
return;
}
IChangeableForward *pForward;
HandleSecurity sec(pPlugin->GetIdentity(), g_pCoreIdent);
if (handlesys->ReadHandle(frame->handle, g_PrivateFwdType, &sec, (void **)&pForward) != HandleError_None)
{
return;
}
pForward->PushCell(frame->data);
pForward->Execute(NULL);
handlesys->FreeHandle(frame->handle, &sec);
}
static cell_t sm_AddFrameAction(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[1]);
if (!pFunction)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
}
IChangeableForward *pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 1, NULL, Param_Cell);
IdentityToken_t *pIdentity = pContext->GetIdentity();
Handle_t Handle = handlesys->CreateHandle(g_PrivateFwdType, pForward, pIdentity, g_pCoreIdent, NULL);
if (Handle == BAD_HANDLE)
{
delete pForward;
return 0;
}
pForward->AddFunction(pFunction);
SMFrameActionData *pData = new SMFrameActionData(Handle, pPlugin->GetMyHandle(), params[2]);
g_pSM->AddFrameAction(PawnFrameAction, pData);
return 1;
}
REGISTER_NATIVES(functionNatives) REGISTER_NATIVES(functionNatives)
{ {
{"GetFunctionByName", sm_GetFunctionByName}, {"GetFunctionByName", sm_GetFunctionByName},
@ -610,5 +669,6 @@ REGISTER_NATIVES(functionNatives)
{"Call_PushStringEx", sm_CallPushStringEx}, {"Call_PushStringEx", sm_CallPushStringEx},
{"Call_Finish", sm_CallFinish}, {"Call_Finish", sm_CallFinish},
{"Call_Cancel", sm_CallCancel}, {"Call_Cancel", sm_CallCancel},
{"RequestFrame", sm_AddFrameAction},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -492,3 +492,20 @@ native FormatNativeString(out_param,
&written=0, &written=0,
String:out_string[]="", String:out_string[]="",
const String:fmt_string[]=""); const String:fmt_string[]="");
/**
* Defines a RequestFrame Callback.
*
* @param data Data passed to the RequestFrame native.
* @noreturn
*/
functag public RequestFrameCallback(any:data);
/**
* Creates a single use Next Frame hook.
*
* @param Function Function to call on the next frame.
* @param data Value to be passed on the invocation of the Function.
* @noreturn
*/
native RequestFrame(RequestFrameCallback:Function, any:data=0);