Skip to content

Commit 6297d2b

Browse files
committed
Fix ScriptHook_t initialization order
When a ScriptClassDesc_t for is initialized (SCRIPTDESC), it recursively invokes its parents initializers in order to obtain their pHelper member. Initialization is only done once, so repeated initialization is skipped. Initialization includes assignment of a vector of ScriptHook_t's (DEFINE_SCRIPTFUNC/BEGIN_SCRIPTHOOK), which must be initialized beforehand. Both of these use (static) globals; Within a translation unit, initialization order is defined to be the same as the order of declaration. So within a translation unit we must define all ScriptHook_t's before the ScriptClassDesc_t using them. A problem occurs with the parent initialization though, since there is no defined order between translation units, meaning initialization of a ScriptClassDesc_t can happen before its ScriptHook_t's, despite being the correct order within its translation unit. On MSVC it seems this issue is benign. On GCC/Linux however the initialization of a ScriptHook_t essentially cleared whatever happened during the initialization of the ScriptClassDesc_t, meaning many hooks simply didn't work. This situation is remedied by delaying the initialization of the ScriptClassDesc_t's ScriptHook_t vector to only when the constructor of it is invoked from its translation unit. This is accomplished simply by adding a boolean parameter to the function (GetScriptDesc()) that is true in the global constructor invocation, and false by default (including when doing parent ScriptClassDesc_t initialization). When false, a valid ScriptClassDesc_t pointer is still returned, which is all that is needed for the initialization of the child ScriptClassDesc_t. The value of the returned pointer is a fixed memory location, and does not change due to the delayed initialization. The script-helper must be initialized eagerly though, for the search of a base-class helper. This also changes the SCRIPTDESC slightly to accommodate the eager initialization of helper instance pointer. Fixes #244.
1 parent 471a840 commit 6297d2b

File tree

10 files changed

+56
-51
lines changed

10 files changed

+56
-51
lines changed

sp/src/game/client/c_baseentity.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,7 @@ ScriptHook_t C_BaseEntity::g_Hook_UpdateOnRemove;
433433
ScriptHook_t C_BaseEntity::g_Hook_ModifyEmitSoundParams;
434434
#endif
435435

436-
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
437-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
436+
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( C_BaseEntity, "Root class of all client-side entities", &g_BaseEntityScriptInstanceHelper )
438437
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
439438
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
440439
#ifdef MAPBASE_VSCRIPT

sp/src/game/client/mapbase/vscript_vgui.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ void CScriptSurface::DrawColoredTextRect( int font, int x, int y, int w, int h,
10311031
#define __base() this->_base
10321032

10331033
#define BEGIN_SCRIPTDESC_VGUI( panelClass )\
1034-
BEGIN_SCRIPTDESC_NAMED( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "" )\
1034+
BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "", VGUI_SCRIPT_INSTANCE_HELPER )\
10351035
DEFINE_VGUI_SCRIPTFUNC_##panelClass()
10361036

10371037
//
@@ -1235,9 +1235,9 @@ class CScriptVGUIScriptInstanceHelper : public IScriptInstanceHelper
12351235

12361236
static CScriptVGUIScriptInstanceHelper g_ScriptVGUIScriptInstanceHelper;
12371237

1238-
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() DEFINE_SCRIPT_INSTANCE_HELPER( &g_ScriptVGUIScriptInstanceHelper )
1238+
#define VGUI_SCRIPT_INSTANCE_HELPER &g_ScriptVGUIScriptInstanceHelper
12391239
#else
1240-
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()
1240+
#define VGUI_SCRIPT_INSTANCE_HELPER NULL
12411241
#endif
12421242

12431243

@@ -1866,8 +1866,6 @@ CLASS_HELPER_INTERFACE_ROOT( Panel )
18661866
};
18671867

18681868
#define DEFINE_VGUI_SCRIPTFUNC_Panel()\
1869-
DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()\
1870-
\
18711869
DEFINE_SCRIPTFUNC( Destroy, "" )\
18721870
DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\
18731871
DEFINE_SCRIPTFUNC( GetName, "" )\

sp/src/game/client/vscript_client.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,7 @@ class CMaterialProxyScriptInstanceHelper : public IScriptInstanceHelper
234234

235235
CMaterialProxyScriptInstanceHelper g_MaterialProxyScriptInstanceHelper;
236236

237-
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript" )
238-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_MaterialProxyScriptInstanceHelper )
237+
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript", &g_MaterialProxyScriptInstanceHelper )
239238
DEFINE_SCRIPTFUNC( GetVarString, "Gets a material var's string value" )
240239
DEFINE_SCRIPTFUNC( GetVarInt, "Gets a material var's int value" )
241240
DEFINE_SCRIPTFUNC( GetVarFloat, "Gets a material var's float value" )

