[Include] w!hook - (beta)
#1

Boas, para quem nгo viu ainda, eu havia criado um tуpico de uma include que fazia hook em callbacks nativas(apenas),
que na maioria dos casos й oque mais acontece, o povo sempre faz hook em nativas...
[Include] HOOK(testes)

Me perguntaram se tinha possibilidade de hookear funзхes que nгo fossem nativas,
e isso fugia da utilidade da minha include, que era simples.

Por isso eu criei esse simples cуdigo para dar inicio a uma forma diferente de se fazer hook, e bem diferente...

Nгo estarei fazendo a introduзгo ao cуdigo, para quem quiser saber mais pode tirar dъvidas comigo.

Код:
hook_f		-	Faz o hook de uma funзгo/nativa
hook_s		-	Faz o hook de uma stock
function	-	Faz a segunda chamada de uma funзгo/nativa hookeada
stock		-	Faz a segunda chamada de uma stock hookeada
call		-	Chama a funзгo do gamemode, apуs ter executado a include
Exemplos de uso,
exemplos com nativas/funзхes
caso 1:
pawn Код:
//hook:: й oque vocк vai usar na sua include.
hook_f::OnGameModeInit()
{
    print("hooked function");

    call->OnGameModeInit();
   
    return nop;
}

//Aqui vocк irб usar no seu gamemode.
function::OnGameModeInit()
{
    print("native function");
    return 1;
}
Eu nгo estarei trabalhando com 3 callbacks diferentes, serгo apenas duas, sendo ambas nativas o processamento delas ficarб separado pelo 'call', que chamarб a callback do GM.

caso 2:
pawn Код:
//Include
hook_f::OnGameModeInit()
{
    print("hooked function");

    call->OnGameModeInit();
   
    return nop;
}

//GM
function::OnGameModeInit()
{
    print("native function");
    return 1;
}
public OnGameModeInit()
{
    // Don't use these lines if it's a filterscript
    SetGameModeText("Blank Script");
    AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
   
    print("[DEBUG / GM] Callback: OnGameModeInit called");
   
    return 1;
}
Nesse exemplo serб chamado apenas a callback da include primeiramente e a callback do GM "function::", a callback declarada normalmente serб descartada do script em questхes de funcionamento, mas caso vocк exclua ou comente as funзхes de hook, a callback normal volta a funcionar, em todos os casos isto nгo gera erros.

caso 3:
pawn Код:
//include
hook_f::Teste()
{
    print("hooked");

    call->Teste();
}

//GM
forward Teste();

function::Teste()
{
    print("none");
}
Aqui vocк irб usar 'hook_f' para indicar que vocк irб hookear uma funзгo, como a funзгo nгo й nativa, vocк precisa do 'forward', isso vocкs jб sabem..

Exemplos com stocks
caso 4:
pawn Код:
//Include
hook_s::Teste()
{
    print("hooked");

    call->Teste();
}

//GM
stock::Teste()
{
    print("none");
}

//[GM] Uso:
main()
{
    Teste();
}
Aqui vocк irб usar 'hook_s' para indicar que vocк hookear uma stock.

Exemplos de casos errados,
caso 1:
pawn Код:
//Include
hook_f::OnGameModeInit()
{
    print("hooked function");

    call->OnGameModeInit();
   
    return nop;
}

//GM
public OnGameModeInit()
{
    // Don't use these lines if it's a filterscript
    SetGameModeText("Blank Script");
    AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
   
    print("[DEBUG / GM] Callback: OnGameModeInit called");
   
    return 1;
}
Isto irб gerar erros, pois vocк nгo estб utilizando a callback 'function::' que serve para chamar a funзгo nativa que funcionarб em "paralelo" com a funзгo da include.

caso 2:
pawn Код:
//Include
hook_f::OnGameModeInit()
{
    print("hooked function");
   
    return nop;
}

//GM
function::OnGameModeInit()
{
    print("native function");
    return 1;
}
Isto nгo irб funcionar, pois vocк nгo estб utilizando o 'call' para fazer a chamada para a funзгo do "function::".
OBS: isto й algo que pode ser melhorado futuramente, deixando de lado o 'call'.

o caso de uso correto teria de usar o
pawn Код:
call->OnGameModeInit();
caso 3:
pawn Код:
//Include
hook_f::OnGameModeInit()
{
    print("hooked function");
   
    return nop;
}

