I'm new c++ and extension and i made my extension for some detour functions, compile/build works okay. But server does crash when PrintIfWatched detouring.
so I oversaw PrintIfWatched source-code, and i found that function uses variable argument. I have no idea how to detour that function.
and I'm sure signatures are correct.
PrintIfWatched code :
https://github.com/VSES/SourceEngine...ot/bot.h#L1011
my extension.cpp
Code:
#include "extension.h"
IGameConfig *g_pGameConf;
IForward *g_pOnStopFollowing;
IForward *g_pOnSetState;
IForward *g_pOnPrintIfWatched;
CDetour *dtrStopFollowing;
CDetour *dtrSetState;
CDetour *dtrPrintIfWatched;
BotController g_BotController;
SMEXT_LINK(&g_BotController);
DETOUR_DECL_MEMBER0(StopFollowing, void)
{
CBaseEntity *pBot = (CBaseEntity *)this;
cell_t result = g_BotController.OnStopFollowing(pBot);
if (result == Pl_Handled || result == Pl_Stop)
return;
DETOUR_MEMBER_CALL(StopFollowing)();
}
DETOUR_DECL_MEMBER1(SetState, void, cell_t, state)
{
CBaseEntity *pBot = (CBaseEntity *)this;
cell_t result = g_BotController.OnSetState(pBot, state);
if (result == Pl_Handled || result == Pl_Stop)
return;
DETOUR_MEMBER_CALL(SetState)(state);
}
DETOUR_DECL_MEMBER1(PrintIfWatched, void, char *, message)
{
CBaseEntity *pBot = (CBaseEntity *)this;
cell_t result = g_BotController.OnPrintIfWatched(pBot, message);
if (result == Pl_Handled || result == Pl_Stop)
return;
DETOUR_MEMBER_CALL(PrintIfWatched)(message);
}
bool BotController::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
if (!gameconfs->LoadGameConfigFile("bot.games", &g_pGameConf, error, maxlength))
return false;
g_pOnStopFollowing = g_pForwards->CreateForward("CCSBot_OnStopFollowing", ET_Hook, 1, NULL, Param_Cell);
g_pOnSetState = g_pForwards->CreateForward("CCSBot_OnSetState", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
g_pOnPrintIfWatched = g_pForwards->CreateForward("CCSBot_OnPrintIfWatched", ET_Hook, 2, NULL, Param_Cell, Param_String);
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
dtrStopFollowing = DETOUR_CREATE_MEMBER(StopFollowing, "CCSBot::StopFollowing");
if (!dtrStopFollowing)
return false;
dtrSetState = DETOUR_CREATE_MEMBER(SetState, "CCSBot::SetState");
if (!dtrSetState) {
smutils->Format(error, maxlength, "Detour failed: CCSBot::SetState");
return false;
}
dtrPrintIfWatched = DETOUR_CREATE_MEMBER(PrintIfWatched, "CCSBot::PrintIfWatched");
if (!dtrPrintIfWatched) {
smutils->Format(error, maxlength, "Detour failed: CCSBot::PrintIfWatched");
return false;
}
dtrStopFollowing->EnableDetour();
dtrSetState->EnableDetour();
dtrPrintIfWatched->EnableDetour();
g_SMAPI->ConPrint("Bot Controller Extension Loaded");
return true;
}
void BotController::SDK_OnUnload()
{
if (dtrStopFollowing != NULL) {
dtrStopFollowing->Destroy();
dtrStopFollowing = NULL;
}
if (dtrSetState != NULL) {
dtrSetState->Destroy();
dtrSetState = NULL;
}
if (dtrPrintIfWatched != NULL) {
dtrPrintIfWatched->Destroy();
dtrPrintIfWatched = NULL;
}
}
cell_t BotController::OnStopFollowing(CBaseEntity *pBot)
{
g_pOnStopFollowing->PushCell(gamehelpers->EntityToBCompatRef(pBot));
cell_t retValue = Pl_Continue;
g_pOnStopFollowing->Execute(&retValue);
return retValue;
}
cell_t BotController::OnSetState(CBaseEntity *pBot, cell_t stateAddress)
{
g_pOnSetState->PushCell(gamehelpers->EntityToBCompatRef(pBot));
g_pOnSetState->PushCell(stateAddress);
cell_t retValue = Pl_Continue;
g_pOnSetState->Execute(&retValue);
return retValue;
}
cell_t BotController::OnPrintIfWatched(CBaseEntity *pBot, char *message)
{
if (pBot == NULL)
return Pl_Continue;
cell_t pBotRef = gamehelpers->EntityToBCompatRef(pBot);
g_SMAPI->LogMsg(g_PLAPI, "%d %s", pBotRef, message);
g_pOnPrintIfWatched->PushCell(pBotRef);
g_pOnPrintIfWatched->PushString(message);
cell_t retValue = Pl_Continue;
g_pOnPrintIfWatched->Execute(&retValue);
return retValue;
}
and my extension.h
Code:
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define CCSPlayer CBasePlayer
/**
* @file extension.h
* @brief Sample extension code header.
*/
#include "smsdk_ext.h"
#include "CDetour/detours.h"
/**
* @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
*/
class BotController : public SDKExtension
{
public:
/**
* @brief This is called after the initial loading sequence has been processed.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail.
*/
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
/**
* @brief This is called right before the extension is unloaded.
*/
virtual void SDK_OnUnload();
/**
* @brief This is called once all known extensions have been loaded.
* Note: It is is a good idea to add natives here, if any are provided.
*/
//virtual void SDK_OnAllLoaded();
/**
* @brief Called when the pause state is changed.
*/
//virtual void SDK_OnPauseChange(bool paused);
/**
* @brief this is called when Core wants to know if your extension is working.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @return True if working, false otherwise.
*/
//virtual bool QueryRunning(char *error, size_t maxlength);
public:
#if defined SMEXT_CONF_METAMOD
/**
* @brief Called when Metamod is attached, before the extension version is called.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/**
* @brief Called when Metamod is detaching, after the extension version is called.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
/**
* @brief Called when Metamod's pause state is changing.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param paused Pause state being set.
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
cell_t OnStopFollowing(CBaseEntity *bot);
cell_t OnSetState(CBaseEntity *bot, cell_t stateAddress);
cell_t OnPrintIfWatched(CBaseEntity *bot, char *message);
};
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_