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

CollisionHook


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 10-07-2012 , 20:18   CollisionHook
Reply With Quote #1

HEY READ THIS (MARCH 2024)
The notice below still holds. I don't personally use this extension, but contributions on GitHub are welcome.


HEY READ THIS (DEC 2014)
I know you probably really want to use this extension, but here's the fine print: it's now completely unsupported by myself. If you need gamedata updates you're on your own. This extension should be a last resort when you have exhausted all other options for managing collisions: m_nSolidType, m_CollisionGroup, etc

This extension provides a straightforward and easy way to hook and modify collision rules between entities.

You might say "but sdkhooks provides this functionality already!", and you would be partly right. However, I wasn't happy with how sdkhooks ShouldCollide works, and here's why:

If you're familiar with sdkhooks, this code won't be new:
PHP Code:
// somewhere in your code
SDKHooksomeEntitySDKHook_ShouldCollideShouldCollide );

public 
bool:ShouldCollideentitycollisiongroupcontentsmaskbool:result )
{
    
// modify collision rules

As you can see, the hook doesn't provide much information about exactly which entities are colliding; only the collision group and contents mask of the other entity are given to the plugin developer.


To solve this limitation, I wrote CollisionHook.

CollisionHook provides 2 forwards to plugins, both of which can modify the collision rules of certain types of collisions.

PHP Code:
forward Action:CH_ShouldCollideent1ent2, &bool:result ); 
CH_ShouldCollide is called when vphysics is determining whether two vphysics objects (and their associated entities) should collide. Examples of these kinds of collisions include projectiles colliding with the world entity.

PHP Code:
forward Action:CH_PassFilterent1ent2, &bool:result ); 
CH_PassFilter is called when the game is performing a ray/hull trace and is making use of an entity filter. Examples of these kinds of collisions include player-player collisions.

To modify the behavior of the collision check, simply set result to true if you wish for the entities to collide; otherwise false, and return Plugin_Handled or Plugin_Stop in the forward. If you want the game to use default collision rules, simply return Plugin_Continue in the forward.


The benefits of both of these forwards is that you can strictly control which entities can collide, instead of just a specific type of entity.

Installation
  1. Grab the latest release from here.
  2. Drag & Drop.

Source
The source code is available here.


Limitations / Known Issues / Notes
  • Some collisions are not handled by this extension, those include collisions that are checked with traces that don't use an entity filter. Many of these can be handled by sdkhooks' Touch hook.
  • Modifying collisions that are also performed on the client will lead to prediction errors. This is no different from other server-only methods of overriding collisions.
  • This extension should work for any OB-based mod (TF2 CS:S, DoD:S), but it's only been tested on TF2.

Thanks
  • AzuiSleet, for suggesting PassServerEntityFilter for trace based collisions.
  • psychonic, for providing the linux build, makefile, and generally being the most helpful person on the planet.
__________________

Last edited by VoiDeD; 03-15-2024 at 19:42.
VoiDeD is offline
GoD-Tony
Veteran Member
Join Date: Jul 2005
Old 10-08-2012 , 05:04   Re: CollisionHook
Reply With Quote #2

This is a neat idea! I tried something like this myself a while ago and ran into a few issues with a PassServerEntityFilter detour.

Using this code for example:
PHP Code:
public Action:CH_PassFilterent1ent2, &bool:result )
{
    
// No client-client collisions
    
if (<= ent1 <= MaxClients && <= ent2 <= MaxClients)
    {
        
result false;
        return 
Plugin_Handled;
    }
    
    return 
Plugin_Continue;

This is all on CS:S, and the code above seems to crash when shooting a player.

Normally it would prevent trace weapons from hitting any player target, because the player firing is passed as pPass. So in order to differentiate player collision traces from the rest, I detoured CTraceFilterSimple::ShouldHitEntity instead which provided collisionGroup and contentsMask.

Mine ended up looking like this:
(unreleased because I thought it was an ugly workaround)
Code:
DETOUR_DECL_MEMBER2(ShouldHitEntity, bool, IHandleEntity *, pHandleEntity, int, contentsMask)
{
	IHandleEntity *m_pPassEnt = *(IHandleEntity **)((intptr_t)this + g_iPassEntOffs);
	int m_collisionGroup = *(int *)((intptr_t)this + g_iCollisionOffs);

	cell_t result = DETOUR_MEMBER_CALL(ShouldHitEntity)(pHandleEntity, contentsMask);

	if (!pHandleEntity || !m_pPassEnt || pHandleEntity == m_pPassEnt)
		return (result != 0);

	cell_t touchEnt = gamehelpers->EntityToBCompatRef((CBaseEntity *)pHandleEntity);
	cell_t passEnt = gamehelpers->EntityToBCompatRef((CBaseEntity *)m_pPassEnt);

	g_pOnShouldCollide->PushCell(touchEnt);
	g_pOnShouldCollide->PushCell(passEnt);
	g_pOnShouldCollide->PushCell(m_collisionGroup);
	g_pOnShouldCollide->PushCell(contentsMask);
	g_pOnShouldCollide->PushCellByRef(&result);
	g_pOnShouldCollide->Execute(NULL);

	return (result != 0);
}
Then in the plugin if you only wanted to work with player collisions, you could check if contentsMask == MASK_PLAYERSOLID.
__________________

Last edited by GoD-Tony; 10-08-2012 at 05:21.
GoD-Tony is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 10-08-2012 , 13:12   Re: CollisionHook
Reply With Quote #3

Quote:
Originally Posted by GoD-Tony View Post
Using this code for example:
PHP Code:
public Action:CH_PassFilterent1ent2, &bool:result )
{
    
// No client-client collisions
    
if (<= ent1 <= MaxClients && <= ent2 <= MaxClients)
    {
        
result false;
        return 
Plugin_Handled;
    }
    
    return 
Plugin_Continue;

This is all on CS:S, and the code above seems to crash when shooting a player.
Interesting, in TF2 that code works as expected. The original purpose of the extension was to support a plugin I'm working on that controls precise player-player collision.

I haven't tested CS:S so I'm not sure why that would crash, but I'll check it out and see if anything can be salvaged.

Quote:
Originally Posted by GoD-Tony View Post
Normally it would prevent trace weapons from hitting any player target, because the player firing is passed as pPass. So in order to differentiate player collision traces from the rest, I detoured CTraceFilterSimple::ShouldHitEntity instead which provided collisionGroup and contentsMask.

Mine ended up looking like this:
(unreleased because I thought it was an ugly workaround)
Code:
DETOUR_DECL_MEMBER2(ShouldHitEntity, bool, IHandleEntity *, pHandleEntity, int, contentsMask)
{
	IHandleEntity *m_pPassEnt = *(IHandleEntity **)((intptr_t)this + g_iPassEntOffs);
	int m_collisionGroup = *(int *)((intptr_t)this + g_iCollisionOffs);

	cell_t result = DETOUR_MEMBER_CALL(ShouldHitEntity)(pHandleEntity, contentsMask);

	if (!pHandleEntity || !m_pPassEnt || pHandleEntity == m_pPassEnt)
		return (result != 0);

	cell_t touchEnt = gamehelpers->EntityToBCompatRef((CBaseEntity *)pHandleEntity);
	cell_t passEnt = gamehelpers->EntityToBCompatRef((CBaseEntity *)m_pPassEnt);

	g_pOnShouldCollide->PushCell(touchEnt);
	g_pOnShouldCollide->PushCell(passEnt);
	g_pOnShouldCollide->PushCell(m_collisionGroup);
	g_pOnShouldCollide->PushCell(contentsMask);
	g_pOnShouldCollide->PushCellByRef(&result);
	g_pOnShouldCollide->Execute(NULL);

	return (result != 0);
}
Then in the plugin if you only wanted to work with player collisions, you could check if contentsMask == MASK_PLAYERSOLID.
That's a pretty good idea! I may rework the extension hook that function instead, as the extra info during collision checking would definitely be useful. Hooking that function also has the added benefit of handling any checks done in StandardFilterRules as well.

Also I'd make the assumption that most mods won't be touching CTraceFilterSimple, so the offsets to the members would likely be safe to get at.
__________________
VoiDeD is offline
GoD-Tony
Veteran Member
Join Date: Jul 2005
Old 10-10-2012 , 03:55   Re: CollisionHook
Reply With Quote #4

Quote:
Originally Posted by VoiDeD View Post
Also I'd make the assumption that most mods won't be touching CTraceFilterSimple, so the offsets to the members would likely be safe to get at.
Yea that's true. I can't remember the exact reason for doing that but it probably wasn't important.

I haven't had a chance to play around with the vphysics stuff yet but it looks pretty cool too!
__________________
GoD-Tony is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 11-20-2012 , 20:25   Re: CollisionHook
Reply With Quote #5

psychonic has been kind enough to update the extension for the linux changes that broke things a while back. You can get it here.
__________________

Last edited by VoiDeD; 11-21-2012 at 13:03. Reason: Fixed link
VoiDeD is offline
shavit
AlliedModders Donor
Join Date: Dec 2011
Location: Israel
Old 11-21-2012 , 10:20   Re: CollisionHook
Reply With Quote #6

Wanted to make a new plugin.
No success
PHP Code:
L 11/21/2012 17:18:23SourceMod error session started
L 11
/21/2012 17:18:23Info (map "bhop_arcane_v1") (file "errors_20121121.log")
L 11/21/2012 17:18:23: [CLHOOKCould not locate PassServerEntityFilter Disabling detour
L 11
/21/2012 17:18:23: [SMUnable to load extension "collisionhook.ext"Unable to hook PassServerEntityFilter!
L 11/21/2012 17:18:23: [SMUnable to load plugin "noblock.smx"Required extension "CollisionHook" file("collisionhook.ext"not running 
CS:S Windows 7 server.
SM 1.4.7 & MM:S 1.9.0.
__________________
retired
shavit is offline
VoiDeD
AlliedModders Donor
Join Date: Mar 2009
Location: Illinois, USA
Old 11-21-2012 , 13:08   Re: CollisionHook
Reply With Quote #7

Quote:
Originally Posted by shavit View Post
Wanted to make a new plugin.
No success
PHP Code:
L 11/21/2012 17:18:23SourceMod error session started
L 11
/21/2012 17:18:23Info (map "bhop_arcane_v1") (file "errors_20121121.log")
L 11/21/2012 17:18:23: [CLHOOKCould not locate PassServerEntityFilter Disabling detour
L 11
/21/2012 17:18:23: [SMUnable to load extension "collisionhook.ext"Unable to hook PassServerEntityFilter!
L 11/21/2012 17:18:23: [SMUnable to load plugin "noblock.smx"Required extension "CollisionHook" file("collisionhook.ext"not running 
CS:S Windows 7 server.
SM 1.4.7 & MM:S 1.9.0.
Whoops! I made a small error in the gamedata file. If you edit it and change "tf" to "#default", it'll work for CS:S.

That being said, I haven't yet investigated the CS:S crashes mentioned in the previous posts. As this extension was originally designed for TF2, your mileage may vary.
__________________
VoiDeD is offline
shavit
AlliedModders Donor
Join Date: Dec 2011
Location: Israel
Old 11-23-2012 , 06:00   Re: CollisionHook
Reply With Quote #8

Quote:
Originally Posted by VoiDeD View Post
Whoops! I made a small error in the gamedata file. If you edit it and change "tf" to "#default", it'll work for CS:S.

That being said, I haven't yet investigated the CS:S crashes mentioned in the previous posts. As this extension was originally designed for TF2, your mileage may vary.
PHP Code:
"Games"
{
    
"#default"
    
{
        
"Signatures"
        
{
            
"PassServerEntityFilter"
            
{
                
"library"    "server"
                
                "windows"    "\x55\x8b\xec\x57\x8b\x7d\x0c\x85\xff\x75\x2a\xb0\x01\x5f\x5d\xc3\x56\x8b\x75"
                "linux"        "@_Z22PassServerEntityFilterPK13IHandleEntityS1_"
            
}
        }
    }

Crashes my server.
I'll try to find the correct signature.
__________________
retired
shavit is offline
Trotim
Junior Member
Join Date: Mar 2011
Old 03-05-2013 , 09:54   Re: CollisionHook
Reply With Quote #9

Does this still work? Or is there a better way to do this by now?
Trotim is offline
Peace-Maker
SourceMod Plugin Approver
Join Date: Aug 2008
Location: Germany
Old 03-06-2013 , 18:26   Re: CollisionHook
Reply With Quote #10

It works perfectly fine! There is no other way to do what this does.
__________________
Peace-Maker 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 19:21.


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