//GM
function::OnGameModeInit()
{
    print("native function");

    call->OnGameModeInit();

    return 1;
}
Isto poderб gerar stack overflows apуs um loop infinito de chamadas, pois o 'call' sу chama a funзгo do gm 'function::', se vocк utilizar o call dentro dela para chamar a ela mesmo, isto se tornarб um loop atй que a sua memуria bufunfe, o correto й utilizar o call somente na chamada 'hook_f::'

Exemplo de script.inc:
pawn Код:
hook_f::OnGameModeInit()
{
    //Cуdigos para o hook da include.
    print("Estб funзгo estб hookeada");

    //Chamada para funзгo/nativa do GameMode
    call->OnGameModeInit();
    return 1;
}

hook_f::OnPlayerCommandText(playerid, cmdtext[])
{
    if (strcmp(cmdtext, "/teste") == 0)
    {
        SendClientMessage(playerid, -1, "Vocк usou um comando :D");
        print("comando da funзгo hookeada utilizado.");
    }
    call->OnPlayerCommandText(playerid, cmdtext);
    return nop; //NOP, seria o valor que indicaria 'No Operation', pois o ъnico valor de retorno que importa, й o da funзгo do gamemode..
}
Exemplo de script.pwn:
pawn Код:
#include <a_samp>
#include <whook>

main(){}

function::OnGameModeInit()
{

    print("Inicializando servidor.");
   
    //Inicializaзхes, addPlayerClass, addStaticVehicle....

    return 1;
}

function::OnPlayerCommandText(playerid, cmdtext[])
{
    print(cmdtext);
    return 0;
}
Download whooks.inc

Atй entгo й isso, o cуdigo da include estб simples, mas estб bem diferenciado,
eu criei este tуpico separado para ele pois й do meu interesse ir atualizando
e se possнvel aumentar o caso de uso dele, assim aumentando tambйm a funcionalidade.

Faзam seus testes, e podem comentar se o interesse for:
tirar dъvidas,
reportar possнveis bugs,
ideias adicionais,
postar exemplos de cуdigos utilizando a include,
pedir autуgrafos,
elogiar.
Reply
#2

boa!!
Reply
#3

Boa!

muito bom agr so nao faz isto quem nao quer

+rep

@ edit

so vi agr o treco dos autуgrafos

QUERO UM!
Reply
#4

Wiliam, aqui um jeito de nгo precisar de STOCK::

pawn Код:
#define hookfunc%1(%2) \
                        %1(%2)

#define call%1(%2) \
            %1_hooked(%2)

hookfunc func() {
    print("teste a");
   
    call func();
}

#define stock%1(%2) \
            %1_hooked(%2)

stock func() {
    print("teste b");
}

quando ele usa

stock func() mal ele sabe que estб fazendo stock func_hooked(). Logo, estarб hookeando sem mudar todas stocks atuais do GM

Simples



pawn Код:
main() {

   func();
}
vai chamar

func() que vai chamar a func_hooked()

e resultar em:

