New hooks (stocks, natives, improved publics)
#1

OK, question:

I’ve been thinking about extensions to y_hooks for a while now (I’ve mentioned this a few times already). Namely the ability to hook regular and native functions. In theory the code would look something like this:

Code:

hook native SetPlayerPos(playerid, Float:x, Float:y, Float:z)
{
    // What goes in here?
}
There are two options:
  1. Explicit chaining. So your hook would look like this:

    Code:
    
    hook native SetPlayerPos(playerid, Float:x, Float:y, Float:z)
    {
        printf("cool");
        return SetPlayerPos(playerid, x, y z); // NOT recursive, calls the next hook, or the native.
    }
    
    This has several advantages:
    • Control flow is obvious and explicit.
    • Preventing and manipulating when the next function is called is easy.
    • Return values are easy to deal with. This wasn’t an issue with publics, because they only return 0 or 1, but other function types can return anything.
    • The generated code is MUCH simpler.
    • Compile-time errors if the original function you are hooking (for hook stock) doesn’t exist. You can hook publics that don’t exist, but not natives and stocks.
  2. Implicit chaining.

    So within the hook you don’t call the original SetPlayerPos, all hooks and the original are called one after the other. I really don’t like this idea - it makes writing hook code almost impossible. HOWEVER, this is how hooked publics currently work, and I’m a big fan of consistency. On the other hand, since you can hook publics that don’t actually exist, requiring them to exist breaks the whole situation entirely.
I’m thinking about having both methods available for publics. The legacy code will continue to operate exactly as it did before:

Code:

hook OnPlayerConnect(playerid)
{
    printf("cool");
    return 1;
}
Or using the newer syntax will require explicit chaining, but would also require that the next callback exists already:

Code:

hook public OnPlayerConnect(playerid)
{
    printf("cool");
    return OnPlayerConnect(playerid);
}
Thoughts?
Reply
#2

Using implicit chaining, you would have to add syntax for both prehooks and posthooks, in case you needed to check the returned value of the actual function. You might also need to pass the arguments by reference, since a prehook could also want to change their value.
Reply
#3

This would make easier script anticheat include, debug include, player config include for example:
Code:
hook native PlayAudioStreamForPlayer(playerid, url[], Float:posX = 0.0, Float:posY = 0.0, Float:posZ = 0.0, Float:distance = 50.0, usepos = 0)
{
	if(pAudioEnabled[playerid]) return PlayAudioStreamForPlayer(playerid, url, posX, posY, posZ, distance, usepos);
	return 0;
}
Reply
#4

This would be very useful. Libraries such as anticheats and so on could benefit a lot from this. Besides, it allows for cleaner code when applying, like Gr00t said, custom configs and such. It would allow to write code like that and rely on the hooks you make.

Regarding the proposed new explicit syntax for public functions, it would allow a more obvious and probably even more powerful control flow. It would be great to see this implemented.
Reply
#5

Finally?
Reply
#6

Explicit chaining method seems very useful.
Reply
#7

Explicit chaining looks good, but in that case I would substitute the word hook with the word override, this eliminates the code readers' wrong assumption about recursion.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)