Monthly Target: $400 Donations: $602
 150% 

DHooks (Dynamic Hooks - Dev Preview)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Dr!fter
SourceMod Developer
Join Date: Mar 2007
Old 03-10-2012 , 20:46   DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #1

Oh no, not ANOTHER hooks extension!!!

This extension is not just ANOTHER hooks extension But rather allows sourcemod plugins to create their own hooks. It has a very limited (currently) param and return type support.

Return types supported


Param types supported


Note that you cannot set or get a unknown param/return's value.

If you feel that a common param type is missing let me know and ill try to add support for it. This currently also allows for a total 10 params for a function. If you need to hook a function with more params also let me know and ill add support for more

So, some examples! (This example plugin is inside the zip and is only for cs:s and l4d2)

PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <dhooks>

// int CBaseCombatCharacter::BloodColor(void)
new Handle:hBloodColor;

// bool CBaseCombatCharacter::Weapon_CanUse(CBaseCombatWeapon *)
new Handle:hHookCanUse;

// Vector CBasePlayer::GetPlayerMaxs()
new Handle:hGetMaxs;

// string_t CBaseEntity::GetModelName(void)
new Handle:hGetModelName;

// bool CGameRules::CanHaveAmmo(CBaseCombatCharacter *, int)
new Handle:hCanHaveAmmo;

// void CBaseEntity::SetModel(char  const*)
new Handle:hSetModel;

//float CCSPlayer::GetPlayerMaxSpeed()
new Handle:hGetSpeed;

//void CDirector::OnGameplayStart()
new Handle:hGameplayStart;

//int CCSPlayer::OnTakeDamage(CTakeDamageInfo const&)
new Handle:hTakeDamage;

enum GameType
{
    
GameUnknown,
    
GameCstrike,
    
GameL4D2
};
new 
GameType:gametype GameUnknown;

