Includes richtig erstellen | Hooking ganz einfach

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Es gibt Neuigkeiten! Ab sofort könnt ihr dem Donators Club auf Lebenszeit beitreten.
    Weitere Infos im Thema Donator's Club ab heute wieder verfügbar!

    • Includes richtig erstellen | Hooking ganz einfach

      Hallo Community,

      aufgrund diverser Includes, die mich schon fast kotzen lassen,
      zeige ich euch mal, wie ihr jetzt richtig Includes schreibt.
      Dafür benötigen wir das sogenannte "hooking".

      Was ist Hooking?

      Hook ist englisch und bedeutet Haken (siehe z.B. Kapitän Hook).
      Im Endeffekt heißt es also nichts anderes als sich irgendwo einzuhaken bzw sich irgendwo dazwischen zu klemmen.

      Wozu wird Hooking benötigt?

      Hooking wird z.B. in Includes benötigt und zwar aus einem einfachen Grund.
      Includes sind theoretisch nichts weiter als Implementierung in die Scripte.

      Beispiel:

      Script:

      PAWN-Quellcode

      1. #include <BeispielInclude>
      2. forward Tutorial(playerid);
      3. forward SekundenTimer();
      4. main() { }
      5. public Tutorial(playerid)
      6. {
      7. return 1;
      8. }
      9. public SekundenTimer()
      10. {
      11. return 1;
      12. }
      Alles anzeigen




      Include:

      PAWN-Quellcode

      1. new Variable;
      2. new Float:FloatVariable;
      3. new Array[5];




      So würde der Code zusammengefasst aussehen

      PAWN-Quellcode

      1. new Variable;
      2. new Float:FloatVariable;
      3. new Array[5];
      4. forward Tutorial(playerid);
      5. forward SekundenTimer();
      6. main() { }
      7. public Tutorial(playerid)
      8. {
      9. return 1;
      10. }
      11. public SekundenTimer()
      12. {
      13. return 1;
      14. }
      Alles anzeigen



      Wie man nun sehr gut erkennen kann wurde #include <BeispielInclude>
      mit dem Inhalt der BeispielInclude ersetzt.

      Wozu ich euch das zeige?
      Einfach :D
      Wenn wir nun 2x eine Funktion im Script haben, spuckt der Compiler logischerweise einen Fehler aus,
      da er nicht genau weiß, was nun mit der 2. Funktion geschehen soll.


      Wie verhindert man dies?

      Theoretisch gar nicht.


      Oder doch?
      Prinzip ist einfach.
      Man hakt sich zwischen die Funktionen.
      Bitte bedenkt, das sich das zwar auf alle Funktionen ausweiten lässt,
      aber nicht immer Sinn macht.
      Ab wann was Sinn macht, lest ihr weiter unten.


      Hooking von Callbacks/Funktionen

      Dazu benutzen wir das ALS-Hooking verfahren.
      Das normale Hooking-Verfahren würde bei mehreren Hooks nur zu Problemen führen.
      Die ALS Methode ist bisher am verbreitesten.

      Es wird immer einen Include und Scriptteil und geben,
      das dient nur zu Übersicht ;)

      Wir nehmen mal als Beispiel das Callback OnPlayerConnect

      Script:

      PAWN-Quellcode

      1. #include <a_samp>
      2. #include <hooking>
      3. public OnPlayerConnect(playerid)
      4. {
      5. return true;
      6. }



      Hier ist das noch ziemlich Standardmäßig :D
      Aber nun zum eigentlichen.

      Wir wollen uns ja dazwischen klemmen, deshalb erstellen wir einen weitern
      Public, mit dem gleichen Namen.

      Aber, dann haben wir doch das gleiche Problem wie vorher...


      Ja, aber nur momentan, da kommt noch was dazu, also Geduld ;)


      Kommen wir zum eigentlichen.
      Wir müssen dem Compiler nun sagen, das es 2 verschiedene Funkionen/Callbacks sind.
      Das machen wir mit einem Macro/Define.

      PAWN-Quellcode

      1. #define OnPlayerConnect _OnPlayerConnect


      Vorsicht:
      Ihr dürft aber nicht den Fehler machen und es ganz nach oben setzen,
      sonst habt ihr eure Problem nicht umgangen.
      Es muss direkt unter den public, den ihr hooken wollt.

      Include:

      PAWN-Quellcode

      1. public OnPlayerConnect(playerid) // Die Parameter kommen natürlich immer auf die Funktion an ;)
      2. {
      3. return true;
      4. }
      5. #define OnPlayerConnect _OnPlayerConnect




      Aber moment.
      Nun bekommt ihr den Fehler, das _OnPlayerConnect noch nicht deklariert wurde,
      falls ihr versucht es zu compilen.

      Das liegt daran, das der Macro/Define erst dann anfängt zu wirken, wenn er erstellt wird.
      D.h. würde ich ihn nach oben setzen, würde er den neu erstellten public mit "umbennen".

      Um das nicht definiert Problem zu lösen erstellen wir einen forward mit dem Namen der hinter der Funktion steht, die gehookt werden soll.

      PAWN-Quellcode

      1. forward _OnPlayerConnect(playerid); // Die Parameter kommen natürlich immer auf die Funktion an ;)




      Aber HALT.

      Wenn wir 2 Includes haben die nach diesem Prinzip arbeiten, bekommen wir Fehler.
      Dafür ist das oben erwähnte ALS-Hooking erforderlich.
      Sofern die 2. Include dies auch verwendet.
      Wie gesagt es ist verbreitet, aber nicht jede Include benutzt dies auch ;)

      Dafür müssen wir Macro/Define etwas erweitern.

      Folgendes kommt dazu

      PAWN-Quellcode

      1. #if defined _OnPlayerConnect
      2. forward _OnPlayerConnect(playerid);
      3. #endif#
      4. if defined _ALS_OnPlayerConnect
      5. #undef OnPlayerConnect
      6. #else
      7. #define _ALS_OnPlayerConnect
      8. #endif
      9. //hier kommt der Macro hin (#define OnPlayerConnect _OnPlayerConnect)



      Kurze Erklärung.

      Als erstes wird geprüft, ob die Funktion die wir hooken wollen überhaupt verwendet wird,
      wenn ja wird, sie geforwardet um keine Fehler auszulösen.

      Danach wird geprüft, ob das ALS Hooking schoneinmal verwendet wurde,
      falls Ja, wird der Macro ab der Stelle ungültig gemacht.
      Falls Nein, wird ein Macro/Define gesetzt, zu Markierung für weitere Includes,
      damit keine Fehler auftreten.

      Direkt darunter, wird ein neuer(unser) Macro/Define erstellt.

      Fast Fertig.
      Bisher sollte es dann so aussehen.

      Include:

      PAWN-Quellcode

      1. public OnPlayerConnect(playerid) // Die Parameter kommen natürlich immer auf die Funktion an ;)
      2. {
      3. return 1;
      4. }
      5. #if defined _OnPlayerConnect
      6. forward _OnPlayerConnect(playerid); // Die Parameter kommen natürlich immer auf die Funktion an ;)
      7. #endif
      8. #if defined _ALS_OnPlayerConnect
      9. #undef OnPlayerConnect
      10. #else
      11. #define _ALS_OnPlayerConnect
      12. #endif
      13. #define OnPlayerConnect _OnPlayerConnect
      Alles anzeigen




      Momentmal, wenn ich es nun teste, wird OnPlayerConnect in meinem Gamemode bzw Script nicht aufgerufen.

      Ich sagte doch, wir sind erst fast fertig :P
      Wir haben uns nicht ganz dazwischen gehakt, sondern es eher abgefangen.
      Aber wir wollen dazwischen und nicht es abfangen.

      Das machen wir wie folgt.
      Wie wir es bereits weiter oben gemacht haben nutzen wir wieder die "#if defined" Überprüfung.
      Ist es vorhanden rufen wir das Callback auf, wenn nicht, geben wir einfach "true" zurück.
      Das verhindert, das wir unnötig Zeit verlieren und das der Aufruf nicht einfach ins Leere läuft.

      Am Ende sieht es dann für unser Beispiel wie folgt aus:

      PAWN-Quellcode

      1. public OnPlayerConnect(playerid)
      2. {
      3. #if defined _OnPlayerConnect
      4. return _OnPlayerConnect(playerid);
      5. #else return true;
      6. #endif
      7. }




      Diese Methode funktioniert zwar immer noch, ist aber recht ineffektiv

      Dafür hat SA:MP die Funktion CallLocalFunction.
      Diese Funktion lässt uns Funktionen direkt aus dem Script, in dem es verwendet wird, laden.


      Es gibt aber noch die Möglichkeit des direkten Funktionsaufrufs.
      Da gibt es nicht viel zu beachten,
      einfach die Funktion mit dem neuen Namen aufrufen,
      hier wäre das:

      PAWN-Quellcode

      1. _OnPlayerConnect(playerid);




      CallLocalFunktion, funktioniert wie SetTimerEx.
      Das brauch ich wohl nicht zu erklären ^^

      Nun sind wir fertig ;)
      "Bevor ich mir Informationen aus der "Bild" hole,
      werde ich anfangen, Wahlergebnisse danach vorauszusagen,
      neben welchen Busch unsere Katze gepinkelt hat."
      Margarete Stokowski

      Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von Akino Kiritani () aus folgendem Grund: Tutorial an den neuen BBCode angepasst - doofer Leerzeichenpraser ._.

    • Hooken von Funktionen

      Das Prinzip ist das gleiche wie vorher, nämlich ALS_Hooking,
      nur benutzen wir hier keine Forwards bzw Publics sondern müssen hier direkt in das Native System eingreifen.
      Desweitern werden wir hier stocks benutzen,
      publics sind hier nutzlos, da wir sie nicht per CallLocalFunction oder Timer aufrufen.

      Ok, greifen wir ein.
      Zu erst müssen wir eine eigene Native erstellen und dem die Funktion zuweisen.
      Hier werde ich SendClientMessage als Beispiel nehmen ;)

      C-Quellcode

      1. native __SendClientMessage(playerid,color,const string[]);

      Nun haben wir zwar unsere eigene Native,
      aber wenn wir den Server nun starten würden, käme "File or Function not found".
      Der Grund ist der, die Native ist nirgends registriert.
      Sprich der Server kennt diese nicht.

      das umgehen wir, einfach, da wir hier ja kein Plugin schreiben, mit einer einfachen zuweisung.
      Auch hier gilt, das wir uns dazwischen hängen wollen.

      C-Quellcode

      1. native __SendClientMessage(playerid,color,const string[]) = SendClientMessage; // Wir weisen hier unsere Native zu, das sie wie SendClientMessage funktionern soll. Das ist Später wichtig.


      Nun erstellen wir unseren Stock.

      Achtung: Er darf nicht wie die Native lauten.

      C-Quellcode

      1. stock _SendClientMessage(playerid,color,const string[])
      2. {
      3. return 1;
      4. }


      Das ist nun unsere "neue" SendClientMessage Funktion.
      Diese hooken wir genauso, wie die Callbacks, siehe oben.



      Aber moment, was machen wir nun, wenn wir die alte SendClientMessage verwenden wollen?
      Gute Frage - dafür haben wir ja unsere native.

      Die Include dürfte nun so aussehen:

      C-Quellcode

      1. native __SendClientMessage(playerid,color,const string[]) = SendClientMessage;
      2. stock _SendClientMessage(playerid,color,const string[])
      3. {
      4. //weiteres
      5. __SendClientMessage(playerid,color,string);
      6. return 1;
      7. }
      8. #if defined _ALS_SendClientMessage
      9. #undef SendClientMessage
      10. #else
      11. #define _ALS_SendClientMessage
      12. #endif
      13. #define SendClientMessage _SendClientMessage
      Alles anzeigen


      So könnt, ihr auch euren Funktionen neue Parameter zuweisen ;)

      Ich hoffe ihr habt verstanden was ihr gelesen habt,
      falls Fragen oder Ergänzungen sind, dafür bin ich immer offen :)
      "Bevor ich mir Informationen aus der "Bild" hole,
      werde ich anfangen, Wahlergebnisse danach vorauszusagen,
      neben welchen Busch unsere Katze gepinkelt hat."
      Margarete Stokowski

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Akino Kiritani () aus folgendem Grund: BBCode Anpassung

    • PAWN-Quellcode

      1. #if defined _ALS_OnPlayerConnect
      2. #undef OnPlayerConnect
      3. #else
      4. #define _ALS_OnPlayerConnect
      5. #endif
      6. #define OnPlayerConnect _OnPlayerConnect


      Irgendwie peil ich das gerade nicht
      Ich hab das ja auch und OnPlayerConnect reagiert nicht
      Wie meinst du das mit den CallLocalFunktion?
      All in all it's just another brick in the wall
      • Du prüfst, ob der Prüf-Hook schon gesetzt wurde
      • Wenn ja -> entfernen des eigentlichen Hooks
      • Wenn nein -> setzen des Prüf-Hooks
      • Setzen des eigentlichen Hooks
      Wenn der Prüf-Hook ( _ALS_OnPlayerConnect ) gesetzt ist, ist auch der eigentliche Hook ( _OnPlayerConnect ) gesetzt ;)
      Webdesign (bevorzugt backend) • Android-Development • node.js • Pawn • Linux
      Reverse Engineering • Social Engineering • Cryptoanalyse • PGP-Key
      ReferenzenMein Facebook-Acc
    • Tion schrieb:

      Setzen des eigentlichen Hooks

      Da muss ich dich kurz verbessern.

      Setzen des neuen Hooks.

      Ich hab mir mal sein Problem angesehen,
      es liegt bzw lag am fehlenden Aufruf der gehookten Funktion
      "Bevor ich mir Informationen aus der "Bild" hole,
      werde ich anfangen, Wahlergebnisse danach vorauszusagen,
      neben welchen Busch unsere Katze gepinkelt hat."
      Margarete Stokowski
    • Sehr gut erklärt aber ich denke das ein Anfänger sowas kaum verstehen wird...

      + Die Preise liegen bei 5-100+€ Ablauf:
      + Entweder ihr addet mich in Skype (PN vorher Schreiben) oder Ihr schreibt eine PN an mich (Betreff - Euer Wunsch z.B. Filterscript)
      + So nun schreibt ihr mir was ihr alles in dem Script haben wollt ich werd euch dann sagen ob ich es hinbekomme.
      + Dann machen wir ein groben Preis aus. Ich werde das Script erstellen und es zusammen mit dem Kunden Testen.



      edmix23

      + Bitte beim Adden angeben wer ihr seit oder per PN bescheid sagen!


      +Paypal!
      +Direkte Banküberweisung


    • Arendium schrieb:

      und meine wiki bewerbung ist immernoch nicht bearbeitet kam die vielleicht ausversehen in mülleimer oda so ?

      Nein, ich vergess das immer nur, da scheinbar die Leute der Meinung sind mir aus meinen 30 ungelesenen 35 - 38 zumachen,
      deshalb hab ich auch den Satz in der Signatur ;)

      @Rocky
      Das hat nur den Sinn das Includes endlich auch mal Includes sind und nicht zu Codeschnipseln werden.
      Beispiel -> B_Stream
      Erst war es ja nötig
      Beavis_OnPlayerConnect(playerid);
      mit einzubinden.

      Nachdem ich ihm das erklärt hab und dem Tutorial muss man das ja nicht mehr ;)

      @TheO
      Ich glaub auch nicht das ein Anfänger, auf die Idee kommt eine Komplexe Include zu schreiben ;)
      "Bevor ich mir Informationen aus der "Bild" hole,
      werde ich anfangen, Wahlergebnisse danach vorauszusagen,
      neben welchen Busch unsere Katze gepinkelt hat."
      Margarete Stokowski
    • das ergibt in der .amx compiliert folgendes


      Müsstest du ausbessern, denn wie die AMX Datei compiliert aussieht würde man kaum verstehen. Die Scriptsprache ist nur eine vereinfachung der eigentlichen Maschinensprache.
      Ich denke, dass
      so würde der Code zusammengefasst aussehen

      deine Erklärung besser bezeichnet.

      Ansonsten feines Tutorial, haste fein gemacht :love:
    • BlackAce schrieb:


      Ich glaub auch nicht das ein Anfänger, auf die Idee kommt eine Komplexe Include zu schreiben ;)



      Stimmt hast eigentlich recht ;D

      + Die Preise liegen bei 5-100+€ Ablauf:
      + Entweder ihr addet mich in Skype (PN vorher Schreiben) oder Ihr schreibt eine PN an mich (Betreff - Euer Wunsch z.B. Filterscript)
      + So nun schreibt ihr mir was ihr alles in dem Script haben wollt ich werd euch dann sagen ob ich es hinbekomme.
      + Dann machen wir ein groben Preis aus. Ich werde das Script erstellen und es zusammen mit dem Kunden Testen.



      edmix23

      + Bitte beim Adden angeben wer ihr seit oder per PN bescheid sagen!


      +Paypal!
      +Direkte Banküberweisung

    • 10/10 Ein Super Tutorial

      Mir hatte es auch damals geholfen, als mich BlackAce auf das Hooking von meiner Gangschaltungs-Include angesprochen hat.
      Es hier nochmal als Tutorial zu sehen, ist sehr gut, falls man mal etwas vergisst oder so ^^
    • 98% der User verstehen nicht mal was "Hooking" ist. Mal abgesehen, davon, dass das Tutorial total unübersichtlich ist und eine genaue Definition was "Hooking" eigentlich ist nicht vorhanden ist, ganz in ordnung. Wobei ich mich immer Frage, ob das alles für einen SA:MP Server so sinnvoll ist. Ich denke hier gehen die Meinungen sehr stark auseinander ;)
      Chief Technology Officer (CTO)

      fivemp.de
      Du willst mitmachen? - Einfach eine PN schicken!
    • Ich gebe zu, das es etwas unübersicgtlich ist, das liegt aber an der Formatierung :D

      Was Hooking ist steht doch relativ weit oben ;)

      Hooking ist ungefähr vergleichbar mit einem Filterscript ;)
      Daher viele hooks mach schon was aus, da das eigentliche Callback viel später aufgerufen wird.
      "Bevor ich mir Informationen aus der "Bild" hole,
      werde ich anfangen, Wahlergebnisse danach vorauszusagen,
      neben welchen Busch unsere Katze gepinkelt hat."
      Margarete Stokowski