Beiträge von Logan

    Danke für die Information,
    brauche ich aber nicht.
    Habe damals schon das ganze GTA IV Pack also normal GTA IV + Episodes from Liberty City für 8 Euro auf Steam bekommen.


    MFG

    MySQL Tutorial - Cachefunktionen & Threaded Querys


    Hallo Leute,

    und herzlich willkommen zu diesem Tutorial

    Wie man sicher schon an der Überschrift geht es heute um die R7 des MySQL PLugins.

    Wichtig: Dieses Tutorial bezieht sich auf die R7 Version des MySQL Plugins von BlueG.

    (Logisch dass von Strickenkid und ältere Versionen des Plugins werden hier mit dem vorkommenden Code nicht klappen)

    Entweder ihr downloadet es hier oder ihr braucht es gar nicht zu downloaden, da seit dem "Server Pack" der Version 0.3e ist sie standardmäßig bei

    den Includes dabei, wenn ihr euch den SAMP Server von sa-mp.com herunterladet.

    Die Include war beim 0.3e Server Packet dabei, ist aber inzwischen nicht mehr standardmäßig mit drinnen.

    Hier die Google Project Seite für das MySQL Plugin von BlueG: Klick mich!

    Wichtig: Hier wird nur erklärt, was sich bei der R7 Version geändert hat und wie man jetzt Daten ausließt, wie man eine MySQL Verbindung herstellt, wird

    in Maddin's Tutorial ausführlich erklärt.

    Aber nun fangen wir doch einfach mal an.


    Inhaltsverzeichnis:


    1. Wichtigsten Änderungen der R7 Version im Überblick

    2. Was sind Threaded Querys überhaupt und was sind die Vorteile ?

    3. Vorteile der Cachefunktionen

    4. Erklärung aller wichtigen neuen Funktionen

    5. Schlusswort


    1. Änderungen der R7'er Version im Überblick


    Mit dem Update auf R7 des MySQL Plugins von BlueG konnten sich noch nicht alle anfreunden.

    Grund dafür war, dass es viele Funktionen mittlerweile nicht mehr gibt bzw. Sie einen anderen Namen bekommen haben oder ihre

    Syntax sich verändert hat, die im ersten Moment für Verwirrung sorgt. Dazu kommt, dass mittlerweile nur noch threaded Querys unterstützt werden, was das zu bedeuten hat, wird in Kapitel 2 näher erläutert.

    Desweiteren wurden Cache Funktionen hinzugefügt, die das Auslesen von Daten aus einer Tabelle einfacher machen sollten.

    Dabei braucht man nicht mehr mit mysql_free_result oder mysql_store_result anzuwenden um das Ergebnis zu speichern oder nach der Beendigung des Querys das Ergebnis bzw. den Speicher wiederfreizugeben.


    2.Was sind threaded Querys überhaupt und was sind die Vorteile ?


    Kommen wir zu Beantwortung der Frage, was threaded Querys überhaupt sind.

    Ich glaube zu diesem Thema gab es auch schon mal ein Tutorial, das sich jedoch auf das MySQL Plugin von Strickenkid bezog ( Das findet ihr hier ) (bei BlueG's sieht das nur ein bisschen anders aus). Wenn man mit MySQL Sachen auslesen will, bzw. einen Query ausführt, benötigt es eine gewisse Verarbeitungszeit, um diesen fertigzustellen. Wenn man jetzt z.B 3000 Autos auslesen will, bzw. man generell eine große Rate an Anfragen hat, wartet PAWN auf die Fertigstellung des Querys, da eben nicht 2 Dinge auf einmal gemacht werden können, was wiederum im schlimmsten Falle zu Laggs führen könnte.

    Das kann eben passieren, wenn man beim Ausgeben eines Querys einfach im Code weiterschreibt und nicht einen 2.Thread eröffnet, wo der Code nach dem Query weitergeht. Wenn man jetzt aber einen 2.Thread eröffnet ( bzw. Callback), in dem der Code weiter geht nach dem Beendet des Querys, können in der Zwischenzeit noch andere Dinge von PAWN erledigt werden. So werden Laggs und im schlimmsten Fall sogar ein Serverabsturz vermieden.

    Wie gesagt, hier nochmal der Verweiß auf das Tutorial OnQueryFinish, wo das nochmals ausführlich erklärt wird: Klick mich!


    3. Vorteile der Cachefunktionen


    Einzig und allein reichen threaded Querys aber dazu nicht aus, um die Geschwindigkeit um einiges zu verbessern, da man bisher immer noch

    mysql_store_result() bzw. mysql_free_result() verwenden musste, um Daten richtig auslesen zu können.

    Vorteile:

    - Mithilfe der Cachefunktionen wird unser gesamter Code schneller. Die Geschwindigkeit verbessert sich um das 10-20 fache ( Klick mich für das Ergebnis )

    - Man braucht nicht mehr mysql_store_result() bzw. mysql_free_result() zu verwenden

    - Es ist mittlerweile auch leichter Daten effektiv auszulesen als mit sscanf ( und auch schneller als sscanf ! )

    Hier mal ein Beispiel wie man mit sscanf Daten ausgelesen hat:



    sscanf(store,"p<|>s[24]s[20]s[30]",pName,Fraktion,irgendeinstring)

    Wird durch die neuen cache Funktionen zu:

    cache_get_row(0,0,pName);
    cache_get_row(0,1,Fraktion);
    cache_get_row(0,2,irgendeinstring);

    oder zu

    cache_get_field_content(0,"Name",pName);
    //weiteres hier

    Das ganze hier ist schneller als sscanf & auch einfacher für die, die spezifischen Symbole davon nicht kennen.. Zwar ist das parsen der einen Linie von sscanf schneller als die cach_get_rows bzw.
    cache_get_field_content, jedoch arbeitet die sscanf Lösung auch mit mysql_fetch_row, was einen extra Array benötigt die "Daten" zu holen und dann
    daraus zu parsen. Beim Caching ist das jedoch schneller.
    Die genaue Syntax der neuen Funktion bzw. Erklärung folgt in Kapitel 4.


    4. Erklärung aller neuen Funktionen
    In diesem Kapitel werde ich euch die Syntax,Nutzen und jeweils ein Beispiel der neuen Funktionen bringen.

    mysql_function_query(connectionHandle,query[],bool:cache,callback[],format[],{Float,_}:...)


    Fangen wir doch mal beim wichtigsten an, um einen Query nutzen zu können.
    Die Funktion mysql_query wurde durch mysql_function_query ersetzt. Dabei wurden auch noch neue Parameter bei der letzeren Funktionen hinzugefügt.
    Die Erklärung der Parameter
    - connectionHandle = Logischerweiße die ConnectionHandle eurer MySQL Verbindung. Speichert den Rückgabewert von mysql_connect am besten in einer globalen Variable, und setzt diese dann hier immer ein.
    -query[] = Der Query der ausgeführt werden soll. z.B "SELECT XX FROM XX Where YY = XX"
    -bool:cache = Setzt ihr dies auf true, wird festgelegt, dass ihr den Cache verwenden wollt, false, deaktiviert den Cache. Empfehlenswert ist es, den Cache nur bei SELECT Abfragen zu nutzen, bei UPDATE INSERT, etc. lasst ihr das am besten auf false
    -callback[] = Der Thread bzw. das Callback, in dem der Code weiterlaufen soll. Auch hier, am besten nur bei SELECT Abfragen verwenden, bei allen
    anderen Abfragen einfach leerlassen also "" einfach reinschreiben


    -format[] = Hier habt ihr die Möglichkeit, Parameter in den jeweiligen Callback (wenn ihr einen benutzt) mitzuliefern, wie z.B Bei SetTimerEx
    -{Float }: ... = Hier kommt rein, was ihr für Parameter an das entsprechende Callback übergeben wollt.


    Ein kleines Beispiel zu mysql_function_query:



    mysql_function_query(handle,"SELECT ... FROM table ...'",true,"QueryFinished","si","Logan_Adams",playerid); //Führen einen SELECT Query aus, das kommt ins Callback QueryFinished, nutzen den Cache und übergeben Parameter an das Callback um eine Erstellung von anderen Variablen zu ersparen
    forward QueryFinished(Name[],playerid); // Wir forwarden unseren Callback mit den entsprechenden, oben angegebenen Parametern
    public QueryFinished(Name[],playerid) { //Wir erstellen unseren Callback
    printf("Name: %s , ID: %d",Name,playerid); // Geben es in der Konsole aus
    }

    Wie gesagt, das obige ist nur ein Beispiel ;)
    Nochmal erläutere ich das richtige Einsetzen des Caches ( macht nur bei SELECT Abfragen wirklich Sinn ( die ein Ergebnis zurückliefern) )
    Ein paar kleine Beispiele:

    mysql_function_query(handle,"SELECT * From accounts",true,"LoadPlayers",""); //Wir führen einen SELECT Befehl aus, aktivieren den Cache, lassen es ins Callback "LoadPlayers" umleiten

    Wenn ich jetzt z.B einfach ein paar Werte updaten will sieht das ca. so aus

    mysql_function_query(handle,"UPDATE accounts SET level = 10 WHERE Name = 'Logan_Adams'",false,"",""); //Hier führen wir einen simplen Update Query aus, deaktivieren den Cache und lassen in kein Callback umleiten


    cache_get_data(&num_rows,&num_fields,connectionHandle=1)


    Diese Funktion returnt bzw. gibt die Anzahl der Zeilen und Felder zurück, die der Query returnt.
    - num rows = Anzahl der Zeilen
    - num fields = Anzahl der Felder
    Man kann diese Funktion z.B dazu verwenden, um zu überprüfen, ob der Spieler schon auf dem Server registriert ist
    Ein Beispiel:
    new query[128];
    format(query,sizeof query,"SELECT * FROM accounts WHERE Name = '%s'",SpielerName(playerid));
    mysql_function_query(dbhandle,query,true,"OnPlayerCheck","d",playerid); //Ausgeben aller Daten vom jeweiligen Spieler
    forward OnPlayerCheck(playerid); //Forwarden unseres Callbacks
    public OnPlayerCheck(playerid) {
    new zeilen,felder; //Erstellen zweier Variabeln für die Zeilen und Felder
    cache_get_data(zeilen,felder); //Benutzen unsere Funktion um die Zeilen und Felder zu erhalten die oben im Query angefragt wurden
    if(!zeilen) { //Wenn es keine Zeilen gibt , d.h. der Spieler noch nicht registriert ist
    //Weiter Code ....
    }
    else { //Wenn es doch welche gibt, d.h. der Spieler ist schon registriert
    //Weiter Code hier
    }
    }


    cache_get_row(row,idx,dest[],connectionHandle=1)

    Diese Funktion ist eine, die man eigentlich am meisten benutzt. Damit können wir viele unterschiedliche Daten auslesen.
    Diese Funktion nimmt den zeilen und den Feld Index und speichert dessen Daten im angegebenen String.
    - row = Zeilen Index meistens 0
    - idx = Felder Index
    - dest[] = Der String, in dem wir die ausgelesenen Daten zwischenspeichern wollen
    Wie gesagt wir brauchen den Felder Index. Wenn unsere Tabelle, beispielsweiße so aufgebaut ist:
    ID ( Auto Increment ) = Feld Index 0
    Name = Feld Index 1
    Passwort = Feld Index 2
    Level = Feld Index 3
    ...
    Hier bei fällt auf, dass der Feld Index immer bei 0 beginnt, was man sich merken muss (ist aber bei switch&case auch so)
    Wenn ihr also so Daten auslesen wollt, immer auf den richtigen Index achten ( ein Blick in eure MySQL Tabelle genügt aber dafür, um diesen herauszufinden)
    Ein kleines Beispiel:

    mysql_function_query(..........) //Unser Query
    forward ...... //Forwarden
    public ...... { //Das entsprechende Callback
    new speicher[30]; //Erstellen unserer Variable um die Daten zwischenzuspeichern
    cache_get_row(0,0,speicher); //Holt uns die Daten von jetzt z.B 'ID'
    printf("Seine ID: %d",strval(speicher)); //Konvertieren in eine Zahl, um es ausgeben zu können
    cache_get_row(0,1,speicher); //holen uns daten aus z.B "Name"
    printf("Name: %s",speicher); //Ausgeben
    cache_get_row(0,2,speicher); //Holen uns Daten aus "Passwort"
    printf("Passwort: %s",speicher); //Ausgeben in der Konsole
    cache_get_row(0,3,speicher); //Holen uns Daten aus "Level". Da dies aber eine Zahl ist, müssen wir diese noch konvertieren
    printf("Level: %d",strval(speicher)); //Ausgeben mit Konvertieren des Strings
    }

    Wichtig: Das was ihr erhaltet ist immer ein String. Wenn ihr jetzt z.B Level mit "speicher" ausgelesen habt müsst ihr z.B eurem Spieler Enum
    SpielerInfo[playerid][Level] "speicher" zuweisen, aber nicht vergessen, speicher in eine Zahl mit strval zu konvertieren.
    Bei Floats, dann natürlicht mit floatstr ...


    cache_get_field(field_idx,dest[],connectionHandle=1)

    Diese Funktion speichert den Namen eines Feldes.
    - field_idx = Der Feld Index des Felder, der ausgelesen werden soll
    - dest[] = Der String, indem der Name des Feldes zwischengespeichert werden soll
    Ein kleines Beispiel dazu wäre:

    //Den oberen Teil lasse ich weg ....
    public QueryBeendet()
    {
    new fname[30]; //Erstellen einer Variablen
    cache_get_field(0,fname); //Holen uns den Namen des Feldes mit dem Index 0 in die Variable "fname"
    printf("Name des Feldes mit dem Index 0: %s",fname); //Ausgeben in der Konsole
    return 1;
    }


    cache_get_field_content(row,const field_name[],dest[],connectionHandle=1)

    Diese Funktion macht eigentlich genau das gleiche wie cache_get_row. Der Unterschied hierbei ist nur, dass ich keinen Feldindex angeben muss.
    Für Leute, die zu faul sind, sich nach dem diesem zu erkunden, ist diese Funktion das richtige. Der
    Geschwindigkeitsunterschied ist auch nur ziemlich gering.
    - row = Die Zeile die ich auslesen will ( meistens 0)
    - const field_name[] = Der Name des Feldes das ich auslesen will. z.B "Passwort"
    - dest [] = String, in denen ich die Daten zwischenspeichern will
    Ein Beispiel dazu:

    //Oberer Teil ist wieder weggelassen
    //Natürlich muss unten stehender Code in ein Callback
    new store[24];
    cache_get_field_content(0,"Name",store); //Holen uns Daten aus "Name" und speichern in "store"
    printf("Name: %s",store); //Ausgeben des Wertes in der Konsole


    cache_get_row_int(row,idx,connectionHandle=1)

    Achtung: Diese Funktion wird nur bei den Versionen R8+ unterstützt.
    Diese Funktion ist eigentlich nur eine Variation der Funktion cache_get_row, die Syntax ist auch fast die gleiche, außer,
    dass es keinen destination Parameter gibt. Stattdessen wird das über die Rückgabe geregelt.
    Mit dieser Funktion ist es gleich möglich Spalten in einen Integer Wert zu speichern, man muss also nicht mehr mit strval den String
    von cache_get_row in eine Ganzzahl konvertieren.
    Ein kleines Beispiel dazu:
    public ...... { //Das entsprechende Callback
    new speicher;//Variable um die Ganzzahl zu speichern
    speicher = cache_get_row_int(0,0); //Holt uns die Daten von jetzt z.B 'ID' (natürlich muss der Index wieder stimmen)
    printf("Seine ID: %d",speicher); //Ausgabe, aber dieses Mal ist keine Konvertierung nötig
    }


    Neue Tests haben ergeben, dass der neue Code hier im Beispiel ca. 1,5 mal schneller ist, als der alte Code mit Konvertierung.


    cache_get_row_float(row,idx,connectionHandle=1)

    Achtung: Diese Funktion wird nur bei den Versionen R8+ unterstützt.
    Wieder "nur" eine Variation der Funktion cache_get_row, funktioniert wie cache_get_row_int.
    Auch hier kann man einen Float Wert von einer Spalte auslesen und auch wieder in einen Float-Wert speichern, ohne Konvertierung.
    Beispiel zu dieser neuen Funktion:
    public ...... { //Das entsprechende Callback
    new Float:speicher;//Variable um die Gleitkommazahl zu speichern
    speicher = cache_get_row_float(0,5); //Holt uns die Daten von jetzt z.B 'LastX' (natürlich muss der Index wieder stimmen)
    printf("LastX-Koordinate: %f",speicher); //Ausgabe, aber dieses Mal ist keine Konvertierung nötig
    }


    Auch hier ist der neue Code ca. 2 mal schneller als mit Konvertierung.


    cache_get_field_content_int(row, const field_name[], connectionHandle = 1);

    Achtung: Diese Funktion wird nur bei den Versionen R8+ unterstützt.
    Diese Funktion bewirkt eigentlich genau das gleiche wie cache_get_row_int, nur dass man hier nicht den Zeilen Index angeben muss,
    sondern nur den Namen des zu Inhalt holenden Feldes, konvertiert dabei dann das Ergebnis gleich in eine Ganzzahl, um nicht
    selbst manuell konvertieren zu müssen.
    Beispiel:
    public .... { //das entsprechende Callback
    new store;
    store = cache_get_field_content_int(0,"ID",dbhandle); //Inhalt aus dem Feld ID holen
    printf("ID: %d",store); //In der Konsole ausgeben
    }


    cache_get_field_content_float(row, const field_name[], connectionHandle = 1);

    Achtung: Diese Funktion wird nur bei den Versionen R8+ unterstützt.
    Macht genau das gleiche wie cache_get_field_content_int, konvertiert das Ergebnis jedoch jetzt gleich in eine Gleit bzw. Fließkommazahl.
    Beispiel ist hier, so denke ich, nicht von Nöten.

    5. Schlusswort


    Ich hoffe ich konnte mit diesem Tutorial einigen Leuten helfen, die bisher mit der R7 Version noch nicht zurecht gekommen sind.
    Wenn irgendwo Fehler im Tutorial sind, bitte macht mich darauf aufmerksam


    Mit Freundlichen Grüßen

    So habe mal dir die "heutige Sitzung" mal rauskopiert:


    Was auffällt, das im Query aber das richtig gehashte PW ist, jedoch nicht eingetragen wird :O


    Danke im Voraus


    MFG

    Hallo Leute,
    heute habe ich versucht mein Script, das auf MySQL Basiert, auf die R7 des G-Stylezzz Plugins umzuschreiben.
    Dort werden nur noch threaded Queries unterstützt, außerdem gibt es dazu noch Cache Funktionen, die die Performanche bis zu 12 mal so gut verbessern.
    Nachdem ich alles umgeschrieben habe, gibt es jetzt jedoch leider ein paar Bugs.
    Es wird kein richtiges Passwort eingetragen. D.h. immer wird '0' anstatt der Eingabe eingegeben. Dann wird auch immer der Account zwei mal angelegt ...#
    Hier mal ein bisschen Code:
    case DIALOG_REGISTER: {
    if(strlen(inputtext) < 6) {
    SendClientMessage(playerid,ROT,"Fehler: Dein Passwort darf nicht kürzer als 6 Zeichen sein. Bitte wähle ein anderes Passwort!");
    ShowPlayerDialog(playerid,DIALOG_REGISTER,DIALOG_STYLE_PASSWORD,"Registrierung",""WEISS_HTML"Bitte gebe hier dein Passwort ein,das du festlegen willst.\nWichtig: Merke es dir gut und beachte Groß- bzw. Kleinschreibung:","OK","");
    }
    else {
    new buffer[129];
    WP_Hash(buffer,sizeof buffer,inputtext);
    CreateAccount(playerid,buffer);
    SetPVarInt(playerid,"eingeloggt",1);
    SpawnPlayer(playerid);
    }
    }
    stock CreateAccount(playerid,pass[])
    {
    new query[256],Name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, Name, MAX_PLAYER_NAME);
    mysql_real_escape_string(Name,Name);
    mysql_real_escape_string(pass,pass);
    format(query, sizeof(query), "INSERT INTO `accounts` (`Name`, `Passwort`) VALUES ('%s', '%s')", Name, pass);
    mysql_function_query(mysql_connectionhandle,query,false,"","");
    return true;
    }


    Wenn ihr mehr Code braucht, sagt es einfach.


    Danke im Voraus

    Hey Leute,
    komischerweiße mache ich nur heute mein Skript auf, includiere was und compile.
    Die Includes habe ich danach nicht mehr inkuldiert, jetzt kommen auf einmal Errors und Warnings, die vorher nie da waren.
    Errors/Warnings:


    Wenn man sich mal die Zeile 511 anschaut, ist mir nichts aufgefallen:

    stock mysql_CheckAccount(playerid)
    {
    new Query[128],Name[MAX_PLAYER_NAME+1];
    GetPlayerName(playerid, Name, MAX_PLAYER_NAME+1);
    mysql_real_escape_string(Name, Name);
    format(Query, sizeof(Query), "SELECT * FROM `accounts` WHERE `Name` = '%s'", Name);
    mysql_query(Query,THREAD_OnAccountChecked); //DAS HIER IST DIE ERRORZEILE
    return 1;
    }


    Danke im Voraus!


    MFG

    Wieso editierst du denn die Include ?
    Ist dir eigentlich bewusst, dass die Include eigentlich gar nicht das "richtige" Junkbuster ist, sondern das Filterscript das Anti Cheat System beinhaltet ?


    MFG

    Danke und frage , Was passiert wenn man mit einem Befehl leben bekommt ist das dann weg ??


    Bzw. wenn man duch den befehl /gmwaffen Waffen bekommt sind diese dann auch weg ?


    Nein sind sie meines Wissens nicht, denn im Junkbuster wird dein Befehl also GivePlayerWeapons durch die serverseitige Funktion erstetzt, und die Waffen müssten dort bleiben, bloß bei Cheatern, b ei denen wird diese Funktion nicht aufgerufen und die Waffen werden weggenommen, usw.


    MFG


    genau das sagt mir einer der hier Donator gekaut hat :facepalm:


    Wie kann man bitte den Donator Rank mit Zigaretten vergleichen ?
    Zudem unterstütze ich damit das Forum, im Gegensatz ich mit Zigaretten mir mein eigenes Grab schaufle, und Donator mir weitaus billiger kommt, als
    für Zigaretten 5 Euro / Tag auszugeben.


    MFG

    Ich würde nicht mehr Zamaroths sondern jetzt iPlexomax's Textdraweditor benutzen, da
    man das jetzt alles mit der Maus machen kann und nicht mehr mit den Pfeiltasten, etc....
    Einfach mal in der SuFU eingeben im englischen SAMP Forum.


    MFG