public 
OnPluginStart()
{
    new 
Handle:temp LoadGameConfigFile("dhooks-test.games");
    if(
temp == INVALID_HANDLE)
        
SetFailState("Why you no has gamedata?");
    
    new 
String:game[64];
    
GetGameFolderName(gamesizeof(game));
    new 
offset;
    
    if(
strcmp(game"cstrike") == 0)
    {
        
gametype GameCstrike;
        
offset GameConfGetOffset(temp"BloodColor");
        
hBloodColor DHookCreate(offsetHookType_EntityReturnType_IntThisPointer_CBaseEntityBloodColorPost);
    
        
offset GameConfGetOffset(temp"GetModelName");
        
hGetModelName DHookCreate(offsetHookType_EntityReturnType_StringThisPointer_CBaseEntityGetModelName);
    
        
offset GameConfGetOffset(temp"GetMaxs");
        
hGetMaxs DHookCreate(offsetHookType_EntityReturnType_VectorThisPointer_IgnoreGetMaxsPost);
    
        
offset GameConfGetOffset(temp"CanUse");
        
hHookCanUse DHookCreate(offsetHookType_EntityReturnType_BoolThisPointer_CBaseEntityCanUsePost);
        
DHookAddParam(hHookCanUseHookParamType_CBaseEntity);
    
        
offset GameConfGetOffset(temp"CanHaveAmmo");
        
hCanHaveAmmo DHookCreate(offsetHookType_GameRulesReturnType_BoolThisPointer_IgnoreCanHaveAmmoPost);
        
DHookAddParam(hCanHaveAmmoHookParamType_CBaseEntity);
        
DHookAddParam(hCanHaveAmmoHookParamType_Int);
    
        
offset GameConfGetOffset(temp"SetModel");
        
hSetModel DHookCreate(offsetHookType_EntityReturnType_VoidThisPointer_CBaseEntitySetModel);
        
DHookAddParam(hSetModelHookParamType_CharPtr);
    
        
offset GameConfGetOffset(temp"GetMaxPlayerSpeed");
        
hGetSpeed DHookCreate(offsetHookType_EntityReturnType_FloatThisPointer_CBaseEntityGetMaxPlayerSpeedPost);
        
        
offset GameConfGetOffset(temp"OnTakeDamage");
        
hTakeDamage DHookCreate(offsetHookType_EntityReturnType_IntThisPointer_CBaseEntityOnTakeDamage);
        
DHookAddParam(hTakeDamageHookParamType_ObjectPtr);
    }
    else if(
strcmp(game"left4dead2") == 0)
    {
        
gametype GameL4D2;
        new 
Address:addr GameConfGetAddress(temp"CDirector");
        
offset GameConfGetOffset(temp"OnGameplayStart");
        
hGameplayStart DHookCreate(offsetHookType_RawReturnType_VoidThisPointer_IgnoreOnGameplayStart);
        
DHookRaw(hGameplayStarttrueaddrRemovalCB);
    }
    
DHookAddEntityListener(ListenType_CreatedEntityCreated);
    
DHookAddEntityListener(ListenType_DeletedEntityDeleted);
    
CloseHandle(temp);
    
}
public 
OnMapStart()
{
    if(
gametype == GameCstrike)
    {
        
//Hook Gamerules function in map start
        
DHookGamerules(hCanHaveAmmotrueRemovalCB);
    }
}
public 
OnClientPutInServer(client)
{
    if(
gametype == GameCstrike)
    {
        
DHookEntity(hBloodColortrueclientRemovalCB);
        
DHookEntity(hHookCanUsetrueclientRemovalCB);
        
DHookEntity(hGetMaxstrueclientRemovalCB);
        
DHookEntity(hGetModelNametrueclientRemovalCB);
        
DHookEntity(hSetModelfalseclientRemovalCB);
        
DHookEntity(hGetSpeedtrueclientRemovalCB);
        
        
//Dont add removal callback for this one
        
DHookEntity(hTakeDamagefalseclient);
    }

}
public 
EntityCreated(entity, const String:classname[])
{
    
PrintToServer("Entity %i has been created it is %s"entityclassname);
}
public 
EntityDeleted(entity)
{
    
PrintToServer("Entity %i has been deleted"entity);
}
//int CCSPlayer::OnTakeDamage(CTakeDamageInfo const&)
public MRESReturn:OnTakeDamage(thisHandle:hReturnHandle:hParams)
{
    
PrintToServer("DHooksHacks = Victim %i, Attacker %i, Inflictor %i, Damage %f"thisDHookGetParamObjectPtrVar(hParams140ObjectValueType_Ehandle), DHookGetParamObjectPtrVar(hParams136ObjectValueType_Ehandle), DHookGetParamObjectPtrVar(hParams148ObjectValueType_Float));
    
    if(
this <= MaxClients && this && !IsFakeClient(this))
    {
        
DHookSetParamObjectPtrVar(hParams148ObjectValueType_Float0.0);
        
PrintToChat(this"Pimping your hp");
    }
}
//void CDirector::OnGameplayStart()
public MRESReturn:OnGameplayStart()
{
    
PrintToServer("Gameplay starting!");
    return 
MRES_Ignored;
}
// void CBaseEntity::SetModel(char  const*)
public MRESReturn:SetModel(thisHandle:hParams)
{
    
//Change all bot skins to phoenix one
    
if(IsFakeClient(this))
    {
        
DHookSetParamString(hParams1"models/player/t_phoenix.mdl");
        return 
MRES_ChangedHandled;
    }
    return 
MRES_Ignored;
}
//float CCSPlayer::GetPlayerMaxSpeed()
public MRESReturn:GetMaxPlayerSpeedPost(thisHandle:hReturn)
{
    if(
IsFakeClient(this))
        return 
MRES_Ignored;
    
    
//Change return max speed for non bots.
    
DHookSetReturn(hReturn1000.0);
    return 
MRES_Override;
}
// bool CGameRules::CanHaveAmmo(CBaseCombatCharacter *, int)
public MRESReturn:CanHaveAmmoPost(Handle:hReturnHandle:hParams)
{
    
PrintToServer("Can has ammo? %s %i"DHookGetReturn(hReturn)?"true":"false"DHookGetParam(hParams2));
    return 
MRES_Ignored;
}
// string_t CBaseEntity::GetModelName(void)
public MRESReturn:GetModelName(thisHandle:hReturn)
{
    if(
IsFakeClient(this))
    {
        new 
String:returnval[128];
        
DHookGetReturnString(hReturnreturnvalsizeof(returnval));
        
PrintToServer("It is a bot, Model should be: models/player/t_phoenix.mdl It is %s"returnval);
    }
    return 
MRES_Ignored;
    
}
// Vector CBasePlayer::GetPlayerMaxs()
public MRESReturn:GetMaxsPost(Handle:hReturn)
{
    new 
Float:vec[3];
    
DHookGetReturnVector(hReturnvec);
    
PrintToServer("Get maxes %.1f, %.1f, %.1f"vec[0], vec[1], vec[2]);
    return 
MRES_Ignored;
}
// bool CBaseCombatCharacter::Weapon_CanUse(CBaseCombatWeapon *)
public MRESReturn:CanUsePost(thisHandle:hReturnHandle:hParams)
{
    
//Deny bots everything
    
if(IsFakeClient(this))
    {
        
DHookSetReturn(hReturnfalse);
        return 
MRES_Override;
    }
    return 
MRES_Ignored;
}
// int CBaseCombatCharacter::BloodColor(void)
public MRESReturn:BloodColorPost(thisHandle:hReturn)
{
    
//Change the bots blood color to goldish yellow
    
if(IsFakeClient(this))
    {
        
DHookSetReturn(hReturn2);
        return 
MRES_Override;
    }
    return 
MRES_Ignored;
}
public 
RemovalCB(hookid)
{
    
PrintToServer("Removed hook %i"hookid);

As a basic note, if the return type is void there won’t be a return handle pushed to the callback. If there is no params no param handle will be pushed. If this pointer is set to ignore this won’t be pushed.

Here is a quick example written for TF2 to stop round ending. (Not tested just wrote it )
PHP Code:
new Handle:hWinning;
public 
OnPluginStart()
{
    new 
Handle:temp LoadGameConfigFile("tf2-roundend.games");
    if(
temp == INVALID_HANDLE)
        
SetFailState("Why you no has gamedata?");
    
    new 
offset;
    
    
offset GameConfGetOffset(temp"SetWinningTeam");
    
hWinningDHookCreate(offsetHookType_GameRulesReturnType_VoidThisPointer_IgnoreWinningPre);
    
DHookAddParam(hWinningHookParamType_Int);
    
DHookAddParam(hWinningHookParamType_Int);
    
DHookAddParam(hWinningHookParamType_Bool);
    
DHookAddParam(hWinningHookParamType_Bool);
    
DHookAddParam(hWinningHookParamType_Bool);
    
    
CloseHandle(temp);
}
public 
OnMapStart()
{
    if(
hWinning != INVALID_HANDLE)
    {
        
DHookGamerules(hWinningfalseRemovalCB);
    }
}
public 
MRESReturn:WinningPre(Handle:hParams)
{
    return 
MRES_Supercede;
}
public 
RemovalCB(hookid)
{
    
PrintToServer("Removed hook %i"hookid);

TF2 win block gamedata


Gamedata for the test plugin is inside the zip.

Note: Gamerule hooks are removed OnMapEnd so you must hook them again in OnMapStart. Entity hooks are removed when the entity is removed.

Thats all there is to it!

Since this is a dev preview crashes can happen. I mostly tested in CS: S Windows. If you experience a crash please post the function, game, OS, and code. This extension can replace most of SDKHooks hooks but not all... yet

Changelog:
  • 1.0.1-pre-alpha
    • Added Raw hook (allows passing class pointer)
    • Fixed certain hooks unhooking randomly.
  • 1.0.2-alpha
    • Added support for more params (new max is 10)
    • Added ability to add entity listeners (To hook OnEntityCreated and OnEntityDestroyed)
    • Changed from pre-alpha to alpha
  • 1.0.3-alpha
    • Fixed various memory leaks.
    • Fixed requiring latest gamehelpers i face
  • 1.0.4-alpha
    • Added support for Object pointer params (CTakeDamage in OnTakeDamage for example)
    • Removed the need for a removal callback when hooking (Its not mandatory now).
  • 1.0.5-alpha
    • Fixed a crash when a hook was removed that had no removal callback.
  • 1.0.6-alpha
    • Fixed a crash on newer engines.
  • 1.0.7-alpha
    • Fixed a crash with strings
    • Fixed a crash on new engines
    • Added support for CS:GO
    • Added support for edict_t
  • 1.0.8-alpha
    • Added support for getting the address of |this|
  • 1.0.9-alpha
    • Removed asserts from OnEntityCreated
  • 1.0.11-alpha
    • Made engine specific builds so that it works with tf2 again.
    • Hopefully fixed crashes in CS:GO in OnEntityCreated
    • Fixed a bug using Edict params.
    • Requires SM 1.5 and MM:S 1.9+
  • 1.0.12-alpha
    • Fixed crashing when accessing NULL pointers
    • Added native to check if a param is NULL before accessing it (DHookIsNullParam)
  • 1.0.13-alpha
    • Fixed a memory leak when unhooking entities.
    • Removed the need for gamedata by switching to SDKHooks entity listeners.
Current builds supported are CS:S, CS:GO, OBV, L4D/2. Other builds can be supported per request.
Note: You can delete the old dhooks files without the engine extensions (dhooks.ext.dll and dhooks.ext.so).

P.S Don't laugh at my code But feel free to point out ways to improve it.

Credits:
asherkin - Explaining how SourceHook changes params along with other tidbits of info.
psychonic - For SDKHooks code to look at and answering way too many questions.

The source code can be found here: https://bitbucket.org/Drifter321/dhooks

DHooks2 Builds : http://users.alliedmods.net/~drifter/builds/dhooks/2.0/ (Requires SM 1.7)
Attached Files
File Type: zip dhooks-1.0.13-alpha.zip (1.91 MB, 3476 views)
__________________
Like my work? Donate!

Last edited by Dr!fter; 09-12-2014 at 10:35.
Dr!fter is offline
donrevan
SourceMod Donor
Join Date: Jul 2010
Old 03-11-2012 , 05:56   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #2

I can't belive it! This is so much awesome!! It will replace nearly all my "just-a-hook-extensions" thank you for releasing this (did I already said this IS awesome?)

Last edited by donrevan; 03-11-2012 at 06:11.
donrevan is offline
Thrawn2
Veteran Member
Join Date: Apr 2009
Old 03-11-2012 , 09:18   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #3

Nice work!
Is being used by this.
__________________
einmal mit profis arbeiten. einmal.
Thrawn2 is offline
Zephyrus
Cool Pig B)
Join Date: Jun 2010
Location: Hungary
Old 03-11-2012 , 11:37   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #4

ill use it with my hats plugin to hook setentitymodel, thank you, nice job
__________________
Taking private C++/PHP/SourcePawn requests, PM me.
Zephyrus is offline
Peace-Maker
SourceMod Plugin Approver
Join Date: Aug 2008
Location: Germany
Old 03-11-2012 , 13:52   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #5

Wow, that's more than useful. I'll definetly mess with this Thank you!
__________________
Peace-Maker is offline
KyleS
SourceMod Plugin Approver
Join Date: Jul 2009
Location: Segmentation fault.
Old 03-11-2012 , 14:42   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #6

Your example has already done something I've been looking to do for a while now, thanks a ton Drifter!
KyleS is offline
Dreamy
SourceMod Donor
Join Date: Mar 2012
Old 03-11-2012 , 15:04   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #7

awsum, great job!! =)
Dreamy is offline
Dr!fter
SourceMod Developer
Join Date: Mar 2007
Old 03-13-2012 , 20:54   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #8