sp/src/game/server/baseentity.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,8 +2257,7 @@ ScriptHook_t CBaseEntity::g_Hook_ModifyEmitSoundParams;
22572257
ScriptHook_t CBaseEntity::g_Hook_ModifySentenceParams;
22582258
#endif
22592259

2260-
BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" )
2261-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
2260+
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( CBaseEntity, "Root class of all server-side entities", &g_BaseEntityScriptInstanceHelper )
22622261
DEFINE_SCRIPTFUNC_NAMED( ConnectOutputToScript, "ConnectOutput", "Adds an I/O connection that will call the named function when the specified output fires" )
22632262
DEFINE_SCRIPTFUNC_NAMED( DisconnectOutputFromScript, "DisconnectOutput", "Removes a connected script function from an I/O event." )
22642263

sp/src/game/shared/baseentity_shared.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ inline HSCRIPT ToHScript(CBaseEntity* pEnt)
255255
return (pEnt) ? pEnt->GetScriptInstance() : NULL;
256256
}
257257

258-
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*);
258+
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*, bool);
259259
inline CBaseEntity* ToEnt(HSCRIPT hScript)
260260
{
261261
return (hScript) ? (CBaseEntity*)g_pScriptVM->GetInstanceValue(hScript, GetScriptDescForClass(CBaseEntity)) : NULL;

sp/src/game/shared/mapbase/vscript_funcs_shared.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ END_SCRIPTDESC();
376376

377377
CPlaneTInstanceHelper g_PlaneTInstanceHelper;
378378

379-
BEGIN_SCRIPTDESC_ROOT( cplane_t, "" )
380-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_PlaneTInstanceHelper )
379+
BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( cplane_t, "", &g_PlaneTInstanceHelper )
381380
END_SCRIPTDESC();
382381

383382
static HSCRIPT ScriptTraceLineComplex( const Vector &vecStart, const Vector &vecEnd, HSCRIPT entIgnore, int iMask, int iCollisionGroup )
@@ -509,9 +508,7 @@ static void DestroyFireBulletsInfo( HSCRIPT hBulletsInfo )
509508
//-----------------------------------------------------------------------------
510509
CAnimEventTInstanceHelper g_AnimEventTInstanceHelper;
511510

512-
BEGIN_SCRIPTDESC_ROOT( scriptanimevent_t, "" )
513-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_AnimEventTInstanceHelper )
514-
511+
BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( scriptanimevent_t, "", &g_AnimEventTInstanceHelper )
515512
DEFINE_SCRIPTFUNC( GetEvent, "" )
516513
DEFINE_SCRIPTFUNC( SetEvent, "" )
517514

sp/src/game/shared/vscript_shared.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = fal
2121

2222
#define DECLARE_ENT_SCRIPTDESC() ALLOW_SCRIPT_ACCESS(); virtual ScriptClassDesc_t *GetScriptDesc()
2323

24-
#define BEGIN_ENT_SCRIPTDESC( className, baseClass, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC( className, baseClass, description )
25-
#define BEGIN_ENT_SCRIPTDESC_ROOT( className, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT( className, description )
26-
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
27-
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
28-
29-
#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className * ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
24+
#define BEGIN_ENT_SCRIPTDESC( className, baseClass, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC( className, baseClass, description )
25+
#define BEGIN_ENT_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper )
26+
#define BEGIN_ENT_SCRIPTDESC_ROOT( className, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT( className, description )
27+
#define BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper )
28+
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
29+
#define BEGIN_ENT_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper )
30+
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
31+
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper )
32+
33+
#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className *, bool ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
3034

3135
// Only allow scripts to create entities during map initialization
3236
bool IsEntityCreationAllowedInScripts( void );

sp/src/public/vscript/ivscript.h

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -697,37 +697,48 @@ static inline int ToConstantVariant(int value)
697697
//
698698
//-----------------------------------------------------------------------------
699699

