[jTuT] MySQL R41-4 (Installation, XAMPP, Verwendung, Bedienung & Registrations-System)

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
  • Wenn du Daten von Usern speichern möchtest die eventuell schon Disconnected sind. Würde ich "mysql_query" verwenden weil ich neuer Thread eigentlich unnötig dafür ist.


    Über GetPlayerMoney würde ich auch das Geld nicht abfragen, User können sich das Geld mit s0beit Cheaten und dann abspeichern lassen. ;)


    Und du erstellt nur den Query aber rufst ihn nirgends ab. :) (mysql_query(Handle, Query);)

  • Guten Morgen.


    Ich habe folgendes Problem:


    Wenn ich mich registriere klappt zwar alles aber das Level wird einfach nicht auf 1 gesetzt nach dem Login.
    Level wird nicht gespeichert und nicht wieder ausgegeben.
    Adminlevel wird nicht gespeichert


    @Jeffry bitte mal drüber schauen


    So sieht mein Code aus:


    forwars:


    Palyerenum:


    PlayerClass:


    Verbinden/Verlassen:


    OnDialogResponse: //Register/Login:


    MYSQL-SETING:


    Spielerprüfen/Registerprüfen/Loginprüfen:


  • @Jeffry bitte mal drüber schauen

    Könntest du den Code bitte nochmals korrekt formatiert posten? So wie es momentan ist kann ich leider nichts erkennen.



    Was man vielleicht noch sagen sollte ist, dass die Verschlüsselung hier von md5 nichts bringt, da kein Salt verwendet wird.

    Das kann man machen, hat aber mit dem Tutorial nichts zu tun, da sich das MySQL Plugin nicht um Verschlüsselungen handelt. ;)



    Wenn du Daten von Usern speichern möchtest die eventuell schon Disconnected sind. Würde ich "mysql_query" verwenden weil ich neuer Thread eigentlich unnötig dafür ist.


    Über GetPlayerMoney würde ich auch das Geld nicht abfragen, User können sich das Geld mit s0beit Cheaten und dann abspeichern lassen. ;)


    Und du erstellt nur den Query aber rufst ihn nirgends ab. :) (mysql_query(Handle, Query);)

    Zu 1:
    Das würde ich nicht empfehlen, da der Server so lange steht (=Lag) bis das Query ausgeführt wurde. Daher ein neuer Thread, dann hast du das Problem nicht.


    Zu 2:
    Das stimmt, das muss aber jeder für sich selbst entscheiden und es soll auch nur als Beispiel dienen. Mit einem wirksamen Anti-Cheat kann man es auch so nutzen (habe ich selbst so verwendet, auf meinem Server, ohne Probleme).


    Zu 3:
    Bezüglich welchem Code Teil? Könntest du diesen genauer nennen oder posten?

    3HZXdYd.png

    Einmal editiert, zuletzt von Jeffry ()

  • Nein, der wartet, bis das Query ausgeführt wurde.Siehe:

    http://wiki.sa-mp.com/wiki/MySQL/R33#mysql_query


    stock mysql_CheckAccount(playerid)
    {
    new pq[128],count;
    format(pq, sizeof(pq), "SELECT * FROM `users` WHERE `Spielername` = '%s'", SpielerName(playerid));
    mysql_query(dbhandle,pq);
    mysql_store_result();
    count = mysql_num_rows();
    mysql_free_result();
    return count;
    }


    Fehler :
    C:\Users\Dome\Desktop\Script.pwn(28665) : error 017: undefined symbol "mysql_store_result"
    C:\Users\Dome\Desktop\Script.pwn(28666) : error 017: undefined symbol "mysql_num_rows"
    C:\Users\Dome\Desktop\Script.pwn(28667) : error 017: undefined symbol "mysql_free_result"
    Ne idee? Gestern ging noch alles wtf.

  • Diese drei Funktionen existieren in dieser Version des Plugins nicht mehr, da sie veraltet sind.


    Nutze die Cache Funktion stattdessen.
    cache_get_row_count()


    Das kannst du direkt ins return setzen, und die drei Zeilen vor dem return löschen, sowie die Deklaration von count.

  • Hallo, ich wollte dass wenn der User sich registriert, das Geld auf 2500 gesetzt wird. Dies funktioniert aber nicht.
    Hier der Code:


    public OnUserRegister(playerid)
    {
    //Der Spieler wurde in die Datenbank eingetragen, es wird die id ausgelesen
    PlayerInfo[playerid][p_id] = cache_insert_id();
    SendClientMessage(playerid, 0x00FF00FF, "[System] Registrierung erfolgreich.");
    PlayerInfo[playerid][pLevel] = 1;
    PlayerInfo[playerid][pAdmin] = 0;
    PlayerInfo[playerid][pMoney] = 2500;
    PlayerInfo[playerid][pKills] = 0;
    PlayerInfo[playerid][pDeaths] = 0;
    return 1;
    }


    Hoffe auf Hilfe, evtl. ja direkt von @Jeffry mit freundlichem Gruß,
    SebMcpepp

    2 Mal editiert, zuletzt von SebMcpepp () aus folgendem Grund: Neues Problem

  • Okey, aber müsste ja auch so gehen da bei OnUserLogin das Geld gegeben wird.



    public OnUserLogin(playerid)
    {
    //Query wurde ausgeführt und das Ergebnis im Cache gespeichert
    if(cache_get_row_count() == 0)
    {
    //Der Spieler hat ein falsches Passwort eingegeben
    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmelden", "Bitte melden Sie sich an:\n{FF0000}Falsches Passwort!", "Ok", "Abbrechen");
    }
    else
    {
    new geld = PlayerInfo[playerid][pMoney];
    GivePlayerMoney(playerid,geld);
    //Es existiert ein Ergebnis, das heißt der Spieler hat das richtige Passwort eingegeben
    //Wir lesen nun die erste Zeile des Caches aus (ID 0)
    PlayerInfo[playerid][p_id] = cache_get_field_content_int(0, "id", handle);
    PlayerInfo[playerid][pLevel] = cache_get_field_content_int(0, "level", handle);
    PlayerInfo[playerid][pAdmin] = cache_get_field_content_int(0, "admin", handle);
    PlayerInfo[playerid][pMoney] = cache_get_field_content_int(0, "money", handle);
    PlayerInfo[playerid][pKills] = cache_get_field_content_int(0, "kills", handle);
    PlayerInfo[playerid][pDeaths] = cache_get_field_content_int(0, "deaths", handle);
    PlayerInfo[playerid][pLoggedIn] = true;
    SendClientMessage(playerid, 0x00FF00FF, "[Konto] Eingeloggt.");
    }
    return 1;
    }


    Und das Level wird auch nicht wie gewollt auf Level 1 gesetzt sondern bleibt bei 0.


    public OnUserRegister(playerid)
    {
    //Der Spieler wurde in die Datenbank eingetragen, es wird die id ausgelesen
    PlayerInfo[playerid][p_id] = cache_insert_id();
    SendClientMessage(playerid, 0x00FF00FF, "[System] Registrierung erfolgreich.");
    PlayerInfo[playerid][pLevel] = 1;
    PlayerInfo[playerid][pAdmin] = 0;
    PlayerInfo[playerid][pMoney] = 2500;
    PlayerInfo[playerid][pKills] = 0;
    PlayerInfo[playerid][pDeaths] = 0;
    return 1;
    }


    Mit freundlichem Gruß,
    SebMcpepp

  • So wie es im Tutorial angegeben wird.


    So werden Accounts gespeichert:


    stock SaveUserStats(playerid)
    {
    //Wenn der Spieler nicht eingeloggt ist, dann speichere seine Statistiken nicht
    if(!PlayerInfo[playerid][pLoggedIn]) return 1;



    //Ansonsten speichere sie
    new query[256];
    mysql_format(handle, query, sizeof(query), "UPDATE users SET level = '%d', admin = '%d', money = '%d', kills = '%d', deaths = '%d' WHERE id = '%d'",
    PlayerInfo[playerid][pLevel], PlayerInfo[playerid][pAdmin], PlayerInfo[playerid][pMoney], PlayerInfo[playerid][pKills], PlayerInfo[playerid][pDeaths], PlayerInfo[playerid][p_id]);



    //Das Query wird abgesendet
    mysql_pquery(handle, query);
    return 1;
    }

    Hier die Dialoge für Login und Register:


    public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
    {
    if(dialogid == DIALOG_REGISTER)
    {
    //Spieler hat Abbrechen gewählt
    if(!response) return Kick(playerid);



    //Wenn der Spieler kein, oder ein zu kurzes, Passwort eingegeben hat
    if(strlen(inputtext) < 3) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registrierung", "Bitte registrieren Sie sich:\n{FF0000}Mindestens 3 Zeichen!", "Ok", "Abbrechen");



    //Wenn alles passt wird der Spieler in der Datenbank angelegt
    //Als Verschlüsselung für das Passwort wird MD5 verwendet
    new query[256];
    mysql_format(handle, query, sizeof(query), "INSERT INTO users (name, password) VALUES ('%e', MD5('%e'))", PlayerInfo[playerid][pName], inputtext);



    //Das Query wird abgesendet und die playerid an OnUserRegister übergeben
    mysql_pquery(handle, query, "OnUserRegister", "d", playerid);
    return 1;
    }
    if(dialogid == DIALOG_LOGIN)
    {
    //Spieler hat Abbrechen gewählt
    if(!response) return Kick(playerid);



    //Wenn der Spieler kein, oder ein zu kurzes, Passwort eingegeben hat
    if(strlen(inputtext) < 3) return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmelden", "Bitte melden Sie sich an:\n{FF0000}Mindestens 3 Zeichen!", "Ok", "Abbrechen");



    //Wenn alles passt wird die Datenbank ausgelesen
    new query[256];
    mysql_format(handle, query, sizeof(query), "SELECT * FROM users WHERE name = '%e' AND password = MD5('%e')", PlayerInfo[playerid][pName], inputtext);



    //Das Query wird abgesendet und die playerid an OnUserLogin übergeben
    mysql_pquery(handle, query, "OnUserLogin", "d", playerid);
    return 1;
    }
    return 0;
    }

    Hier noch etwas von OnPlayerRequestClass falls es nötig ist:

    public OnPlayerRequestClass(playerid, classid)
    {
    //Wenn der Spieler die Class-Selection betritt, prüfe ob er bereits eingeloggt ist
    if(!PlayerInfo[playerid][pLoggedIn])
    {
    //Wenn nicht, dann prüfe ob der Spieler ein Konto hat
    //Dazu wird ein Query gesendet und ein neues Callback aufgerufen
    //%e steht für einen geprüften String (sollte anstatt %s in Queries verwendet werden)
    new query[128];
    mysql_format(handle, query, sizeof(query), "SELECT id FROM users WHERE name = '%e'", PlayerInfo[playerid][pName]);



    //Das Query wird abgesendet und die playerid an OnUserCheck übergeben
    mysql_pquery(handle, query, "OnUserCheck", "d", playerid);
    }
    return 1;
    }

    Definiert ist alles so:

    enum pDataEnum
    {
    p_id,
    bool:pLoggedIn,
    pName[MAX_PLAYER_NAME],
    pLevel,
    pAdmin,
    pMoney,
    pKills,
    pDeaths
    }
    new PlayerInfo[MAX_PLAYERS][pDataEnum];


    Mfg,
    SebMcpepp

  • Hier mal fürs Register: Code Anpassen @Seb_Mcpepp



    Register:


    Login:



    Warum hast du Bei OnPlayerRequestClass folgendes Entfernt?


    Code
    public OnPlayerRequestClass(playerid, classid)
    {
        SetPlayerPos(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerCameraPos(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerCameraLookAt(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerFacingAngle(playerid,49.4261);
    	return 1;
    }
  • Warum hast du Bei OnPlayerRequestClass folgendes Entfernt?


    Code
    public OnPlayerRequestClass(playerid, classid)
    {
        SetPlayerPos(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerCameraPos(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerCameraLookAt(playerid, 329.0244,-1513.3033,36.0391);
    	SetPlayerFacingAngle(playerid,49.4261);
    	return 1;
    }

    Warum nicht? :P Und du hast mir schonmal weitergeholfen. Es wird nun das Level und das Geld gesetzt. Jedoch bekomme ich das Geld nicht auf die Hand trotz:
    public OnUserLogin(playerid)
    {
    //Query wurde ausgeführt und das Ergebnis im Cache gespeichert
    if(cache_get_row_count() == 0)
    { //Der Spieler hat ein falsches Passwort eingegeben
    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmelden", "Bitte melden Sie sich an:\n{FF0000}Falsches Passwort!", "Ok", "Abbrechen");
    }
    else
    {
    new geld = PlayerInfo[playerid][pMoney];
    GivePlayerMoney(playerid,geld);
    //Es existiert ein Ergebnis, das heißt der Spieler hat das richtige Passwort eingegeben
    //Wir lesen nun die erste Zeile des Caches aus (ID 0)
    PlayerInfo[playerid][p_id] = cache_get_field_content_int(0, "id", handle);
    PlayerInfo[playerid][pLevel] = cache_get_field_content_int(0, "level", handle);
    PlayerInfo[playerid][pAdmin] = cache_get_field_content_int(0, "admin", handle);
    PlayerInfo[playerid][pMoney] = cache_get_field_content_int(0, "money", handle);
    PlayerInfo[playerid][pKills] = cache_get_field_content_int(0, "kills", handle);
    PlayerInfo[playerid][pDeaths] = cache_get_field_content_int(0, "deaths", handle);
    PlayerInfo[playerid][pLoggedIn] = true; SendClientMessage(playerid, 0x00FF00FF, "[Konto] Eingeloggt.");
    SetPlayerScore(playerid,PlayerInfo[playerid][pLevel]);
    }
    return 1;
    }

    Hier gebe ich doch das Geld was im Account ist. Aber es passiert nix. Meine Tabelle sieht so aus:

    Code
    id 	name 	        password 	                      level     admin money   kills  deaths
    1 	SebMcpepp 	098f6bcd4621d373cade4e832627b4f6 	1 	  0   2500 	0 	0


    //edit by Seb: Habe es gelöst in dem ich es einfach in OnPlayerSpawn gepackt habe mit dem Geld geben und dem Score.

    Einmal editiert, zuletzt von SebMcpepp ()

  • @SebMcpepp
    du hast beim Login folgendes Stehen:


    LoginPlayer:


    Das Prob dabei ist du gibst Spieler x geld mit dem Wert Geld was nicht so ganz funktionieren kann.


    Es müsste so aussehen wenn ich mich jetzt nicht täuschen sollte:


    Richtige Variante(Bin nicht ganz sicher)


    Ich hoffe es klappt so. Ob es klappt weiß ich nicht ganz genau

  • @Markuslobicher GivePlayerMoney benötigt die playerid als ersten Parameter, dein Vorschlag wird also nicht klappen.




    Der Grund warum es nicht geht ist, dass erst das Geld gegeben wird und dann der Cache gelesen wird. Somit ist die Variable immer 0.


    Lösche
    new geld = PlayerInfo[playerid][pMoney];


    Und füge
    GivePlayerMoney(playerid, PlayerInfo[playerid][pMoney]);
    nach
    PlayerInfo[playerid][pMoney] = cache_get_field_content_int(0, "money", handle);
    ein, dann klappt es.

  • Der Grund warum es nicht geht ist, dass erst das Geld gegeben wird und dann der Cache gelesen wird. Somit ist die Variable immer 0.

    Das ging leider auch nicht als ich es dahinter geschrieben habe. Aber danke für die Hilfe von euch beiden, habe es nun gelöst und im vorherigen Post editiert ^^

  • @SebMcpepp
    Wenn du dem Spieler das Geld bei OnPlayerSpawn gibst, dann musst du ihm es aber vorher mit ResetPlayerMoney zurücksetzen, sonst verdoppelt sich sein Geld jedes mal wenn er spawnt.


    Ich schätze allerdings, dass du irgendwo zwischen Login und Spawn das schon drin hast, und der Spieler deshalb das Geld nicht bekommt, denn wenn du dir den Cache Wert des Geldes direkt nach dem Auslesen ausgibst, dann steht da der korrekte Wert drin (da er ja auch bei OnPlayerSpawn korrekt ist und dazwischen nicht verändert wird).



    @Markuslobicher für was denn? Das wichtigste ist ja dass es funktioniert, egal wer die Lösung oder den Hinweis bringt, wie im Fußball :)

  • @SebMcpepp
    Wenn du dem Spieler das Geld bei OnPlayerSpawn gibst, dann musst du ihm es aber vorher mit ResetPlayerMoney zurücksetzen, sonst verdoppelt sich sein Geld jedes mal wenn er spawnt.

    Ne muss ich garnicht, habe dem Spieler beim Registrieren 2500 per folgendem Code gegeben:

    if(dialogid == DIALOG_REGISTER)
    {
    //Spieler hat Abbrechen gewählt
    if(!response) return Kick(playerid);



    //Wenn der Spieler kein, oder ein zu kurzes, Passwort eingegeben hat
    if(strlen(inputtext) < 3) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registrierung", "Bitte registrieren Sie sich:\n{FF0000}Mindestens 3 Zeichen!", "Ok", "Abbrechen");



    //Wenn alles passt wird der Spieler in der Datenbank angelegt
    //Als Verschlüsselung für das Passwort wird MD5 verwendet
    new query[256];
    [b]--> [/b] mysql_format(handle, query, sizeof(query), "INSERT INTO users (name, password, level, money) VALUES ('%e', MD5('%e'),1,2500)", PlayerInfo[playerid][pName], inputtext);



    //Das Query wird abgesendet und die playerid an OnUserRegister übergeben
    mysql_pquery(handle, query, "OnUserRegister", "d", playerid);
    SetPlayerScore(playerid,PlayerInfo[playerid][pLevel]);
    return 1;
    }

    Und unter OnPlayerSpawn gebe ich im das Geld was im pMoney als Wert steht. Dies tuhe ich folgendermaßen und das funktioniert ohne das jedes mal 2500$ mehr gutgeschrieben werden:

    public OnPlayerSpawn(playerid)
    {
    if(PlayerInfo[playerid][pErsterLogin] == 0)
    {
    GivePlayerMoney(playerid,PlayerInfo[playerid][pMoney]);
    SetPlayerScore(playerid,PlayerInfo[playerid][pLevel]);
    PlayerInfo[playerid][pErsterLogin] = 1;
    //Tutorial(playerid);
    return 1;
    }
    else if(PlayerInfo[playerid][pErsterLogin] >= 1)
    {
    new geld = PlayerInfo[playerid][pMoney];
    GivePlayerMoney(playerid,geld);
    SetPlayerScore(playerid,PlayerInfo[playerid][pLevel]);
    return 1;
    }
    return 1;
    }


    Mit freundlichem Gruß,
    SebMcpepp