mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2024-12-27 15:25:30 +03:00
Merge branch 'feature/vscript/hook-handler-prototype-1' of https://github.com/mapbase-source/source-sdk-2013 into feature/vscript/hook-handler-prototype-1
This commit is contained in:
commit
38be2ca932
@ -860,6 +860,15 @@ public:
|
||||
//--------------------------------------------------------
|
||||
virtual ScriptStatus_t ExecuteFunction( HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait ) = 0;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
//--------------------------------------------------------
|
||||
// Hooks
|
||||
//--------------------------------------------------------
|
||||
virtual bool ScopeIsHooked( HSCRIPT hScope, const char *pszEventName ) = 0;
|
||||
virtual HSCRIPT LookupHookFunction( const char *pszEventName, HSCRIPT hScope, bool &bLegacy ) = 0;
|
||||
virtual ScriptStatus_t ExecuteHookFunction( const char *pszEventName, HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait ) = 0;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------
|
||||
// External functions
|
||||
//--------------------------------------------------------
|
||||
@ -1573,12 +1582,13 @@ struct ScriptHook_t
|
||||
|
||||
// Cached for when CanRunInScope() is called before Call()
|
||||
HSCRIPT m_hFunc;
|
||||
bool m_bLegacy;
|
||||
|
||||
// Checks if there's a function of this name which would run in this scope
|
||||
HSCRIPT CanRunInScope( HSCRIPT hScope )
|
||||
{
|
||||
extern IScriptVM *g_pScriptVM;
|
||||
m_hFunc = g_pScriptVM->LookupFunction( m_desc.m_pszScriptName, hScope );
|
||||
m_hFunc = g_pScriptVM->LookupHookFunction( m_desc.m_pszScriptName, hScope, m_bLegacy );
|
||||
return m_hFunc;
|
||||
}
|
||||
|
||||
@ -1602,7 +1612,8 @@ struct ScriptHook_t
|
||||
// Make sure we have a function in this scope
|
||||
if (!m_hFunc && !CanRunInScope(hScope))
|
||||
return false;
|
||||
else
|
||||
// Legacy
|
||||
else if (m_bLegacy)
|
||||
{
|
||||
for (int i = 0; i < m_desc.m_Parameters.Count(); i++)
|
||||
{
|
||||
@ -1623,6 +1634,15 @@ struct ScriptHook_t
|
||||
|
||||
return true;
|
||||
}
|
||||
// New Hook System
|
||||
else
|
||||
{
|
||||
g_pScriptVM->ExecuteHookFunction( m_desc.m_pszScriptName, m_hFunc, pArgs, m_desc.m_Parameters.Count(), pReturn, hScope, true );
|
||||
if (bRelease)
|
||||
g_pScriptVM->ReleaseFunction( m_hFunc );
|
||||
m_hFunc = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -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
|
||||
//--------------------------------------------------------
|
||||
@ -2248,6 +2255,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_);
|
||||
|
@ -122,6 +122,98 @@ class CSimpleCallChainer
|
||||
chain = null;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Hook handler
|
||||
//---------------------------------------------------------
|
||||
Hooks <- { Registered = {} }
|
||||
|
||||
function Hooks::Add( scope, event, func, name )
|
||||
{
|
||||
Hooks.Registered[name] <- [event, scope, func];
|
||||
}
|
||||
|
||||
function Hooks::Remove( name )
|
||||
{
|
||||
Hooks.Registered.rawdelete(name);
|
||||
}
|
||||
|
||||
function Hooks::ScopeHookedToEvent( scope, event )
|
||||
{
|
||||
//printl("Running ScopeHookedToEvent()")
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[1] == scope && elem[0] == event)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function Hooks::CallHooks(event, scope, ...)
|
||||
{
|
||||
//printl("vargv.len() = " + vargv.len())
|
||||
switch (vargv.len())
|
||||
{
|
||||
case 0:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2]()
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0])
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0], vargv[1])
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0], vargv[1], vargv[2])
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0], vargv[1], vargv[2], vargv[3])
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0], vargv[1], vargv[2], vargv[3], vargv[4])
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
foreach (elem in Hooks.Registered)
|
||||
{
|
||||
if (elem[0] == event && elem[1] == scope)
|
||||
return elem[2](vargv[0], vargv[1], vargv[2], vargv[3], vargv[4], vargv[5])
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Documentation
|
||||
//---------------------------------------------------------
|
||||
__Documentation <- {}
|
||||
|
||||
local DocumentedFuncs = {}
|
||||
|
Loading…
Reference in New Issue
Block a user