700-
#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *);
701-
702-
#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_NAMED( className, baseClass, #className, description )
703-
#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_NAMED( className, #className, description )
704-
705-
#define BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) \
706-
template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*); \
707-
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*); \
708-
ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr); \
709-
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*) \
700+
#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *, bool);
701+
702+
#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, NULL )
703+
#define BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper ) BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, #className, description, helper )
704+
#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, NULL )
705+
#define BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper ) BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, #className, description, helper )
706+
707+
#define BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper ) \
708+
template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*, bool); \
709+
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool); \
710+
ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr, true); \
711+
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool init) \
710712
{ \
711713
static ScriptClassDesc_t g_##className##_ScriptDesc; \
712714
typedef className _className; \
713715
ScriptClassDesc_t *pDesc = &g_##className##_ScriptDesc; \
714-
if (pDesc->m_pszClassname) return pDesc; \
715-
pDesc->m_pszDescription = description; \
716-
ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \
717-
ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \
718-
while ( pInstanceHelperBase ) \
716+
if (!pDesc->m_pszClassname) \
719717
{ \
720-
if ( pInstanceHelperBase->pHelper ) \
718+
pDesc->m_pszDescription = description; \
719+
ScriptClassDesc_t *pBaseDesc = GetScriptDescForClass( baseClass ); \
720+
ScriptInitClassDescNamed( pDesc, className, pBaseDesc, scriptName ); \
721+
pDesc->pHelper = helper; \
722+
if ( !pDesc->pHelper ) \
721723
{ \
722-
pDesc->pHelper = pInstanceHelperBase->pHelper; \
723-
break; \
724+
while ( pBaseDesc ) \
725+
{ \
726+
if ( pBaseDesc->pHelper ) \
727+
{ \
728+
pDesc->pHelper = pBaseDesc->pHelper; \
729+
break; \
730+
} \
731+
pBaseDesc = pBaseDesc->m_pBaseDesc; \
732+
} \
724733
} \
725-
pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \
726-
}
734+
} \
735+
if (!init) return pDesc;
727736

728737

729738
#define BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) \
730-
BEGIN_SCRIPTDESC_NAMED( className, ScriptNoBase_t, scriptName, description )
739+
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, NULL )
740+
#define BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper ) \
741+
BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, ScriptNoBase_t, scriptName, description, helper )
731742

732743
#define END_SCRIPTDESC() \
733744
return pDesc; \
@@ -736,7 +747,7 @@ static inline int ToConstantVariant(int value)
736747
#define DEFINE_SCRIPTFUNC( func, description ) DEFINE_SCRIPTFUNC_NAMED( func, #func, description )
737748
#define DEFINE_SCRIPTFUNC_NAMED( func, scriptName, description ) ScriptAddFunctionToClassDescNamed( pDesc, _className, func, scriptName, description );
738749
#define DEFINE_SCRIPT_CONSTRUCTOR() ScriptAddConstructorToClassDesc( pDesc, _className );
739-
#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) pDesc->pHelper = (p);
750+
#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) MUST_USE_BEGIN_SCRIPTDESC_WITH_HELPER_INSTEAD
740751

741752
#ifdef MAPBASE_VSCRIPT
742753
// Use this for hooks which have no parameters
@@ -781,10 +792,10 @@ static inline int ToConstantVariant(int value)
781792
do { ScriptMemberDesc_t *pBinding = &((pDesc)->m_Members[(pDesc)->m_Members.AddToTail()]); pBinding->m_pszScriptName = varName; pBinding->m_pszDescription = description; pBinding->m_ReturnType = returnType; } while (0);
782793
#endif
783794

784-
template <typename T> ScriptClassDesc_t *GetScriptDesc(T *);
795+
template <typename T> ScriptClassDesc_t *GetScriptDesc(T *, bool = false);
785796

786797
struct ScriptNoBase_t;
787-
template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *) { return NULL; }
798+
template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *, bool ) { return NULL; }
788799

789800
#define GetScriptDescForClass( className ) GetScriptDesc( ( className *)NULL )
790801

sp/src/vscript/vscript_bindings_base.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,9 @@ CScriptKeyValues::~CScriptKeyValues( )
387387
//=============================================================================
388388
CScriptColorInstanceHelper g_ColorScriptInstanceHelper;
389389

390-
BEGIN_SCRIPTDESC_ROOT( Color, "" )
390+
BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( Color, "", &g_ColorScriptInstanceHelper )
391391

392392
DEFINE_SCRIPT_CONSTRUCTOR()
393-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_ColorScriptInstanceHelper )
394393

395394
DEFINE_SCRIPTFUNC( SetColor, "Sets the color." )
396395

sp/src/vscript/vscript_bindings_math.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,9 @@ void ScriptMatrixSetTranslation( const Vector& vecset, HSCRIPT hMat1 )
205205
//=============================================================================
206206
CScriptQuaternionInstanceHelper g_QuaternionScriptInstanceHelper;
207207

208-
BEGIN_SCRIPTDESC_ROOT_NAMED( Quaternion, "Quaternion", "A quaternion." )
208+
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( Quaternion, "Quaternion", "A quaternion.", &g_QuaternionScriptInstanceHelper )
209209

210210
DEFINE_SCRIPT_CONSTRUCTOR()
211-
DEFINE_SCRIPT_INSTANCE_HELPER( &g_QuaternionScriptInstanceHelper )
212211
DEFINE_SCRIPTFUNC_NAMED( ScriptInit, "Init", "Creates a quaternion with the given values." )
213212

214213
DEFINE_MEMBERVAR( "x", FIELD_FLOAT, "The quaternion's i axis component." )

0 commit comments

Comments
 (0)