Autos aus Mysql Datenbank laden

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 mache hierfür ein extra Thema auf, weil das Thema höchst wahrscheinlich etwas ausführlicher wird.


    Ich habe eine Mysql Tabelle die so aufgebaut ist: (Bild im Anhang)


    Darin werden wenn ein User ein Auto bei einem Autohaus kauft sein Name und die Daten gespeichert.


    Jetzt habe ich ein Enum, welches alle Daten der Spielerautos speichern soll:



    Außerdem habe ich dort wo der Spieler geladen wird das hier eingefügt:


    Code
    mysql_format(db_handle,query,sizeof(query),"SELECT * FROM usercars WHERE besitzer = '%s'",GPlayerName(playerid));
       			mysql_tquery(db_handle,query,"LoadPlayerCars","i",playerid);


    Ich habe nur keine Ahnung wie das public LoadPlayerCars aussehen muss um die Autos richtig, an deren Spawnposition, zu laden.
    Bzw, vielleicht könntet ihr mir auch helfen, oder mir einen Tipp geben kann wie ich eine funktion schreiben kann die Überprüft ob dem Spieler ein Auto gehört, dessen Vehicle ID übergeben wird.
    z.B;

    Code
    stock IsPlayerOwnerOfCar(playerid,vID)
    {
    
    
      return 1;
    }


    Hänge teilweise recht stark an mysql leider, und hoffe ihr könnt mir auch ein bisschen erklären was ihr macht, weil ich es gerne verstehen würde.




    edit: ich bekomme in dieser Zeile einen Fehlercode:

    Code
    pCar[playerid][besitzer] = GPlayerName(playerid);
    
    
    error 047: array sizes do not match, or destination array is too small
  • Du sprichst von "die Autos". Wie viele Fahrzeuge kann ein Spieler besitzen?
    Davon ist der Code nämlich sehr stark abhängig (eins oder mehrere).
    Außerdem gehe ich davon aus, dass die Fahrzeuge (bzw. das Fahrzeug) entfernt werden, wenn der Spieler den Server verlässt, oder?


    Auch dein Stock ist davon abhängig. Wenn du jetzt angenommen nur ein Fahrzeug pro Spieler erlaubst, dann würde die Prüfung so aussehen, unter obiger Annahme:

    C
    stock IsPlayerOwnerOfCar(playerid,vID)
    {
        if(IsPlayerConnected(playerid))
        {
            if(pCar[playerid][pc_vID] == vID) return 1;
        }
        return 0;
    }


    Zu dem Error den du im Code hast:

    C
    pCar[playerid][besitzer] = GPlayerName(playerid);

    Das ist nicht erlaubt, da man mehrdimensionalen Arrays keinen Wert direkt zuweisen kann/darf.
    Du musst entweder strcat oder format nutzen. Ich schlage immer format vor, da sich die meisten mehr darunter vorstellen können.

    C
    format(pCar[playerid][besitzer], MAX_PLAYER_NAME, GPlayerName(playerid));
  • Das enum mit Deklaration muss dann so aussehen:

    Man könnte den Besitzer auch weg lassen, da du ja über die playerid auf den Besitzer-Name kommst. Das kannst du aber halten wie du willst.
    Die 2 steht für die Anzahl der Fahrzeuge pro Spieler.
    Die modelid habe ich hinzugefügt.
    Die db_id habe ich außerdem hinzugefügt. Da muss die AUTO_INCREMENT id aus der Datenbank rein, damit du das Fahrzeug auch wieder speichern kannst.
    Füge beide bitte auch in deiner Tabelle hinzu, falls du das noch nicht hast.


    Dann dort wo die Fahrzeuge laden sollen:

    C
    mysql_format(db_handle,query,sizeof(query),"SELECT * FROM usercars WHERE besitzer = '%s'",GPlayerName(playerid));
    mysql_tquery(db_handle,query,"LoadPlayerCars","i",playerid);


    Und dann die Lade-Funktion so:

    Wie gesagt, du musst die Spaltennamen gegebenenfalls anpassen, wie sie bei dir heißen.


    Das Speichern würde dann so aussehen:


    Die Zuweisung (Besitzer?) wäre dann so:

    C
    format(pCar[playerid][i][besitzer], MAX_PLAYER_NAME, GPlayerName(playerid));

    Wobei i eben die Fahrzeugnummer ist, also das erste (0) oder zweite (1) Fahrzeug des Spielers. Ich weiß nicht ob du das über Keys (Schlüssel) machst, oder automatisch.
    Über Keys:

    C
    new i = carKey[playerid];
    format(pCar[playerid][i][besitzer], MAX_PLAYER_NAME, GPlayerName(playerid));


    Über automatische freie Suche:

    C
    new i = getFreeCarID(playerid);
    if(i == -1) return SendClientMessage(playerid, 0xFF0000FF, "Error: Du hast bereits die maximale Anzahl an Fahrzeugen.");
    format(pCar[playerid][i][besitzer], MAX_PLAYER_NAME, GPlayerName(playerid));

    Dazu dann dieser stock:

    C
    stock getFreeCarID(playerid)
    {
        for(new i=0; i<sizeof(pCar[]); i++)
        {
            if(pCar[playerid][i][pc_vID] == 0) return i;
        }
        return -1;
    }


    Der IsPlayerOwnerOfCar-stock sieht dann so aus:



    Weitere Funktionen, wie zum Beispiel das Entfernen der Fahrzeuge beim Disconnect kannst du analog zur SavePlayerCars Funktion machen. Die Schleife mit der Abfrage darin stehen jeweils für alle existierenden Fahrzeuge des Spielers.
    Schau mal ob du damit klar kommst. Bei Fragen kannst du natürlich gerne nachfragen.


    Ist jetzt etwas viel geworden, aber ich dachte mir bevor ich dir das als Pseudo-Code oder Lückentext gebe, schreibe ich es lieber gleich vollständig kurz zusammen, dann hilft es vielleicht auch dem einen oder anderen, der auf diesen Thread stößt, weiter. Daher ist es auch gut, dass du einen eigenen Thread erstellt hast (was sich eigentlich meistens empfielt).

    3HZXdYd.png

    Einmal editiert, zuletzt von Jeffry ()

  • Danke für den fast perfekten Code, 2 kleine Dinge nur:
    Bei dem:

    Code
    cache_get_field_content_int(i, "besitzer", pCar[playerid][i][besitzer], db_handle, MAX_PLAYER_NAME);


    gehört das MAX_PLAYER_NAME weg (zumindest bei meiner Mysql Version und das ist die neueste von BlueG


    Und hier:

    Code
    GetVehiclePos(pCar[playerid][i][pc_vID], pCar[playerid][i][s_x], pCar[playerid][i][s_y], pCar[playerid][i][s_z], pCar[playerid][i][s_r]);


    hast du, wahrscheinlich unabsichtlich, hinten noch die Rotation abgefragt, wodurch ein Error kommt.



    Ich habe den Deletecar Befehl jetzt so geschrieben, geht das besser oder passt das so?


    Code
    stock DeletePlayerCars(playerid)
    {
    	DestroyVehicle(pCar[playerid][0][vID]);
    	DestroyVehicle(pCar[playerid][1][vID]);
    	return 1;
    }

    Edit: 2 Fragen noch:


    1. wenn sich ein Spieler das Auto neu kauft, wie speichere ich das dann wenn er sich ausloggt ab, da wurde ja noch keine ID für das Auto aus der Datenbank geladen?
    2. Wie finde ich heraus ob es das erste, oder das zweite Auto des spielers ist, für meinen /car park Befehl?

    2 Mal editiert, zuletzt von Simon2202 ()

  • gehört das MAX_PLAYER_NAME weg (zumindest bei meiner Mysql Version und das ist die neueste von BlueG

    Welche Version nutzt du denn? In der neusten Version funktioniert das nämlich so, auch laut Doku: http://wiki.sa-mp.com/wiki/MySQL/R33#cache_get_field_content




    wahrscheinlich unabsichtlich, hinten noch die Rotation abgefragt, wodurch ein Error kommt.

    Oh ja, das war ein Copy-Paste Fehler, und da ich ohne das ohne Compiler geschrieben habe, ist es nicht aufgefallen. Ist verbessert.



    Schreibe das Löschen besser so:




    wenn sich ein Spieler das Auto neu kauft, wie speichere ich das dann wenn er sich ausloggt ab, da wurde ja noch keine ID für das Auto aus der Datenbank geladen?

    Mit einem INSERT INTO Query.





    Wie finde ich heraus ob es das erste, oder das zweite Auto des spielers ist, für meinen /car park Befehl?

    Das kannst du auch mit der Schleife machen.


    C
    for(new i=0; i<sizeof(pCar[]); i++)
    {
    	if(pCar[playerid][i][vID] != vehicleid)
    	{
    		//Parke das Fahrzeug der Nummer "i"
    	}
    }
  • Mit einem INSERT INTO Query.

    Das ist mein Dialog für den Auto Kauf:


    Selbst wenn ich das ganze jetzt mit einem INSERT INTO query schreibe, habe ich im Script ja noch immer nicht die eindeutige id des fahrzeuges, im Enum von dir mit db_id bezeichnet, da diese ja erst angelegt wird, wenn das Fahrzeug mit INSERT INTO eingetragen wurde.


    Nur gerade eine Idee:


    Muss ich bei dem Dialog das Auto mit INSERT INTO einfügen und direkt danach neu laden um die ID zu bekommen ?