EntityHook test_function not working?

Please post any questions about developing your plugin here. Please use the search function before posting!
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

EntityHook test_function not working?

Postby Hymns For Disco » Wed Mar 21, 2018 1:02 am

I'm creating a custom class which extends Entity. When an object is made, it will create EntityPreHook decorators to bind entity events to class functions. I have created a test function which will only return true when the test entity is equal to my entity. Printing the tests, I can see that it is only returning true when I want it to. However, the function is still being called for EVERY start_touch event. If I make my test function always return false, the hooked function is never called. am I doing this wrong? I simply want to be able to hook the entity events to call the object's function.

Code: Select all

# from __init__
        EntityPreHook(
            self.is_me,
            'start_touch')(self.on_pre_start_touch)
           
 # test function
     def is_me(self, other):
        print(other.index, self.index == other.index)
        return self.index == other.index
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: EntityHook test_function not working?

Postby L'In20Cible » Wed Mar 21, 2018 3:57 am

This is not how it works. The test_function is only used to determine from which entity the method is retrieved and hooked from but filtering the calls is your responsibility. Just add a call to your test function into your callback and return the call if it fails.
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: EntityHook test_function not working?

Postby Hymns For Disco » Wed Mar 21, 2018 5:08 am

The reason I wanted to filter the entities like this is because when the hooked event is fired for an entity with a parent, the server freezes. This seems like a major issue with a fundamental part of many plugins. I saw your workaround for this in another thread, but Im hoping there's a simpler way to do such a thing. Either way I need to hook for touch and end_touch also
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: EntityHook test_function not working?

Postby L'In20Cible » Wed Mar 21, 2018 5:24 am

You will have to block the original call and reproduce what it does by calling the trampoline for their parents. I guess the workaround you are mentioning is the following: viewtopic.php?f=20&t=1447&p=9615#p9615
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: EntityHook test_function not working?

Postby Hymns For Disco » Wed Mar 21, 2018 8:40 pm

I've tried implementing this solution however I am now getting errors thrown when picking up weapons.

Code: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\timer\core\zone.py", line 163, in pre_to
uch
    parent.touch.call_trampoline(other)
  File "..\addons\source-python\packages\source-python\memory\helpers.py", line
335, in call_trampoline
    return super().call_trampoline(self._this, *args)
  File "<string>", line 1, in <lambda>

ValueError: Function was not hooked.


Im not too sure what this error means or why its being raised. If it's safe to just catch the exception and ignore it, I could do that.
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: EntityHook test_function not working?

Postby Hymns For Disco » Wed Mar 21, 2018 9:40 pm

The second problem im having is that I can't find the entity property names for the start_touch and end_touch functions (if they exist). For touch you use m_pfnTouch, but I can't seem to find any other properties like this for touch function. If these properties dont exist, is there any alternate method I can use to hook these touch events?

Edit: If these pointers do not exist for such functions, doesn't this make EntityHooks nearly unusable since you can't confirm that they won't randomly kill your server at any time? (various maps may or may not have parented entities of certain types)
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: EntityHook test_function not working?

Postby Hymns For Disco » Wed Mar 21, 2018 10:28 pm

Well I've realised finally that I can use EntityPostHook instead of EntityPreHook and it seems to avoid this whole server freezing situation, which is great since post hooks will work fine in my circumstances. However I, and I'm sure other people too, would like to know how to safely use EntityPreHook for functions other than touch
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: EntityHook test_function not working?

Postby L'In20Cible » Wed Mar 21, 2018 10:44 pm

Hymns For Disco wrote:I've tried implementing this solution however I am now getting errors thrown when picking up weapons.

Code: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\timer\core\zone.py", line 163, in pre_to
uch
    parent.touch.call_trampoline(other)
  File "..\addons\source-python\packages\source-python\memory\helpers.py", line
335, in call_trampoline
    return super().call_trampoline(self._this, *args)
  File "<string>", line 1, in <lambda>

ValueError: Function was not hooked.


Im not too sure what this error means or why its being raised. If it's safe to just catch the exception and ignore it, I could do that.

You get this error because the Function instance you try to call the trampoline is not hooked. Without your code it won't be possible to tell you where and why it happens but let's just say you are trying to do something that cannot be done. But if I had to guess, I would say that pOther has its own implementation of the Touch method into its dispatch table meaning that this is not the one that is hooked so you could just leave the call continue in such case. Either that or you are hooking start_touch and is calling the trampoline for touch, which is obviously not hooked.

Hymns For Disco wrote:The second problem im having is that I can't find the entity property names for the start_touch and end_touch functions (if they exist). For touch you use m_pfnTouch, but I can't seem to find any other properties like this for touch function. If these properties dont exist, is there any alternate method I can use to hook these touch events?

Edit: If these pointers do not exist for such functions, doesn't this make EntityHooks nearly unusable since you can't confirm that they won't randomly kill your server at any time? (various maps may or may not have parented entities of certain types)


You don't have to do that call for StartTouch, because the original CBaseEntity::StartTouch is not doing so unlike CBaseEntity::Touch. So basically, you only have to call the trampoline for the parent in your case.

Hymns For Disco wrote:Well I've realised finally that I can use EntityPostHook instead of EntityPreHook and it seems to avoid this whole server freezing situation, which is great since post hooks will work fine in my circumstances. However I, and I'm sure other people too, would like to know how to safely use EntityPreHook for functions other than touch

They only have to know that the hooks are not thread safe meaning that if you hook a function that call itself, you cannot let the original call go through and you have to mimic what it does by calling the trampoline so that the hook doesn't get re-called internally before the original call is done. For start_touch, you would use the same code I linked above without the following lines:

Syntax: Select all

 
ptr = entity.get_property_pointer('m_pfnTouch')
if ptr != NULL:
func = ptr.make_function(Convention.THISCALL,
(DataType.POINTER, DataType.POINTER), DataType.VOID)
func(entity, other)

Because StartTouch does nothing else than noticing the parent of the this pointer.
User avatar
Hymns For Disco
Member
Posts: 32
Joined: Wed Nov 22, 2017 7:18 am
Contact:

Re: EntityHook test_function not working?

Postby Hymns For Disco » Fri Mar 23, 2018 8:23 pm

Thank you for helping with this problem. I think I now have a better understanding of how these hooks work. So turns out I was just being dumb before thinking that pothooks were safe, same issue. I've implemented the fix like you said and it seems to work fine, however there are still crashes if the entity's parent has a parent and so on. So the trampoline call must be recursive to truly solve the issue. This seems like a lot of work to make a basic feature like ent hooks even safe to use at all. Are there any plans to apply similar fixes to the sourcepython api?

Edit: actually not sure if the parent tree is the problem. I got an identical crash as the weapon pickups from touching a door with multiple parents, but I'm not able to recreate it.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 37 guests