Updated the extension to add support for raw pointer address's. There is an example using CDirector for left4dead2 in the test plugin. Also fixed hooks randomly getting unhooked if they weren't entity hooks.
__________________
Like my work? Donate!
Dr!fter is offline
Dr!fter
SourceMod Developer
Join Date: Mar 2007
Old 03-17-2012 , 10:50   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #9

Updated again. Full changelog is in the original post. I removed the "pre-alpha" tag and made it an alpha. Ive been getting more time to test different hooks and seems to be working good so that is the reason
__________________
Like my work? Donate!
Dr!fter is offline
KyleS
SourceMod Plugin Approver
Join Date: Jul 2009
Location: Segmentation fault.
Old 03-18-2012 , 02:01   Re: DHooks (Dynamic Hooks - Dev Preview)
Reply With Quote #10

<KyleS> Drifter, Are you aware of any leaks in DHooks? D:
* ViolentCrimes has quit (Read error: Connection reset by peer)
<KyleS> Drifter, http://pastie.org/private/vxdnhepkmhi7wowytmydcg - If the client is kicked, if the plugin or ext is unloaded, the memory still isn't freed. I'm not sure where it's occuring. I could fire up Valgrind though if you can't reproduce it.
<KyleS> Hit about 2.5gb in 12h lol D:
KyleS is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 05:20.


Powered by vBulletin®
Copyright ©2000 - 2015, vBulletin Solutions, Inc.
Theme made by Freecode