-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CODE] Script hook parameter reset on Linux #244
Comments
I stumbled upon this limitation when trying out a mod, and I attempted to fix this: diff --git a/sp/src/game/shared/baseentity_shared.h b/sp/src/game/shared/baseentity_shared.h
index 85a0ffd8..4891b0bc 100644
--- a/sp/src/game/shared/baseentity_shared.h
+++ b/sp/src/game/shared/baseentity_shared.h
@@ -255,7 +255,7 @@ inline HSCRIPT ToHScript(CBaseEntity* pEnt)
return (pEnt) ? pEnt->GetScriptInstance() : NULL;
}
-template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*);
+template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*, bool);
inline CBaseEntity* ToEnt(HSCRIPT hScript)
{
return (hScript) ? (CBaseEntity*)g_pScriptVM->GetInstanceValue(hScript, GetScriptDescForClass(CBaseEntity)) : NULL;
diff --git a/sp/src/game/shared/vscript_shared.h b/sp/src/game/shared/vscript_shared.h
index 50834220..2145825b 100644
--- a/sp/src/game/shared/vscript_shared.h
+++ b/sp/src/game/shared/vscript_shared.h
@@ -26,7 +26,7 @@ inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = fal
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
-#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className * ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
+#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className *, bool ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
// Only allow scripts to create entities during map initialization
bool IsEntityCreationAllowedInScripts( void );
diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h
index 58f981e0..3b6d0b02 100644
--- a/sp/src/public/vscript/ivscript.h
+++ b/sp/src/public/vscript/ivscript.h
@@ -697,33 +703,36 @@ static inline int ToConstantVariant(int value)
//
//-----------------------------------------------------------------------------
-#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *);
+#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *, bool);
#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_NAMED( className, baseClass, #className, description )
#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_NAMED( className, #className, description )
#define BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) \
- template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*); \
- template <> ScriptClassDesc_t* GetScriptDesc<className>(className*); \
- ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr); \
- template <> ScriptClassDesc_t* GetScriptDesc<className>(className*) \
+ template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*, bool); \
+ template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool); \
+ ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr, true); \
+ template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool init) \
{ \
static ScriptClassDesc_t g_##className##_ScriptDesc; \
typedef className _className; \
ScriptClassDesc_t *pDesc = &g_##className##_ScriptDesc; \
- if (pDesc->m_pszClassname) return pDesc; \
- pDesc->m_pszDescription = description; \
- ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \
- ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \
- while ( pInstanceHelperBase ) \
+ if (!pDesc->m_pszClassname) \
{ \
- if ( pInstanceHelperBase->pHelper ) \
+ pDesc->m_pszDescription = description; \
+ ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \
+ ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \
+ while ( pInstanceHelperBase ) \
{ \
- pDesc->pHelper = pInstanceHelperBase->pHelper; \
- break; \
+ if ( pInstanceHelperBase->pHelper ) \
+ { \
+ pDesc->pHelper = pInstanceHelperBase->pHelper; \
+ break; \
+ } \
+ pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \
} \
- pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \
- }
+ } \
+ if (!init) return pDesc;
#define BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) \
@@ -781,10 +790,10 @@ static inline int ToConstantVariant(int value)
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);
#endif
-template <typename T> ScriptClassDesc_t *GetScriptDesc(T *);
+template <typename T> ScriptClassDesc_t *GetScriptDesc(T *, bool = false);
struct ScriptNoBase_t;
-template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *) { return NULL; }
+template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *, bool ) { return NULL; }
#define GetScriptDescForClass( className ) GetScriptDesc( ( className *)NULL ) Within a TU, gcc orders the static constructors from first/top to bottom/last, which is fine as long as the Seems to work on my end. If you think it looks fine I can open a PR, but I'm not familiar with this system, perhaps deferring that part when initializing the subclasses' |
Nothing in this fix jumps out to me as problematic. @samisalreadytaken might have his own input, but please feel free to open a PR for this. |
The design of ScriptHook_t could also be changed to fix it, but this looks fine. |
Describe the bug
[gcc 11.2] Static initialisation of
ScriptHook_t
variables happens afterScriptHook_t::AddParameter()
is called insideBEGIN_ENT_SCRIPTDESC()
, resettingScriptHook_t::m_desc::m_Parameters
which breaks scripts that expect parameters.This is not an issue with non-entity hooks such as
OnEntityCreated
.This can be observed in a debugger. Using
PlayerRunCommand
as that is the simplest hook with parameters that doesn't have any prerequisites.Steps to reproduce
To observe in game, create a hook with parameters. Legacy type or not does not matter.
The text was updated successfully, but these errors were encountered: