AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Extensions (https://forums.alliedmods.net/forumdisplay.php?f=134)
-   -   CollisionHook (https://forums.alliedmods.net/showthread.php?t=197815)

VoiDeD 10-07-2012 20:18

CollisionHook
 
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.

GoD-Tony 10-08-2012 05:04

Re: CollisionHook
 
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.

VoiDeD 10-08-2012 13:12

Re: CollisionHook
 
Quote:

Originally Posted by GoD-Tony (Post 1814680)
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 (Post 1814680)
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.

GoD-Tony 10-10-2012 03:55

Re: CollisionHook
 
Quote:

Originally Posted by VoiDeD (Post 1814901)
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!

VoiDeD 11-20-2012 20:25

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

shavit 11-21-2012 10:20

Re: CollisionHook
 
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.

VoiDeD 11-21-2012 13:08

Re: CollisionHook
 
Quote:

Originally Posted by shavit (Post 1841340)
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.

shavit 11-23-2012 06:00

Re: CollisionHook
 
Quote:

Originally Posted by VoiDeD (Post 1841419)
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.

Trotim 03-05-2013 09:54

Re: CollisionHook
 
Does this still work? Or is there a better way to do this by now?

Peace-Maker 03-06-2013 18:26

Re: CollisionHook
 
It works perfectly fine! There is no other way to do what this does.


All times are GMT -4. The time now is 09:59.

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