diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 02e1d85..2643bf5 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -1195,3 +1195,11 @@ enum InfoMapBuyParam BUYING_ONLY_TERRORISTS, BUYING_NO_ONE, }; + +enum USE_TYPE +{ + USE_OFF, + USE_ON, + USE_SET, + USE_TOGGLE +}; diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 0963ffb..07c69e0 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -7,60 +7,70 @@ #include /* -* Sets callback for entity +* Sets Think callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Think_Callback(const ent)" * * @noreturn */ -native SetThink(const ent, const callback[]); +native SetThink(const ent, const callback[], const params[] = "", const len = 0); /* -* Sets callback for entity +* Sets Touch callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)" * * @noreturn */ -native SetTouch(const ent, const callback[]); +native SetTouch(const ent, const callback[], const params[] = "", const len = 0); /* -* Sets callback for entity +* Sets Use callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)" * * @noreturn */ -native SetUse(const ent, const callback[]); +native SetUse(const ent, const callback[], const params[] = "", const len = 0); /* -* Sets callback for entity +* Sets Blocked callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)" * * @noreturn */ -native SetBlocked(const ent, const callback[]); +native SetBlocked(const ent, const callback[], const params[] = "", const len = 0); /* -* Sets callback for entity +* Sets MoveDone callback for entity +* +* @param entity Entity index +* @param callback The forward to call +* +* @note Use "" to reset callback * @note Entity should be inherited from CBaseToggle, otherwise server can crash -* -* @param entity Entity index -* @param callback The forward to call -* @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)" * * @noreturn */ -native SetMoveDone(const ent, const callback[]); +native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0); /* * Sets a value to CSGameRules_Members members. diff --git a/reapi/src/amx_hook.h b/reapi/src/amx_hook.h index 7fbb793..7082868 100644 --- a/reapi/src/amx_hook.h +++ b/reapi/src/amx_hook.h @@ -8,7 +8,7 @@ enum fwdstate FSTATE_STOPPED }; -template +template class CAmxxHook { public: @@ -18,9 +18,11 @@ public: g_amxxapi.UnregisterSPForward(m_index); m_index = -1; } + + delete m_uniqueData; } - CAmxxHook(AMX *amx, const char *funcname, int index, T data = (T)0) : + CAmxxHook(AMX *amx, const char *funcname, int index, T *data = nullptr) : m_index(index), m_state(FSTATE_ENABLED), m_amx(amx), @@ -29,7 +31,7 @@ public: Q_strlcpy(m_CallbackName, funcname); }; - T GetUnique() const; + T *GetUnique() const; int GetIndex() const; fwdstate GetState() const; AMX *GetAmx() const; @@ -38,7 +40,7 @@ public: void SetState(fwdstate st); private: - T m_uniqueData; + T *m_uniqueData; int m_index; char m_CallbackName[64]; fwdstate m_state; @@ -47,7 +49,7 @@ private: // Inlines template -inline T CAmxxHook::GetUnique() const +inline T *CAmxxHook::GetUnique() const { return m_uniqueData; } diff --git a/reapi/src/entity_callback.cpp b/reapi/src/entity_callback.cpp index dc10ee8..03e6cd5 100644 --- a/reapi/src/entity_callback.cpp +++ b/reapi/src/entity_callback.cpp @@ -7,10 +7,10 @@ void CEntityCallback::PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type) auto it = m_callbacks.begin(); while (it != m_callbacks.end()) { - EntityCallback_t data = (*it)->GetUnique(); + eCallback_t *pUnique = (*it)->GetUnique(); // this callback was already sets, need to unregister the current forward - if (data.m_callbackType == type && data.m_entity == pEntity) { + if (pUnique->m_callbackType == type && pUnique->m_entity == pEntity) { delete (*it); it = m_callbacks.erase(it); } else { @@ -26,8 +26,8 @@ void CEntityCallback::Clear(CBaseEntity *pEntity) auto it = m_callbacks.begin(); while (it != m_callbacks.end()) { - EntityCallback_t data = (*it)->GetUnique(); - if (data.m_entity == pEntity) { + eCallback_t *pUnique = (*it)->GetUnique(); + if (pUnique->m_entity == pEntity) { delete (*it); it = m_callbacks.erase(it); } else { @@ -45,82 +45,107 @@ void CEntityCallback::Clear(CBaseEntity *pEntity) } } -bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) +bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) { PurgeCallbacks(pEntity, CType_Think); - int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + int fwdid; + if (iParamsLen > 0) { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); + } else { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + } + if (fwdid == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); return false; } - EntityCallback_t entry(pEntity, CType_Think); - m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, entry)); + m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Think))); pEntity->SetThink(&CBaseEntity::SUB_Think); return true; } -bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) +bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) { PurgeCallbacks(pEntity, CType_Touch); - int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + int fwdid; + if (iParamsLen > 0) { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); + } else { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + } + if (fwdid == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); return false; } - EntityCallback_t entry(pEntity, CType_Touch); - m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, entry)); + m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Touch))); pEntity->SetTouch(&CBaseEntity::SUB_Touch); return true; } -bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) +bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) { PurgeCallbacks(pEntity, CType_Use); - int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE); + int fwdid; + if (iParamsLen > 0) { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_DONE); + } else { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE); + } + if (fwdid == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); return false; } - EntityCallback_t entry(pEntity, CType_Use); - m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, entry)); + m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Use))); pEntity->SetUse(&CBaseEntity::SUB_Use); return true; } -bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) +bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) { PurgeCallbacks(pEntity, CType_Blocked); - int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + int fwdid; + if (iParamsLen > 0) { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE); + } else { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE); + } + if (fwdid == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); return false; } - EntityCallback_t entry(pEntity, CType_Blocked); - m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, entry)); + m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Blocked))); pEntity->SetTouch(&CBaseEntity::SUB_Blocked); return true; } -bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback) +bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen) { PurgeCallbacks(pEntity, CType_MoveDone); - int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + int fwdid; + if (iParamsLen > 0) { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE); + } else { + fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE); + } + if (fwdid == -1) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__); return false; } - EntityCallback_t entry(pEntity, CType_MoveDone); - m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, entry)); + m_callbacks.push_back(new CAmxxHook(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_MoveDone))); // TODO: Make sure that the entity actually inherited from CBaseToggle ((CBaseToggle *)pEntity)->SetMoveDone(&CBaseToggle::SUB_MoveDone); diff --git a/reapi/src/entity_callback.h b/reapi/src/entity_callback.h index 9a5c731..0d0f772 100644 --- a/reapi/src/entity_callback.h +++ b/reapi/src/entity_callback.h @@ -7,11 +7,11 @@ class CEntityCallback public: void Clear(CBaseEntity *pEntity = nullptr); - bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); - bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); - bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); - bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback); - bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback); + bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); + bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen); enum CallbackType_e { @@ -26,24 +26,53 @@ public: void FireCallbacks(CBaseEntity *pEntity, CallbackType_e type, volatile f_args... args) { for (auto fwd : m_callbacks) { - if (fwd->GetUnique().m_entity == pEntity && fwd->GetUnique().m_callbackType == type) { - g_amxxapi.ExecuteForward(fwd->GetIndex(), args...); + auto data = fwd->GetUnique(); + if (data->m_entity == pEntity && data->m_callbackType == type) + { + if (data->m_iParamLen > 0) { + g_amxxapi.ExecuteForward(fwd->GetIndex(), args..., g_amxxapi.PrepareCellArrayA(data->m_pParams, data->m_iParamLen, true)); + } else { + g_amxxapi.ExecuteForward(fwd->GetIndex(), args...); + } } } } private: void PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type); - struct EntityCallback_t + struct eCallback_t { - EntityCallback_t(CBaseEntity *pEntity, CallbackType_e type) : - m_entity(pEntity), m_callbackType(type) {}; + eCallback_t(CBaseEntity *pEntity, const cell *pParams, size_t iParamsLen, CallbackType_e type) : + m_entity(pEntity), m_callbackType(type) + { + if (iParamsLen > 0) { + m_iParamLen = iParamsLen + 1; + m_pParams = new cell[m_iParamLen]; + Q_memcpy(m_pParams, pParams, sizeof(cell) * iParamsLen); + m_pParams[iParamsLen] = 0; + } else { + m_iParamLen = 0; + m_pParams = nullptr; + } + }; + + ~eCallback_t() + { + if (m_pParams) { + delete[] m_pParams; + m_pParams = nullptr; + } + + m_iParamLen = 0; + } CBaseEntity *m_entity; CallbackType_e m_callbackType; + cell *m_pParams; + size_t m_iParamLen; }; - std::vector *> m_callbacks; + std::vector *> m_callbacks; }; extern CEntityCallback g_entCallback; diff --git a/reapi/src/meta_api.cpp b/reapi/src/meta_api.cpp index 1f6ac03..b66580e 100644 --- a/reapi/src/meta_api.cpp +++ b/reapi/src/meta_api.cpp @@ -33,7 +33,7 @@ META_FUNCTIONS gMetaFunctionTable = NULL, // pfnGetEntityAPI_Post META; called after game DLL GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL - NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL + GetNewDLLFunctions, // pfnGetNewDLLFunctions HL SDK2; called before game DLL NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL NULL, // pfnGetEngineFunctions META; called before HL engine NULL, // pfnGetEngineFunctions_Post META; called after HL engine diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index f8a9022..95b8d1f 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -256,19 +256,21 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params) } /* -* Sets callback for entity +* Sets Think callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Think_Callback(const ent)" * * @noreturn * -* native SetThink(const ent, const callback[]); +* native SetThink(const ent, const callback[], const params[] = "", const len = 0); */ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_handler }; + enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len }; CHECK_ISENTITY(arg_index); @@ -290,23 +292,26 @@ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params) return FALSE; } - return (cell)g_entCallback.SetThink(amx, pEntity, funcname); + cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; + return (cell)g_entCallback.SetThink(amx, pEntity, funcname, pParams, params[arg_len]); } /* -* Sets callback for entity +* Sets Touch callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)" * * @noreturn * -* native SetTouch(const ent, const callback[]); +* native SetTouch(const ent, const callback[], const params[] = "", const len = 0); */ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_handler }; + enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len }; CHECK_ISENTITY(arg_index); @@ -328,23 +333,26 @@ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params) return FALSE; } - return (cell)g_entCallback.SetTouch(amx, pEntity, funcname); + cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; + return (cell)g_entCallback.SetTouch(amx, pEntity, funcname, pParams, params[arg_len]); } /* -* Sets callback for entity +* Sets Use callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)" * * @noreturn * -* native SetUse(const ent, const callback[]); +* native SetUse(const ent, const callback[], const params[] = "", const len = 0); */ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_handler }; + enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len }; CHECK_ISENTITY(arg_index); @@ -366,23 +374,26 @@ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params) return FALSE; } - return (cell)g_entCallback.SetUse(amx, pEntity, funcname); + cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; + return (cell)g_entCallback.SetUse(amx, pEntity, funcname, pParams, params[arg_len]); } /* -* Sets callback for entity +* Sets Blocked callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)" * * @noreturn * -* native SetBlocked(const ent, const callback[]); +* native SetBlocked(const ent, const callback[], const params[] = "", const len = 0); */ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_handler }; + enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len }; CHECK_ISENTITY(arg_index); @@ -404,24 +415,27 @@ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params) return FALSE; } - return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname); + cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; + return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname, pParams, params[arg_len]); } /* -* Sets callback for entity -* @note Entity should be inherited from CBaseToggle, otherwise server can crash +* Sets MoveDone callback for entity * * @param entity Entity index * @param callback The forward to call +* * @note Use "" to reset callback +* @note Entity should be inherited from CBaseToggle, otherwise server can crash +* @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)" * * @noreturn * -* native SetMoveDone(const ent, const callback[]); +* native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0); */ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) { - enum args_e { arg_count, arg_index, arg_handler }; + enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len }; CHECK_ISENTITY(arg_index); @@ -443,7 +457,8 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params) return FALSE; } - return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname); + cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr; + return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname, pParams, params[arg_len]); } AMX_NATIVE_INFO Natives_Common[] =