AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Coding MM:S Plugins & SM Extensions (https://forums.alliedmods.net/forumdisplay.php?f=75)
-   -   g_pGameRules question (https://forums.alliedmods.net/showthread.php?t=95567)

Keeper 06-24-2009 22:41

g_pGameRules question
 
Ok, I've found the game rules via scanning (HL2MP). What am I supposed to do next? I need to hook some functions, and have tried and gotten an error reading that address. Maybe I've scanned for the wrong address, but I want to make sure that I'm thinking right so I can know when I get the right one.

Let's say I want to hook CGameRules:: DeathNotice

Assuming I scan for the g_pGameRules correctly, I use the following to hook that function:
Code:

SH_ADD_HOOK_MEMFUNC ( CGameRules, DeathNotice, g_pMyGameRules, &gPlugin, &CPlugin::MyDeathNotice, PRE );
Is my thinking right?

And no, I'm not using SDK tools...

Nite 06-25-2009 03:39

Re: g_pGameRules question
 
This is how I hook gamerules (in TF2). I basically hook by virtual table index. One of functions I hook in TF2 from CTFGameRules class is FlPlayerFallDamage (returns a float or amount of fall damage taken).

Code:

58    CTFGameRules::FlPlayerFallDamage(CBasePlayer *)
So I first declare it like other hooks:

Code:

SH_DECL_MANUALHOOK1(GR_FlPlayerFallDamage, 58, 0, 0, float, CBasePlayer*);
Then I hook it in other function that is part of a class (CGamerulesHooks) to deal with hooking gamerules functions.

Code:

//to hook
void CGamerulesHooks::SetupHooks()
{
  SH_ADD_MANUALHOOK_MEMFUNC(GR_FlPlayerFallDamage, g_pGameRules, this, &CGamerulesHooks::Hook_FlPlayerFallDamage, false);
}
 
//to unhook
void CGamerulesHooks::RemoveHooks()
{
  SH_REMOVE_MANUALHOOK_MEMFUNC(GR_FlPlayerFallDamage, g_pGameRules, this, &CGamerulesHooks::Hook_FlPlayerFallDamage, false);
}

I unhook gamerules functions at LevelShutdown. Then on ServerActivate I re-obtain gamerules pointer and rehook the gamerules functions (not sure if that is needed but I've been doing this for a while to be on safe side). One thing I noticed is I have to delay the signature scan for it for about 0.10 seconds after ServerActivate, otherwise the pointer is NULL for some reason.

Hope that helps.

Keeper 06-25-2009 13:16

Re: g_pGameRules question
 
Ok, that makes complete sense to me now. Dumping the vtable for the game rules. And I've gone through the binaries over and over again, and I'm 99.9% certain I have the correct address for the gamerules. When I try to access them in any way I get
Quote:

Unhandled exception at 0x0e11c4f1 (keeper_plugins.dll) in srcds.exe: 0xC0000005: Access violation reading location 0x6e29940d.
So I must still be doing something wrong. Did you define your g_pGameRules as CTFGameRules *?

Nite 06-25-2009 15:01

Re: g_pGameRules question
 
Quote:

Originally Posted by Keeper (Post 856858)
So I must still be doing something wrong. Did you define your g_pGameRules as CTFGameRules *?

Nope. I just declare it how it is in SDK just at top of my main plugin cpp file and extern it in header file. Like so:

Code:

CGameRules *g_pGameRules = NULL;
This is what I do for signature scan, I used SourceMod's SDKTools extension (vglobals.cpp file) as an example (Linux part is not tested since my plugin is Windows only build):

Code:

CGameRules *CSignatures::GetGameRules()
{
    static CGameRules *rules = NULL;
#ifdef WIN32
    if (!m_pCreateGameRulesObject)
    {
        LogSigError("CreateGameRulesObject");
        return NULL;
    }
    char *addr = (char*)m_pCreateGameRulesObject;
    rules = **reinterpret_cast<CGameRules***>(addr + 2);
#else
    void *pHandle, *pAddr, *pBase;
    Dl_info info;
    pBase = (void*)g_SMAPI->GetServerFactory(false);
    if (dladdr(pBase, &info) !=0)
    {
        pHandle = dlopen(info.dli_fname, RTLD_NOW);
        if (pHandle)
        {
            pAddr = dlsym(pHandle, "g_pGameRules");
            dlclose(pHandle);
            rules = *(CGameRules**)pAddr;
        }
    }
#endif
    return rules;
}


Keeper 06-25-2009 23:27

Re: g_pGameRules question
 
Ok, I already hook another variable, so I know the code works. It definitely doesn't crash on Linux. I guess my 99.9% was just that ... not a sure thing. I'll look for the sig again tomorrow and see if I can't make some progress in the windows world.

EDIT: While my linux side doesn't crash, none of the hooks are being called either. I'm going back to square one to try and figure this out.

voogru 06-27-2009 03:38

Re: g_pGameRules question
 
You don't need a signature to obtain the gamerules fyi.


Find the "tf_gamerules" entity, when it spawns:

Code:

ServerClass *pServerClass = SH_MCALL(BaseEntity(), GetServerClass)();
        void                *pTFGameRules = NULL;

        if(pServerClass)
        {
                int i, iCount;
                iCount = pServerClass->m_pTable->GetNumProps();
                for(i = 0;i < iCount ;i++)
                {
                        if(FStrEq(pServerClass->m_pTable->GetProp(i)->GetName(), "tf_gamerules_data"))
                        {
                                pTFGameRules = (*pServerClass->m_pTable->GetProp(i)->GetDataTableProxyFn())(NULL, NULL, NULL, NULL, 0);
                                break;
                        }
                }               
        }

Wham, bam, gamerules pointer.

Keeper 06-27-2009 09:05

Re: g_pGameRules question
 
ooooooooh, saixy. I'll give that a shot. Thanks!


All times are GMT -4. The time now is 16:34.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.