Added prototype VScript hook handler

This commit is contained in:
Blixibon
2021-02-24 12:01:50 -06:00
parent fd600b53aa
commit 201a7ad1d1
3 changed files with 225 additions and 2 deletions

View File

@@ -161,6 +161,13 @@ public:
//--------------------------------------------------------
virtual ScriptStatus_t ExecuteFunction(HSCRIPT hFunction, ScriptVariant_t* pArgs, int nArgs, ScriptVariant_t* pReturn, HSCRIPT hScope, bool bWait) override;
//--------------------------------------------------------
// Hooks
//--------------------------------------------------------
virtual bool ScopeIsHooked( HSCRIPT hScope, const char *pszEventName ) override;
virtual HSCRIPT LookupHookFunction( const char *pszEventName, HSCRIPT hScope, bool &bLegacy ) override;
virtual ScriptStatus_t ExecuteHookFunction( const char *pszEventName, HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait ) override;
//--------------------------------------------------------
// External functions
//--------------------------------------------------------
@@ -1986,6 +1993,110 @@ ScriptStatus_t SquirrelVM::ExecuteFunction(HSCRIPT hFunction, ScriptVariant_t* p
return SCRIPT_DONE;
}
bool SquirrelVM::ScopeIsHooked( HSCRIPT hScope, const char *pszEventName )
{
Assert( hScope && hScope != INVALID_HSCRIPT );
sq_pushroottable(vm_);
sq_pushstring(vm_, "Hooks", -1);
sq_get(vm_, -2);
sq_pushstring(vm_, "ScopeHookedToEvent", -1);
sq_get(vm_, -2);
sq_push(vm_, -2);
sq_pushobject(vm_, *((HSQOBJECT*)hScope));
sq_pushstring(vm_, pszEventName, -1);
sq_call(vm_, 3, SQTrue, SQTrue);
SQBool val;
if (SQ_FAILED(sq_getbool(vm_, -1, &val)))
{
sq_pop(vm_, 3);
return false;
}
sq_pop(vm_, 3);
return val ? true : false;
}
HSCRIPT SquirrelVM::LookupHookFunction(const char *pszEventName, HSCRIPT hScope, bool &bLegacy)
{
HSCRIPT hFunc = LookupFunction( pszEventName, hScope );
if (hFunc)
{
bLegacy = true;
return hFunc;
}
else
{
bLegacy = false;
}
if (!ScopeIsHooked(hScope, pszEventName))
return nullptr;
sq_pushroottable(vm_);
sq_pushstring(vm_, "Hooks", -1);
sq_get(vm_, -2);
sq_pushstring(vm_, "CallHooks", -1);
sq_get(vm_, -2);
HSQOBJECT obj;
sq_resetobject(&obj);
sq_getstackobj(vm_, -1, &obj);
sq_addref(vm_, &obj);
sq_pop(vm_, 2);
HSQOBJECT* pObj = new HSQOBJECT;
*pObj = obj;
return (HSCRIPT)pObj;
}
ScriptStatus_t SquirrelVM::ExecuteHookFunction(const char *pszEventName, HSCRIPT hFunction, ScriptVariant_t* pArgs, int nArgs, ScriptVariant_t* pReturn, HSCRIPT hScope, bool bWait)
{
SquirrelSafeCheck safeCheck(vm_);
if (!hFunction)
return SCRIPT_ERROR;
if (hFunction == INVALID_HSCRIPT)
return SCRIPT_ERROR;
HSQOBJECT* pFunc = (HSQOBJECT*)hFunction;
sq_pushobject(vm_, *pFunc);
// TODO: Run in hook scope
sq_pushroottable(vm_);
sq_pushstring(vm_, pszEventName, -1);
sq_pushobject(vm_, *((HSQOBJECT*)hScope));
for (int i = 0; i < nArgs; ++i)
{
PushVariant(vm_, pArgs[i]);
}
bool hasReturn = pReturn != nullptr;
if (SQ_FAILED(sq_call(vm_, nArgs + 3, hasReturn, SQTrue)))
{
sq_pop(vm_, 1);
return SCRIPT_ERROR;
}
if (hasReturn)
{
if (!getVariant(vm_, -1, *pReturn))
{
sq_pop(vm_, 1);
return SCRIPT_ERROR;
}
sq_pop(vm_, 1);
}
sq_pop(vm_, 1);
return SCRIPT_DONE;
}
void SquirrelVM::RegisterFunction(ScriptFunctionBinding_t* pScriptFunction)
{
SquirrelSafeCheck safeCheck(vm_);