EntityPreHook/EntityPostHook changes

Discuss API design here.
User avatar
Ayuto
Project Leader
Posts: 1577
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

EntityPreHook/EntityPostHook changes

Postby Ayuto » Fri Aug 07, 2015 7:59 pm

We just updated the EntityPreHook and EntityPostHook decorators. Now, you need to pass a function to the decorator that will be used to test existing and new entities whether they match the entity you are looking for or not. If the function returns True, the hook will get initialized by using the pointer of the entity.

To make things easier for you, we have defined some functions for common entities (see the EntityCondition class).

Example 1:

Syntax: Select all

from entities.hooks import EntityPreHook
from entities.hooks import EntityCondition

# This hook will get initialized as soon as a player (bot or human) is found
# on the server
@EntityPreHook(EntityCondition.is_player, 'bump_weapon')
def pre_bump_weapon(args):
print(args)

Example 2:

Syntax: Select all

from entities.hooks import EntityPreHook
from entities.hooks import EntityCondition

# This hook will only get initialized when an entity was found on the server
# whose first datamap class name is "CCSPlayer" (this is actually the same
# like EntityCondition.is_human_player).
@EntityPreHook(
EntityCondition.equals_datamap_classname('CCSPlayer'), 'bump_weapon')
def pre_bump_weapon(args):
print(args)
This implementation allows you maximum flexibility. If you have any other methods that should be added to the EntityCondition class, feel free to post them here.
Mahi
Senior Member
Posts: 212
Joined: Wed Aug 29, 2012 8:39 pm
Location: Finland

Postby Mahi » Sat Aug 08, 2015 1:41 pm

How is this an improvement over @EntityPreHook('player', 'bump_weapon'), does it allow more hooks to be made or something similar? Just curious, since "This implementation allows you maximum flexibility." doesn't tell much to a person who's not too knowledgeable of the Source engine. :)
User avatar
satoon101
Project Leader
Posts: 2319
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Aug 08, 2015 1:48 pm

The original design had an issue:
http://forums.sourcepython.com/showthread.php?891-Using-EntityPreHook-on-drop_weapon&p=5549&viewfull=1#post5549

I can explain it better when I get home.

The second implementation had a different issue, which I will also explain later. This new version works for all situations.
Image
Mahi
Senior Member
Posts: 212
Joined: Wed Aug 29, 2012 8:39 pm
Location: Finland

Postby Mahi » Sat Aug 08, 2015 3:38 pm

Oh, that's probably what was causing some random (well, they seemed random at first, never had time to debug) crashes on my EasyPlayer! Since I usually tested the plugins while I was already on the server, I think it often crashed when I joined the server (thus the server adding bots before me).

Also, good to hear that you guys have fixed all the issues! Thank you once again for the awesome work you're doing :)
User avatar
satoon101
Project Leader
Posts: 2319
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Aug 08, 2015 3:43 pm

I don't think it would cause crashes, so that's likely a different issue you are experiencing. The issues with both the first 2 versions were that the hooks wouldn't be called in situations where you would expect them to. Again, I'll post more on that later, but that's the jist of the problems.
Image
User avatar
satoon101
Project Leader
Posts: 2319
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sun Aug 09, 2015 1:31 am

I found the issue with the first implementation while working with the virtual method hook for bump_weapon. My original test script used the following:

Syntax: Select all

@EntityPreHook(['cs_bot', 'player'], 'bump_weapon')

My original testing worked fine, but I didn't load my test script until I was on the server without any bots. Eventually, I started testing with bots on the server. When I did this, I loaded the test script while bots were on and I wasn't. My testing in this instance worked for bots, but not for human players (me). I came to find out that what was occurring was that CCSBot::BumpWeapon was being hooked instead of CCSPlayer::BumpWeapon. Through more testing (and help from Ayuto), I realized that if I used both cs_bot and player in separate pre-hooks, and I loaded the test script prior to adding any bots, it worked fine. However, if a bot was on the server prior to loading the script, their entity classname was already set to player instead of cs_bot, which caused both the cs_bot hook and player hook to hook the same function (CCSBot::BumpWeapon).


To combat this, we decided to use the DataMap class name of the entity instead of the entity's classname. This fixed the issue for BumpWeapon, as we can use CCSBot in a bot hook and CCSPlayer in a human hook, as those are the starting DataMaps for each, respectively.

Syntax: Select all

@EntityPreHook('CCSBot', 'bump_weapon')

...
@EntityPreHook('CCSPlayer', 'bump_weapon')


However, when working on my Anti Team-Flash plugin, I came to realize that (in CS:S) flashbang_projectile entities do not have CFlashbangProjectile as either a DataMap or a ServerClass. In fact, both flashbang_projectile and hegrenade_projectile both start at CBaseCSGrenadeProjectile for both DataMap and ServerClass. If I used the second implementation, I would have to use:

Syntax: Select all

@EntityPreHook('CBaseCSGrenadeProjectile', 'detonate')

But, if I did that, and an hegrenade is thrown before a flashbang, then CHEGrenadeProjectile::Detonate would be hooked instead of CFlashbangProjectile::Detonate. Both of those virtual functions exist, but neither classname is a part of the respective entity's DataMap/ServerClass. In order to fix this issue, and make sure the original issue stayed fixed, Ayuto came up with a brilliant solution that is the purpose of this topic. If you happen to run into a situation where any of the built-in EntityCondition methods does not suffice, you can easily provide your own function instead. I think the built-ins should work in almost all cases, though.

I hope that explains it well enough. If not, let us know how we can clarify.
Image

Return to “API Design”

Who is online

Users browsing this forum: No registered users and 1 guest