PHP код:
[17:46:50teste a
[17:46:50teste b 
Reply
#5

Й um truque, basicamente vocк pode redefinir statments do pawn. Mas isto pode dar problemas, caso tiver outras stocks e vocк nгo hookea-las antes elas nгo pode ser chamadas a nгo ser pelo
Quote:

call func(params)

Reply
#6

Nice. +rep.
Reply
#7

Descobri outro mйtodo, mas este mйtodo tкm problemas porque nгo funciona com um tipo de parвmetro e precisam ser publicas:

pawn Код:
#define fp%0(%1) %0(%1); public %0(%1)

#define hookfunc%1(%2) \
                        fp %1__(%2)

hookfunc func(bru) {
    printf("teste %d [A]", bru);
    return true;

}



#define stock%1(%2) \
        fp %1(%2) return CallLocalFunction(#%1#__, "i", %2), CallLocalFunction(#%1#_hooked, "i", %2); fp %1_hooked(%2)



stock func(bru)
{
    printf("teste %d [B]", bru);
    return true;
}

stock bruno(t) {
    return true;
}

pawn Код:
main(){

    bruno(10);
    func(10);

}

Код:
[18:13:05] teste 10 [A]
[18:13:05] teste 10 [B]
Dб para arrumar este problema? Sim, dб!

Bastaria trocar CallLocalFunction para outra stock feita em #emit, voltada para chamar especialmente funзхes/stocks. Dessa maneira, as stocks serгo stocks e poderгo ser chamadas normalmente.

Com relaзгo aos parвmetros, basta fazer vбrias definiзхes recursivas para encontrar qual tipo de parвmetro estб sendo passado.

****** fez um cуdigo assim, vejam:

pawn Код:
// We don't ACTUALLY want parameters to have this string, it is just used to
// detect strings not arrays.  Remove it in all other cases.
#define string:

#define TYPES:%0) _:TYPE_N:TYPE_M:##%0,,)
#define TYPE_N:TYPE_M:##,,) "")

// Now we have to detect more types.
#define TYPE_M:##%2,%3) TYPE_0:TYPE_1:TYPE_E:##|||%2|||%3)

// What type of array is this?
#define TYPE_0:TYPE_1:TYPE_E:#%0#%1|||%2[]|||%3,%4) TYPE_0a:TYPE_0b:#%0#%1|||%2|||%3,%4)

// String.
#define TYPE_0a:TYPE_0b:#%0#%1|||string:%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0s#%1,%2|||%3|||%4)

// Other.  Note parameter "%5" to ENSURE that there is AT LEAST one more
// parameter after the array to contain the length.  Will give an error if it is
// not a variable because we do not strip the "[]"s.  We add TWO parameters here
// instead of 1 everywhere else.
#define TYPE_0b:#%0#%1|||%2|||%3,%4,%5) TYPE_0:TYPE_1:TYPE_E:#%0ai#%1,%2,%3|||%4|||%5)

// What type of variable is this:
#define TYPE_1:TYPE_E:#%0#%1|||%2|||%3,%4) TYPE_1a:TYPE_1b:#%0#%1|||%2|||%3,%4)

// Tagged (has ":"), we can still use "i" - trust me.
#define TYPE_1a:TYPE_1b:#%0#%1|||%6:%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0i#%1,_:%2|||%3|||%4)

// Normal.
#define TYPE_1b:#%0#%1|||%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0i#%1,%2|||%3|||%4)

// End.
#define TYPE_E:#%0#%1||||||%3) #%0#%1)
Reply
#8

Primeira include do fуrum que vou usar

"You have given out too much Reputation in the last 24 hours, try again later."


Sйrio que isso funciona sу com 18 linhas, sendo 7 de comentбrio? o.O
Reply
#9

Finalmente, o cуdigo ficaria assim:

pawn Код:
#define string:
#define TYPES:%0) _:TYPE_N:TYPE_M:##%0,,)
#define TYPE_N:TYPE_M:##,,) "")
#define TYPE_M:##%2,%3) TYPE_0:TYPE_1:TYPE_E:##|||%2|||%3)
#define TYPE_0:TYPE_1:TYPE_E:#%0#%1|||%2[]|||%3,%4) TYPE_0a:TYPE_0b:#%0#%1|||%2|||%3,%4)
#define TYPE_0a:TYPE_0b:#%0#%1|||string:%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0s#%1,%2|||%3|||%4)
#define TYPE_0b:#%0#%1|||%2|||%3,%4,%5) TYPE_0:TYPE_1:TYPE_E:#%0ai#%1,%2,%3|||%4|||%5)
#define TYPE_1:TYPE_E:#%0#%1|||%2|||%3,%4) TYPE_1a:TYPE_1b:#%0#%1|||%2|||%3,%4)
#define TYPE_1a:TYPE_1b:#%0#%1|||%6:%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0i#%1,_:%2|||%3|||%4)
#define TYPE_1b:#%0#%1|||%2|||%3,%4) TYPE_0:TYPE_1:TYPE_E:#%0i#%1,%2|||%3|||%4)
#define TYPE_E:#%0#%1||||||%3) #%0#%1)

#define fp%0(%1) %0(%1); public %0(%1)
#define hookfunc%1(%2)  fp %1__(%2)

hookfunc func1(bru) {
    printf("teste [A] %d [A]", bru);
    return true;
}


hookfunc func2(str[]) {
    printf("teste [B] %s [A]", str);
    return true;
}


#define stock%1(%2) \
            fp %1(%2) return CallLocalFunction(#%1#__, TYPES:%2), CallLocalFunction(#%1#_hooked, TYPES:%2); fp %1_hooked(%2)



stock func1(bru)
{
    printf("teste [A] %d [B]", bru);
    return true;
}

stock func2(string:str[]) // para strings necessita string:
{
    printf("teste [B] %s [B]", str);
    return true;
}


stock bruno() {
    return true;
}

Problemas

O usuбrio precisaria colocar string:

Nгo poderiam usar ... nas callbacks abaixo (elipse)
Reply
#10

Include Otima Irei usar ela
Reply
#11

Excelente trabalho Willian, parabйns !
Reply
#12

Nice

Muitos projetos com hook

+2
Reply
#13

Quote:
Originally Posted by iSmirnoff
View Post
Nice

Muitos projetos com hook

+2
Queria melhorar as possibilidades de hook, esse aqui й o tуpico certo para isso, jб comeзou pelo fato de ter diminuнdo em questгo de linha de cуdigo e ter aumentado em funcionalidade, atй porque utilizei conceitos diferentes.
Agora vou trabalhar pra aumentar a simplicidade, ai vai ficar bem boa de se usar.
Reply
#14

Quote:
Originally Posted by Willian_Luigi
View Post
Queria melhorar as possibilidades de hook, esse aqui й o tуpico certo para isso, jб comeзou pelo fato de ter diminuнdo em questгo de linha de cуdigo e ter aumentado em funcionalidade, atй porque utilizei conceitos diferentes.
Agora vou trabalhar pra aumentar a simplicidade, ai vai ficar bem boa de se usar.
Mais simples que 7 linhas? .-.

______________________________


Eu acho que jб estб уtima para se usar, mas se conseguir deixar melhor...
Reply
#15

Quote:
Originally Posted by Juniiro3
View Post
Mais simples que 7 linhas? .-.

______________________________


Eu acho que jб estб уtima para se usar, mas se conseguir deixar melhor...
A questгo nгo sгo o tanto de linhas que eu usei, mas й a forma que o usuбrio vai ter de usar, este й o x da questгo em simplicidade que eu quero alcanзar, por isso que o Bruno estб ajudando com ideias.

ao invйs de ter de mudar a sintaxe padrгo para os exemplos que eu citei, imagine se vocк pudesse simplesmente usar:
pawn Code:
//Include:
hook_f::t()
{
    call->t();
    return nop;
}
E ai no GM vocк utilizaria como se fosse algo comum.
pawn Code:
forward t();
public t()
{
    //Code
    return 1;
}
Seria bem mais simples, nгo ? pois a sintaxe seria a padrгo, a ъnica coisa modifica seria a entrada ao hook, mas a saнda continuaria como se vocк fosse criar uma funзгo normal.

A propуsito, parabйns pelo High rola.
Reply
#16

Quote:
Originally Posted by Willian_Luigi
View Post
A questгo nгo sгo o tanto de linhas que eu usei, mas й a forma que o usuбrio vai ter de usar, este й o x da questгo em simplicidade que eu quero alcanзar, por isso que o Bruno estб ajudando com ideias.

ao invйs de ter de mudar a sintaxe padrгo para os exemplos que eu citei, imagine se vocк pudesse simplesmente usar:
pawn Code:
//Include:
hook_f::t()
{
    call->t();
    return nop;
}
E ai no GM vocк utilizaria como se fosse algo comum.
pawn Code:
forward t();
public t()
{
    //Code
    return 1;
}
Seria bem mais simples, nгo ? pois a sintaxe seria a padrгo, a ъnica coisa modifica seria a entrada ao hook, mas a saнda continuaria como se vocк fosse criar uma funзгo normal.

A propуsito, parabйns pelo High rola.
Entendi o que vocк quis dizer, e de fato quanto mais fбcil e prуximo da sintaxe habitual mais fбcil para o usuбrio, basta ver os processadores de comandos mais comuns:

pawn Code:
COMMAND:comando(playerid, params[]) //zmcd
YCMD:comando(playerid, params[], help) //ycmd (acho que a sintaxe й assim)
CMD:comando(playerid, params[]) //jcmd
Bem, se vocк conseguir уtimo, a sintaxe irб ficar hiper simples e fбcil de usar, mas se nгo conseguir уtimo tambйm, a sintaxe nгo estб difнcil.

@OFF

Esse Willian me ama cara *-*
Valeu ai por lembrar da minha high rola hshauhsauhs nem eu tinha reparado -qqq
Reply
#17

william para beta tester
Reply
#18

Quote:
Originally Posted by AlieN_.
View Post
william para beta tester
AlieN_. para um curso de Portuguкs

Quote:
Originally Posted by Willian_Luigi
View Post
Esse jcmd que vocк citou й o meu ?
Tem outro? rs

Desde aquele post no Code.Me que eu tenho usado Jcmd

Vou fazer uns testes aqui, ver se consigo mudar a sintaxe disso, abraзos.
Reply
#19

Quote:
Originally Posted by Juniiro3
View Post
AlieN_. para um curso de Portuguкs
Fexado.mais ele tem ke ter o beta tester dele...o kara й bom dimais pow
Reply
#20

Vocк nгo respondeu sobre a possibilidade de implementar o cуdigo para parsear as tags e definir a funзгo sem precisar substituir por STOCK::

Veja lб o cуdigo. O que acha?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)