MySQL Registersystem [BlueG R8+ (R26)]

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • Hallo Community, ich präsentiere euch hier ein Register-Login-System für die von BlueG gemachte MySQL R8+ (R26) Version.


    In Version R8+ (R26) ist einiges anders, und was, dass wirst du gleich sehen.


    Download Link: Link zum MySQL Plugin (Google - Code)


    Die neuen Funktionen und die allgemeine Callbacks, die wir hier benutzen:


    [tabmenu]


    [tab='Callbacks']OnGameModeInit () // Nach main der nächstgeöffnete Callback nach dem Serverstart
    OnGameModeExit () // Wird aufgerufen, wenn der Server beendet wird
    OnPlayerConnect (playerid) // Spieler betritt den Server
    OnPlayerDisconnect (playerid,reason) // Spieler verlässt den Server
    OnDialogResponse (playerid, dialogid, response, listitem, inputtext[]) // Hier werden Dialogergebnisse gescriptet
    OnPlayerRequestSpawn (playerid) // Wird aufgerufen, wenn der Spieler den Spawnbutton drückt
    OnPlayerSpawn (playerid) // Wird aufgerufen, wenn der Spieler spawnt
    [tab='Neue Funktionen']mysql_format (connectionHandle, output[], len, format[], {Float,_}:... ) // Ähnlich wie format(...), der Unterschied wird unten erklärt
    mysql_tquery (connectionHandle, query[], callback[], format[], {Float,_}:... ) // Ähnlich wie mysql_function_query, bloß cache wird automatisch auf false gesetzt
    mysql_function_query (connectionHandle, query[], bool:cache, callback[], format[], {Float,_}:... ) // das neue "mysql_query", das sogenannte threaded Querying
    cache_get_field_content (row, const field_name[], dest[], connectionHandle = 1) // Gibt der Variable "dest", als String, den Inhalt des Feldes "field_name"
    cache_get_field_content_int (row, const field_name[], connectionHandle = 1) // Sollte wie unten benutzt werden! - Gibt den Integer (Ganzzahl) des Feldes "field_name" in die Variable
    cache_get_field_content_float (row, const field_name[], connectionHandle = 1) // Genauso wie bei cache_get_field_content_int, bloß diese als Float (Dezimalzahl)
    [/tabmenu]


    So kommen wir nun zu den Variablen, mit denen wir arbeiten werden:

    // Optional kannst du natürlich, falls du das noch nicht gemacht hast, MAX_PLAYERS verringern
    // Das ist äußerst resourcenschonender und schneller!
    #undef MAX_PLAYERS
    #define MAX_PLAYERS 5
    // Die Zahl der max. Spieleranzahl musst du natürlich anpassen!


    enum {
    Dialog_Reg = 1, // Anpassen, falls notwendig
    Dialog_Login
    }


    new mycon; // Würde ich verwenden, (mycon = MySQLConnection), um sicherzugehen (Siehe OnGameModeInit)


    enum UserData
    {
    Username[MAX_PLAYER_NAME+1], // +1 wegen dem Null-Terminator '\0'
    Geld, // Zum Test der Integerfunktion
    Float:Leben, // Zum Test der Float Funktion
    LastLogin[11], // Zum Test der Stringfunktion - XX/XX/XXXX + '\0' = 11 Zeichen
    bool:Logged // Ist der Spieler eingeloggt?
    }
    new User[MAX_PLAYERS][UserData];


    So wie du sehen kannst, gibt es keine Passwort Variable, wozu auch, die ist auch völlig unnötig!
    Also, da wir die Variablen haben die wir brauchen, fangen wir mit den Callbacks an!



    forward LoadPlayerDataSequence(playerid, l_step);
    forward KickPlayer(playerid);


    public OnGameModeInit()
    {
    mycon = mysql_connect("127.0.0.1","Username","Database","Passwort"); // Startet die Verbindung zur MySQL Datenbank (Angaben müssen angepasst werden!) (Homeserver muss 127.0.0.1, aufgrund des R26 Bugs(?))
    // mycon müsste wenn es geklappt hat nun 1 sein, ansonsten seid ihr nicht richtig verbunden!
    return 1;
    }


    public OnGameModeExit()
    {
    mysql_close(); // Das gibt es nach wie vor!
    return 1;
    }


    // Kommen wir zum 3. Callback - Einer der Wichtigsten!

    public OnPlayerConnect(playerid)
    {
    // Als allererstes sichern wir den Namen des Spielers
    GetPlayerName(playerid,User[playerid][Username],MAX_PLAYER_NAME);

    // Da wir diesen haben, kommt auch gleich der 1. Query!
    new query[60 + MAX_PLAYER_NAME]; // Anpassen, je nachdem wie groß der Text in mysql_format ist! (Ohne %e)
    mysql_format(mycon, query, sizeof(query), "SELECT COUNT(*) AS `count` FROM `User` WHERE `Name` = '%e'",User[playerid][Username]);
    // So - Was habe ich hier gemacht?
    // Folgendes: die Variable "query" hat nun den daneben eingegeben formatted Text bekommen
    // Wir zählen die Anzahl der Einträge, die in der Tabelle "User" sind, wo der Name "Spielername einfügen" ist.
    // Vielleicht fragt ihr euch, warum %e ? %e ist ein String, der speziell von mysql_format schon escaped wurde
    // also spezielle Zeichen werden abgeändert, damit sie korrekt abgespeichert werden können

    mysql_function_query(mycon, query, true, "LoadPlayerDataSequence","dd",playerid,1);
    // So - Was habe ich hier gemacht?
    // Ganz einfach, jetzt haben wir die Query rausgeschickt und dazu den Cache angeschalten!
    // Die Antwort erhalten wir nun in LoadPlayerDataSequence
    // Wie du unten sehen kannst enthält LoadPlayerDataSequence 2 Parameter, die, die ich oben angegeben habe!
    return 1; // Das nicht vergessen ;)
    }


    // So Callback Nr. 4 - OnPlayerDisconnect

    public OnPlayerDisconnect(playerid, reason)
    {
    if(User[playerid][Logged]) // Er soll nur gespeichert werden, wenn er auch aktiv war, also eingeloggt!
    {
    SavePlayerData(playerid); // Ich finde es extrem angenehm, es woanders zusammengefasst vorzufinden
    }
    ResetPlayerVariables(playerid); // Das Resetten kann eine lange Liste werden und auch das finde ich im unteren Bereich angenehmer
    // ResetPlayerVariables sollte aber aus Sicherheitsgründen auch für nicht eingeloggte Spieler gelten
    return 1;
    }


    // Callback Nr. 5 - OnPlayerSpawn
    public OnPlayerSpawn(playerid)
    {
    // Da ich nicht weiß, wo ihr spawnen wollt, müsst ihr die Position selbst reinmachen!
    // Das ist notwendig, da ihr sonst womöglich durch die Map fallt!
    SetPlayerPos(playerid,??,??,??); // Anpassen!
    return 1;
    }


    // Der vorletzte Callback - OnPlayerRequestSpawn

    public OnPlayerRequestSpawn(playerid)
    {
    if(!User[playerid][Logged]) return 0; // Solange der Spieler nicht eingeloggt ist, soll er nicht spawnen können!
    return 1; // Ermöglicht das Spawnen!
    }


    // Der Verwalter der Dialoge - OnDialogResponse

    public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
    {
    switch(dialogid)
    {
    case Dialog_Reg: // Nehmen wir zuerst den Register-Dialog
    {
    if(!response) // Wenn er den 2. Button (Abbrechen) gedrückt wurde
    {
    // Hier schicken wir den Spieler vom Server
    SendClientMessage(playerid,0xFF0000FF,"Bitte benutzen Sie /q, um das Spiel zu beenden!");
    SetTimerEx("KickPlayer",250,0,"i",playerid);
    return 1;
    }
    // Kein else nötig, da wir oben returnt haben
    if(!strlen(inputtext) || strlen(inputtext) < 3 || strlen(inputtext) > 25) // Für Anfänger (nehmen wir diese!)
    // if(!inputtext[0] || !(3 <= strlen(inputtext) <= 25)) // Für Fortgeschrittene
    {
    // Da die Eingabe wegen Länge oder gar keiner Eingabe fehlgeschlagen ist, bitten wir ihn erneut um eine Eingabe, diesmal mit Hinweis (in Rot!)
    ShowPlayerDialog(playerid, Dialog_Reg, DIALOG_STYLE_PASSWORD, "{00FF00}[Passwort Eingabe - Registrierung]","{FFFFFF}Bitte geben Sie Ihr gewünschtes Passwort ein!\n{FF0000}Bitte zwischen 3 & 25 Zeichen!","Register","Abbrechen");
    return 1;
    }
    // Da das geklappt hat, lassen wir ihn auf den Server, davor aber legen wir einen Eintrag für ihn in der Datenbank ab
    new query[128+MAX_PLAYER_NAME], year, month, day;
    getdate(year, month, day);
    format(query,sizeof(query),"%d/%d/%d",day,month,year); // Damit wir keine extra Variable noch extra erstellen müssen
    mysql_format(mycon,query, sizeof(query), "INSERT INTO `User` (`Name`, `Passwort`, `Geld`, `Leben`, `LastLogin`) VALUES('%e','%e',0,100.0,'%e')", User[playerid][Username], inputtext, query);
    mysql_tquery(mycon, query, "", ""); // Hier benutzen wir mysql_tquery, da wir keine Werte aus der Datenbank brauchen, sondern etwas reinschreiben
    User[playerid][Logged] = true;
    SpawnPlayer(playerid);
    return 1;
    // Register fertig!
    }
    case Dialog_Login:
    {
    if(!response) // Wenn er den 2. Button (Abbrechen) gedrückt wurde
    {
    // Hier schicken wir den Spieler vom Server
    SendClientMessage(playerid,0xFF0000FF,"Bitte benutzen Sie /q, um das Spiel zu beenden!");
    SetTimerEx("KickPlayer",250,0,"i",playerid);
    return 1;
    }
    // Kein else nötig, da wir oben returnt haben
    if(!strlen(inputtext) || strlen(inputtext) < 3 || strlen(inputtext) > 25) // Wie gesagt, Für Anfänger
    // if(!inputtext[0] || !(3 <= strlen(inputtext) <= 25)) // Für Fortgeschrittene
    {
    // Da die Eingabe wegen Länge oder gar keiner Eingabe fehlgeschlagen ist, bitten wir ihn erneut um eine Eingabe, wieder mit Hinweis (in Rot!)
    ShowPlayerDialog(playerid, Dialog_Login, DIALOG_STYLE_PASSWORD, "{00FF00}[Passwort Eingabe - Loginsequenz]","{FFFFFF}Bitte geben Sie Ihr Passwort ein!\{FF0000}Es hat mindestens 3 Zeichen!","Login","Abbrechen");
    return 1;
    }
    // So hier müssen wir nun Abfragen ob das Passwort denn dasselbe ist!
    new query[80 + MAX_PLAYER_NAME];
    mysql_format(mycon, query, sizeof(query), "SELECT COUNT(*) AS `count` FROM `User` WHERE `Name` = '%e' AND `Passwort` = '%e'",User[playerid][Username],inputtext);
    // Hier ganz einfach, wie beim anderen COUNT, wird hier auch gezählt, ob es diesen Eintrag, wo Name und Passwort gleich sind, gibt!
    mysql_function_query(mycon, query, true, "LoadPlayerDataSequence","dd",playerid,2); // Step 2
    // Das ganze schicken wir ab!
    return 1;
    }
    }
    return 1;
    }



    public LoadPlayerDataSequence(playerid, l_step)
    {
    switch(l_step) // Damit man nicht ewig if(...) else if(...) usw. schreiben muss
    {
    case 1:
    {
    // Jetzt gucken wir, ob es einen Eintrag gibt
    new count = cache_get_field_content_int(0,"count"); // Hier holen wir uns den Integer als der "count", die wir temporär in MySQL erstellt haben und stecken sie in die Variable count
    if(count) // Wenn count 1 oder höher ist (Keine Angst, höher als 1 kann sie nicht kommen)
    {
    // Der Eintrag existiert, also lassen wir den Spieler einloggen
    ShowPlayerDialog(playerid, Dialog_Login, DIALOG_STYLE_PASSWORD, "{00FF00}[Passwort Eingabe - Loginsequenz]","{FFFFFF}Bitte geben Sie Ihr Passwort ein!","Login","Abbrechen");
    return 1;
    }
    else
    {
    // Es gibt keinen Eintrag, also ist er neu und muss sich registrieren
    ShowPlayerDialog(playerid, Dialog_Reg, DIALOG_STYLE_PASSWORD, "{00FF00}[Passwort eingabe - Registrierung]","{FFFFFF}Bitte geben Sie Ihr gewünschtes Passwort ein!","Register","Abbrechen");
    return 1;
    }
    }
    case 2:
    {
    // Jetzt gucken wir, ob es einen Eintrag gibt
    new count = cache_get_field_content_int(0,"count");
    if(count) // Wenn count 1 oder höher ist
    {
    // Der Eintrag existiert, also lassen wir den Spieler nun die Spielerdaten laden und danach den Spieler spawnen
    new query[60 + MAX_PLAYER_NAME];
    mysql_format(mycon,query, sizeof(query), "SELECT * FROM `User` WHERE `Name` = '%e'",User[playerid][Username]);
    mysql_function_query(mycon,query,true,"LoadPlayerDataSequence","dd",playerid,3);
    return 1;
    }
    else
    {
    // Es gibt keinen Eintrag, also ist das Passwort falsch
    ShowPlayerDialog(playerid, Dialog_Login, DIALOG_STYLE_PASSWORD, "{00FF00}[Passwort Eingabe - Loginsequenz]","{FFFFFF}Bitte geben Sie Ihr richtiges Passwort ein!\{FF0000}Die vorherige Eingabe war falsch!","Login","Abbrechen");
    return 1;
    }
    }
    case 3:
    {
    // Wir laden nun die Spielerdaten
    // Der Vorteil bei den cache-Funktionen ist, dass sie am Ende kein mysql_free_result brauchen sondern direkt danach den Cache leeren
    User[playerid][Geld] = cache_get_field_content_int(0,"Geld");
    User[playerid][Leben] = cache_get_field_content_float(0,"Leben");
    cache_get_field_content(0,"LastLogin",User[playerid][LastLogin]);
    User[playerid][Logged] = true;
    SpawnPlayer(playerid);
    return 1;
    // Fertig!
    }
    default:
    {
    // Falls er hier auftauchen sollte, was eigentlich unwahrscheinlich ist, wird er aufgefordert zu reconnecten, und gleichzeitig gekickt!
    SendClientMessage(playerid,0xFF0000FF,"Es könnte ein Bug aufgetreten sein! Bitte reconnecten Sie!");
    SetTimerEx("KickPlayer",250,0,"i",playerid); // Wegen einem Bug von SA:MP muss der Kick nun per Timer ablaufen, damit die Nachricht auftaucht!
    return 1;
    }
    }
    return 1;
    }


    stock SavePlayerData(playerid)
    {
    // Hier speichern wir noch die Daten ab
    new query[150 + MAX_PLAYER_NAME];
    new day,month,year; getdate(year,month,day);
    format(User[playerid][LastLogin],11,"%d/%d/%d",day,month,year);
    mysql_format(mycon,query, sizeof(query), "UPDATE `User` SET `Geld` = %d,`Leben` = %.1f,`LastLogin` = '%e' WHERE `Name` = '%e'",User[playerid][Geld],User[playerid][Leben],User[playerid][LastLogin],User[playerid][Username]);
    mysql_tquery(mycon,query,"","");
    return 1;
    }


    stock ResetPlayerVariables(playerid)
    {
    // Und hier noch Resetten
    for(new x; UserData:x < UserData; ++x) User[playerid][UserData:x] = 0; // Danke für den Tipp Prototype
    return 1;
    }


    public KickPlayer(playerid)
    return Kick(playerid);


    Das Tutorial war lang, aber ich hoffe dafür sehr lehrreich und mit guten Erklärungen gefüllt!


    Bei Fragen und evtl. Fehlern schreibt mich doch an, oder besser schreibt es hier in diesen Thread.


    MfG NicoAiko

  • Hab die ganzen Errors :S


    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(52) : warning 225: unreachable code
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(77) : error 017: undefined symbol "SetPlayerSpawn"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(250) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(258) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(278) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(282) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(282) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(286) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(302) : warning 235: public function lacks forward declaration (symbol "LoadPlayerDataSequence")
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(309) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(326) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(338) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(338) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(346) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(347) : error 017: undefined symbol "cache_get_field_float"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(363) : warning 209: function "LoadPlayerDataSequence" should return a value
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(391) : warning 235: public function lacks forward declaration (symbol "KickPlayer")
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    9 Errors.


  • Du hast nicht die neuste Version von MySQL, SetPlayerSpawn hab ich nicht benutzt,
    Zeile 52 bitte nennen, den Rest auch, bitte, und du hast die Forwards nicht gemacht (KickPlayer)
    Und bei LoadPlayerDataSequence hatte ich das return 1; am Ende auskommentiert, weil ich mir nicht sicher war, obs notwendig ist.
    Anscheinend schon, also muss das entkommentiert werden.


    MfG

  • Du hast nicht die neuste Version von MySQL, SetPlayerSpawn hab ich nicht benutzt,
    Zeile 52 bitte nennen, den Rest auch, bitte, und du hast die Forwards nicht gemacht (KickPlayer)
    Und bei LoadPlayerDataSequence hatte ich das return 1; am Ende auskommentiert, weil ich mir nicht sicher war, obs notwendig ist.
    Anscheinend schon, also muss das entkommentiert werden.


    MfG


    Vielen Dank, finde die neuste Version nicht ^^ kannst du mir den Link schicken.


    Danke nochmals

  • t


    Hm, habe die ganzen Fehler behoben aber jetzt habe ich mehr Erros + die neue Version.
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(60) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(251) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(259) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(262) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(279) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(283) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(283) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(287) : warning 217: loose indentation
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(288) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(310) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(327) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(332) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(339) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(339) : error 027: invalid character constant
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(347) : error 017: undefined symbol "cache_get_field_int"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(348) : error 017: undefined symbol "cache_get_field_float"
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(370) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(372) : error 035: argument type mismatch (argument 3)
    C:\Users\Can\Desktop\Samp Server\gamemodes\r7.pwn(376) : error 035: argument type mismatch (argument 3)
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    15 Errors.


  • Wie ich bereits sagte, Ich brauche die Zeilen dafür....
    Und hast du beides geupdated?


    Weil er sagt ja immer noch undefined symbol...

  • zum reseten der spieler variabeln kannst du auch eine for-schleife bneutzen
    for(new x; UserData:x < UserData; ++x) User[playerid][UserData:x] = 0;


    aber einen string versuchen mit format zu leeren ist einfach nur :facepalm: das hätte ich nicht erwartet von dir es gibt auch strdel.


    weiteres bei den dialogen kannst du es dir auch einfacher machen und zwar ein enum dazu verwendem



    enum {
    Dialog_Reg = 1,
    Dialog_Login,
    };


    Zu dem reicht auch 1 query um die daten zu aktualisieren


    Als weiteren tipp beim aufruf der jeweiligen funktion kann man auch state benutzen da muss nicht erstmal switch initalisiert werden und die zahlen durchgehen
    @LoadPlayerDataSequence(playerid, l_step);
    state MySQLState:load
    mysql_function_query(mycon, query, true, "@LoadPlayerDataSequence","dd",playerid,2) ;
    @LoadPlayerDataSequence(playerid, l_step)<MySQLState:load>
    {
    ....... code

  • Naja ich finde es mehr Copy & Paste als Tutorial


    Anstatt mit Name würde ich mit Userid arbeiten, da es einfacher in Späteren fällen sein wird als es immer mit Name zu machen
    (Ändert man den Namen darf man alle Tabellen ändern wo der name eingesetzt wird. Daher ist da userid sinnvoller)


    Den Rest hat ja schon Prototype angeschprochen

    All in all it's just another brick in the wall

  • Naja ich finde es mehr Copy & Paste als Tutorial


    Anstatt mit Name würde ich mit Userid arbeiten, da es einfacher in Späteren fällen sein wird als es immer mit Name zu machen
    (Ändert man den Namen darf man alle Tabellen ändern wo der name eingesetzt wird. Daher ist da userid sinnvoller)


    Den Rest hat ja schon Prototype angeschprochen


    Man kann kein Tutorial als Copy Paste tutorial bezeichnen die Erklärung sind vorhanden es kommt auf die Leute drauf an die dies als Vorlage nehmen um was neues zu lernen
    der Sinn und Zweck eines Tutorials ist nicht der das Leute den Inhalt kopieren und einfügen und meinen dann können sie es siehe den oberen Beitrag das ist einfach stupide. Nein es geht darum es nachzumachen den Code zu verstehen.

  • der Sinn und Zweck eines Tutorials ist nicht der das Leute den Inhalt kopieren und einfügen und meinen dann können sie es


    Das ist ja das Problem
    Ich wette das viele den Inhalt nur nehmen ohne groß zu lesen.
    Das wird das selbe werden wie in maddins Tutorial man sollte eher darauf achten das man die einzelnen Funkionen erklärt ohne groß an codes zu posten..
    Verstehst?


    bsp:
    statt
    // Wir laden nun die Spielerdaten
    // Der Vorteil bei den cache-Funktionen ist, dass sie am Ende kein mysql_free_result brauchen sondern direkt danach den Cache leeren
    User[playerid][Geld] = cache_get_field_content_int(0,"Geld");
    User[playerid][Leben] = cache_get_field_float(0,"Leben");
    cache_get_field_content(0,"LastLogin",User[playerid][LastLogin]);
    User[playerid][Logged] = true;
    SpawnPlayer(playerid);
    return 1;
    // Fertig!
    Es einzelnt erklären was die
    cache_get_field_content_int(0,"Geld");
    Bedeuten das ist sinnvoller in einen Tutorial als nur Codes zu posten die man einfach Kopieren kann..
    Daher seh ich es mehr als Copy&Paste an

    All in all it's just another brick in the wall


  • Ich habe es für Leute geschrieben, die solch ein Tutorial für den Anfang brauchen, daher nicht die komplizierte Gebrauchsweise der For-Schleife.
    Das mit strdel ist so ne Sache, werde ich evtl. ausbessern. Bei mir gibt es bei strdel Fehler, wenn ich 2dimensionale Arrays Variablen benutze :/


    Das mit dem Enum mag zwar sein, aber ich mag die Defines lieber, da habe ich für mich auch bessere übersicht, über benutzte Dialog_IDs und muss nicht rechnen und zählen oder so ^^


    Bei einem Query erstellt man wiederum ein großes Array, das hab ich nicht so gerne ^^
    Daher mach ich ein kleines und schicke alles nach einander ab. Bei Errors, seitens MySQL findet man auch schneller den Fehler ^^


    Das mit dem state ist mir neu...
    Das kenn ich noch gar nicht oO


    Wäre nett... wenn du mir das mal per PN oder so näher erklären könntest ^^


    MfG


    Edit:


    Ich habe mir das mal mit dem State durchgelesen (Tutorial von Kaliber) und es ist wie er schon sagte ne Code Optimierung.
    Für mich ist es kein weiteres Problem Switch&Case zu benutzen.
    Die State-Sache hat zwar was, aber ist meiner Meinung nach Zeit aufwendiger und für mich total unübersichtlich...


    Beavis


    Ich habe an sich das Tutorial geschrieben, ohne viel C&P reinzubringen..
    Meiner Meinung nach habe ich eine Menge erklärt.
    z.B. Die Funktionen sind ganz oben erklärt, also warum sollte ich sie nochmal erklären.


    Es stimmt das ein großteil der User, die dieses Tutorial lesen, bestimmt nicht auf die vielen Kommentare achten, aber das ist dann deren Problem.
    Meiner Meinung nach ist ein Tutorial zum Lesen und Verstehen da. Davon das es teils nur C&P ist, kann also gar nicht die Rede sein!
    (Falls ich es falsch aufgefasst habe, tut es mir leid. Ich habe es nur so verstanden)


    MfG

  • Ich hab mir mal erlaubt das Script etwas zu editieren und verbessern.
    Hier ist die editierte Version, meine eigenen Kommentare sind in eckigen Klammern.
    Besonders die Performance wurde verbessert, da 'cache_save' benutzt wurde. Dadurch wird im ganzen Script nur insgesamt ein Mal eine "SELECT"-Query abgeschickt.
    Verbessert hab ich es weil viele Leute immer noch nicht das Potenzial von 'cache_save' verstehen und ich will immerhin diese Funktion nicht umsonst eingebaut haben.
    Hoffentlich werden die Änderungen umgesetzt.
    MfG

  • Nicht schlecht, danke ^^
    Ich habe mich mit den anderen Funktionen die da waren noch nicht auseinander gesetzt, (wahrscheinlich weil ich überhaupt nicht wusste, dass es dir R20 schon gibt ^^)
    Ich werde es, wenn ich Zeit habe, aktualisieren!


    MfG


    Edit: Obwohl ich sehe gerade, du holst das Passwort aus der Datenbank ^^, da von bin ich ja nicht so der Fan...
    Die COUNT Abfragen sind mir da lieber, auch wenn es ein Query mehr ist...


    PS: Das mit den Konstanten ist doch wurst -_-
    Ich schreibe meine Variablen so wie ich denke, ob nu gecapst oder nicht... ._ .

  • Ich hab mir mal erlaubt das Script etwas zu editieren und verbessern.
    Hier ist die editierte Version, meine eigenen Kommentare sind in eckigen Klammern.
    Besonders die Performance wurde verbessert, da 'cache_save' benutzt wurde. Dadurch wird im ganzen Script nur insgesamt ein Mal eine "SELECT"-Query abgeschickt.
    Verbessert hab ich es weil viele Leute immer noch nicht das Potenzial von 'cache_save' verstehen und ich will immerhin diese Funktion nicht umsonst eingebaut haben.
    Hoffentlich werden die Änderungen umgesetzt.
    MfG


    Du solltest dennoch mal bedenken das , das Ergebnis des querys dadurch zwischen gespeichert wird im memory also temporär und du dieses Ergebniss ihrgend wann abrufen kannst.
    Das hat in dem fall nix mit Performance verbessert zu tun.