Raised This Month: $51 Target: $400
 12% 

using SH_MCALL


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
L. Duke
Veteran Member
Join Date: Apr 2005
Location: Walla Walla
Old 05-30-2006 , 19:28   using SH_MCALL
Reply With Quote #1

I'm trying to use a manual call on CBaseCombatWeapon::GetName()
Code:
char *Restrict2Plugin::Call_GetName(CBaseCombatWeapon *pWeapon)
{
	char *ret;
	SourceHook::ManualCallClass *pWeapon_CC;
	pWeapon_CC = SH_GET_MCALLCLASS(pWeapon, sizeof(CBaseCombatWeapon*));
	ret = SH_MCALL(pWeapon_CC, GetName_hook) (pWeapon);
	SH_RELEASE_CALLCLASS(pWeapon_CC);
	return ret;

}
I know I'm doing something wrong here cause it crashes to somewhere not in my code. It's probably a simple mistake.
L. Duke is offline
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 05-30-2006 , 21:19  
Reply With Quote #2

Show the declarations..
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
L. Duke
Veteran Member
Join Date: Apr 2005
Location: Walla Walla
Old 05-31-2006 , 10:49  
Reply With Quote #3

Code:
/*
  manual hooks
*/

// offsets for windows are 1 more than linux
#ifdef WIN32
    #define VTABLE_OFFSET 0
#else
    #define VTABLE_OFFSET 1
#endif

// vtable offsets
#define VTABLE_OFFSET_WEAPONCANUSE 200 + VTABLE_OFFSET		// CCSPlayer
#define VTABLE_OFFSET_GETNAME 262 + VTABLE_OFFSET			// CBaseCombatWeapon

// hook defintions
SH_DECL_MANUALHOOK1(WeaponCanUse_hook, VTABLE_OFFSET_WEAPONCANUSE, 0, 0, bool, CBaseCombatWeapon *);
SH_DECL_MANUALHOOK0(GetName_hook, VTABLE_OFFSET_GETNAME, 0, 0, char *);
L. Duke is offline
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 05-31-2006 , 13:02  
Reply With Quote #4

pWeapon_CC = SH_GET_MCALLCLASS(pWeapon, sizeof(void*));

PM mentioned that in his post.

Also, don't get the Call Class in any heavily used functions, there is alot of overhead with actually getting the call class.
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
L. Duke
Veteran Member
Join Date: Apr 2005
Location: Walla Walla
Old 05-31-2006 , 19:03  
Reply With Quote #5

OK, thanks.

I'll just go back to the virtual function call method from PM/Mani before SH_MCALL was added. Especially for this function which will be called fairly frequently.
L. Duke is offline
BAILOPAN
Join Date: Jan 2004
Old 05-31-2006 , 20:15  
Reply With Quote #6

Remember that the point of SH_MCALL is to call the original, rather than re-invoke the hook chain. If you know you're going to be calling it often, just retrieve the callclass early on.
__________________
egg
BAILOPAN is offline
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 05-31-2006 , 21:47  
Reply With Quote #7

Quote:
Originally Posted by L. Duke
OK, thanks.

I'll just go back to the virtual function call method from PM/Mani before SH_MCALL was added. Especially for this function which will be called fairly frequently.
Sorry I came across wrong, I didn't mean not to use this method, I mean't when using this method in a released application, that it would be beneficial to get the call class on creation of the entity or ClientPutInServer depending on the app, and use it to invoke the call during any functions instead of using SH_GET_MCALLCLASS in every GetName function.
In other words, only get the pointer once but calling the function is not as intensive.
Sorry for the misconception.
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
TommyV
Member
Join Date: Nov 2005
Old 06-06-2006 , 01:00  
Reply With Quote #8

How much overhead is involved in retrieving the call class?

I have a function that loops through all players and manually calls weapon_getslot on all players, and then might manually call weapon_drop if the weapon is restricted. I switched to using manual call classes instead of the mani/mp method L. Duke mentioned, I'm not really concerned about not invoking any other hooks on these functions it just feels more SourceMMy to use call classes, so should I switch back? The function is only ever called at round start.
TommyV is offline
BAILOPAN
Join Date: Jan 2004
Old 06-06-2006 , 01:35  
Reply With Quote #9

it's considered expensive as in fine-tuning optimization. you wouldn't want to call this every frame, but it's not gonna be like you're selecting 100,000 rows from sqlite3 or using blocking sockets across the country.

the best idea, as said already, is to obtain the callclass when the player connects, save them per-player, and free them on disconnect.
__________________
egg
BAILOPAN is offline
PM
hello, i am pm
Join Date: Jan 2004
Location: Canalization
Old 06-06-2006 , 09:54  
Reply With Quote #10

GetCallClass first checks whether there is an existing callclass with matching interface pointer/size. If yes, it simply increments its reference counter and returns a pointer to it.

If no matching call class is found, a new one is created. This is pretty expensive, because the callclass is first created on the stack (yeah, pretty braindead :s ), then, SourceHook loops through all hooked virtual function pointers, and adds info about the vtbl offset/vtbl index/original function pointer to the callclass if it is affected. Then the callclass object is copied to the call class list, and a pointer to it is returned. (in case you wonder, the refcounter isn't incremented because it defaults to 1 in the constructor ;) )

In case you wonder how callclasses are implemented exactly:

A callclass object contains three things:
- The interface pointer
- The instance size
- A original function pointer table.

The original function table is basically a map<int, vector<void*> >; that is, the key of the map represents the offset to the virtual function table, and the value of the map entry is a vector of pointers, where each element represents one virtual function index (i call it vtable index).

If the key doesn't exist or the vtable index is out of range or the corresponding element in the vector is NULL, there is no hook on that function.

Otherwise, you get the original function pointer by evaluating:

callclass->m_VT[vtable_offset][vtable_index]
__________________
hello, i am pm
PM is offline
Reply



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 11:03.


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