diff --git a/sp/src/game/client/mapbase/vscript_vgui.cpp b/sp/src/game/client/mapbase/vscript_vgui.cpp index c679d6e2..9b2c3af5 100644 --- a/sp/src/game/client/mapbase/vscript_vgui.cpp +++ b/sp/src/game/client/mapbase/vscript_vgui.cpp @@ -2610,9 +2610,17 @@ public: static inline void SetHScript( HSCRIPT &var, HSCRIPT val ) { - if ( var && g_pScriptVM ) - g_pScriptVM->ReleaseScript( var ); - var = val; + if ( g_pScriptVM ) + { + if ( var ) + g_pScriptVM->ReleaseScript( var ); + + var = g_pScriptVM->CopyObject( val ); + } + else + { + var = NULL; + } } #define CheckCallback(s)\ diff --git a/sp/src/game/shared/baseentity_shared.cpp b/sp/src/game/shared/baseentity_shared.cpp index 5f957612..8f5660a2 100644 --- a/sp/src/game/shared/baseentity_shared.cpp +++ b/sp/src/game/shared/baseentity_shared.cpp @@ -3033,7 +3033,7 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f float nextthink = gpGlobals->curtime + flTime; - pf->m_hfnThink = hFunc; + pf->m_hfnThink = g_pScriptVM->CopyObject( hFunc ); pf->m_flNextThink = nextthink; #ifdef GAME_DLL diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index cd95b3fd..7638762e 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -2920,7 +2920,7 @@ int CScriptGameEventListener::ListenToGameEvent( const char* szEvent, HSCRIPT hF if ( bValid ) { m_iContextHash = HashContext( szContext ); - m_hCallback = hFunc; + m_hCallback = g_pScriptVM->CopyObject( hFunc ); m_bActive = true; s_Listeners.AddToTail( this ); @@ -4609,9 +4609,9 @@ public: CScriptConCommand( const char *name, HSCRIPT fn, const char *helpString, int flags, ConCommand *pLinked = NULL ) : BaseClass( name, this, helpString, flags, 0 ), m_pLinked(pLinked), - m_hCallback(fn), m_hCompletionCallback(NULL) { + m_hCallback = g_pScriptVM->CopyObject( fn ); m_nCmdNameLen = V_strlen(name) + 1; Assert( m_nCmdNameLen - 1 <= 128 ); } @@ -4701,7 +4701,7 @@ public: BaseClass::m_pCommandCompletionCallback = this; BaseClass::m_bHasCompletionCallback = true; - m_hCompletionCallback = fn; + m_hCompletionCallback = g_pScriptVM->CopyObject( fn ); } else { @@ -4720,7 +4720,8 @@ public: if ( m_hCallback ) g_pScriptVM->ReleaseScript( m_hCallback ); - m_hCallback = fn; + + m_hCallback = g_pScriptVM->CopyObject( fn ); } else { @@ -4781,7 +4782,7 @@ public: if (fn) { - m_hCallback = fn; + m_hCallback = g_pScriptVM->CopyObject( fn ); BaseClass::InstallChangeCallback( (FnChangeCallback_t)ScriptConVarCallback ); } else diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h index e497bdc9..d835157f 100644 --- a/sp/src/public/vscript/ivscript.h +++ b/sp/src/public/vscript/ivscript.h @@ -1028,6 +1028,8 @@ public: #ifdef MAPBASE_VSCRIPT virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0; virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) = 0; + // To hold strong references to script objects + virtual HSCRIPT CopyObject(HSCRIPT obj) = 0; #endif //---------------------------------------------------------------------------- diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index 88f0abbd..d7391a82 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -225,6 +225,7 @@ public: virtual void CreateArray(ScriptVariant_t &arr, int size = 0) override; virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) override; + virtual HSCRIPT CopyObject(HSCRIPT obj) override; //---------------------------------------------------------------------------- @@ -1317,7 +1318,8 @@ SQInteger function_stub(HSQUIRRELVM vm) ScriptFunctionBinding_t* pFunc = (ScriptFunctionBinding_t*)userptr; - auto nargs = pFunc->m_desc.m_Parameters.Count(); + int nargs = pFunc->m_desc.m_Parameters.Count(); + int nLastHScriptIdx = -1; if (nargs > top) { @@ -1394,9 +1396,10 @@ SQInteger function_stub(HSQUIRRELVM vm) { HSQOBJECT* pObject = new HSQOBJECT; *pObject = val; - sq_addref(vm, pObject); params[i] = (HSCRIPT)pObject; } + + nLastHScriptIdx = i; break; } default: @@ -1453,6 +1456,12 @@ SQInteger function_stub(HSQUIRRELVM vm) delete (HSQOBJECT*)retval.m_hScript; } + for ( int i = 0; i <= nLastHScriptIdx; ++i ) + { + if ( pFunc->m_desc.m_Parameters[i] == FIELD_HSCRIPT ) + delete (HSQOBJECT*)params[i].m_hScript; + } + return pFunc->m_desc.m_ReturnType != FIELD_VOID; } @@ -3201,6 +3210,17 @@ bool SquirrelVM::ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) return ret; } +HSCRIPT SquirrelVM::CopyObject(HSCRIPT obj) +{ + if ( !obj ) + return NULL; + + HSQOBJECT *ret = new HSQOBJECT; + *ret = *(HSQOBJECT*)obj; + sq_addref( vm_, ret ); + return (HSCRIPT)ret; +} + //------------------------------------------------------------- //-------------------------------------------------------------