[jTuT] Fraktions-Fahrzeug-System mit MySQL R41-4

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
  • [jTuT] Fraktions-Fahrzeug-System mit MySQL R41-4




    Hallo zusammen,
    da mir in letzter Zeit die Frage nach einem Fraktions-Fahrzeug-System basierend auf dem aktuellen (Stand 12/2019) MySQL R41-4 Plugin häufig aufgefallen ist, und ich kein vernünftiges Tutorial gefunden habe, poste ich jetzt selbst eines. Gerne kann dieser Thread auch für Fragen bezüglich dem System oder eventuellen Änderungen verwendet werden.



    Voraussetzungen:

    • Einzigste Voraussetzung für dieses Tutorial ist ein vorhandenes Fraktionssystem


    Kurzer Überblick:

    • Dieses Tutorial beschreibt und erklärt die Erstellung von Fahrzeugen, die nur von einer bestimmten Fraktion verwendet werden können. Außerdem wird der Aufbau der Tabelle in der Datenbank, sowie das Laden und das Speichern der Fahrzeuge erklärt. Am Ende haben wir ein komplett funktionsfähiges Fraktions-Fahrzeug-System welches auf BlueG's MySQL Plugin Version R41-4 basiert. Falls Du das Plugin noch nicht hast, lade es Dir bitte jetzt herunter und füge es entsprechend in Deinen Server ein.
      Es ist zu beachten, dass die Codes ganz bewusst mit englischen Variablennamen versehen worden sind, da dies der Einheitlichkeit und Allgemeinverständlichkeit eines Codes dient. Kommentare habe ich auf deutsch gehalten.




    Wir arbeiten uns durch den Code:

    • Zuerst müssen wir uns überlegen, welche Daten wir in der Datenbank speichern möchten. Bei diesem Fahrzeug-System nehmen wir der Einfachheit halber die gängingsten Daten, die da wären:
      Model-ID, X, Y, Z, Rotation, Farbe1, Farbe2 und die FraktionsID
      Außerdem benötigen wir eine Spalte ID die als Primary Key definiert wird.
      Natürlich können weitere Daten beliebig hinzugefügt werden. Damit das Ganze auch ohne Probleme funktioniert, selbst wenn die Tabelle (aus Versehen?) gelöscht wird, erstellen wir die Tabelle automatisch über den Code. Hierzu verwenden wir die folgende Funktion:





      Die Tabelle sieht dann in der Datenbank so aus:
      BvEOjq8.png
      (Quelle: Eigener Screenshot - phpMyAdmin)

    • Dazu erstellen wir auch gleich noch die später benötigte Funktion LoadFracVehicles(), in diese packen wir die obige Funktion:


      C
      LoadFracVehicles()
      {
          CreateFVTable();
          //Hier folgt später mehr.
          return 1;
      }



      Beide Funktionen musst Du ganz unten in Deinem Gamemode einfügen.
      Unter OnGameModeInit (bzw. OnFilterScriptInit) musst Du dann folgendes einfügen:

      C
      LoadFracVehicles();


    • Startest Du jetzt den Server, dann wird die Tabelle direkt in der Datenbank erstellt (falls sie noch nicht existiert), natürlich ohne Daten.
      Jetzt benötigen wir noch einen Speicherplatz für die später erstellten Fahrzeuge, das machen wir mit einem Enum und einer zweidimensionalen Variable. Dazu benötigen wir noch einen Maximal-Wert, den wir hier mit 10 definieren, das kann aber beliebig geändert werden (beachte das Limit an maximal erstellbaren Fahrzeugen (MAX_VEHICLES)).





      Daten können entweder direkt in die Datenbank eingetragen werden, oder mit den Befehlen erstellt/gelöscht werden, die wir später zusammen erstellen.
      In der Datenbank sieht das dann später zum Beispiel so aus:
      jD54TyK.png
      (Quelle: Eigener Screenshot - phpMyAdmin)

    • Jetzt nehmen wir uns die Funktion von vorhin wieder her und erweitern sie um die Funktion Daten aus der neuen Tabelle zu laden.


      C
      LoadFracVehicles()
      {
          CreateFVTable();
          //Hier folgt jetzt mehr.
          return 1;
      }



      Wir bauen dort nun eine Anweisung ein, die uns die Daten aus der Datenbank holt:

      C
      LoadFracVehicles()
      {
          CreateFVTable();
          //handle = die Connection Handle ID die vor mysql_connect steht.
          //Es wird ein SELECT Query an die Datenbank gesendet, diese gibt über das Callback LoadFracVehicles_Data
          //die Daten im Cache zurück.
          mysql_tquery(handle, "SELECT * FROM FracVehicles ORDER BY ID ASC", "LoadFracVehicles_Data");
          return 1;
      }


    • Dazu benötigen wir natürlich das Callback, in welchem wir dann die Daten aus dem Cache auslesen:




      Damit hätten wir das Laden erledigt. Dieses Callback muss ebenfalls ganz unten im Gamemode eingefügt werden.

    • Unser Fahrzeug wird nun also erstellt, falls es in der Datenbank existiert. Jetzt müssen wir die Daten natürlich nach einer eventuellen Änderung speichern lassen. Dazu eignet sich zum Beispiel ein Timer, der jede Minute alle Fahrzeuge speichert.
      Dazu erstellen wir bei OnGameModeInit einen Timer:


      C
      SetTimer("SaveAllFracVehs", 60000, true); //Timer wird alle 60 Sekunden ausgeführt



      Und ganz unten im Gamemode erstellen wir wieder das Callback:



      Diese Funktion kann natürlich auch bei OnGameModeExit eingefügt werden, falls gewünscht.
      Dazu einfach

      C
      SaveAllFracVehs();



      verwenden.


      Hinweis: Je nach dem wie viele Fahrzeuge erstellt werden macht es mehr oder weniger Sinn einen Timer zu verwenden. Bei 100 Fahrzeugen ist das kein Problem, hat man aber zum Beispiel 1000 Fahrzeuge, dann kann aufgrund der 1000 gleichzeitig ausgeführten Queries Lag entstehen, bzw. der Server kurzzeitig eingefroren sein. Dann sollte man von dieser Methode abstand nehmen und nur auf die nachfolgende Methode zurückgreifen.

    • Wenn wir schon dabei sind, dann können wir auch gleich noch eine Funktion erstellen, die ein Fahrzeug anhand seiner Vehicle ID speichern kann, sofern es ein Fraktions-Fahrzeug ist. Diese Funktion sieht dann so aus:




      Das können wir, wenn wir es schon haben, bei OnPlayerExitVehicle einbauen, damit das Fahrzeug gespeichert wird, wenn ein Spieler es verlässt.
      Dazu einfach bei OnPlayerExitVehicle das einfügen:

      C
      SaveFracVehCheck(vehicleid);



      Alternativ kann man auch einen /parken Befehl erstellen, durch den man die neue Position speichert.
      Das könnte dann so aussehen:

      C
      new vehicleid = GetPlayerVehicleID(playerid);
      if(SaveFracVehCheck(vehicleid)) return SendClientMessage(playerid, 0x00FF00FF, "Fahrzeug geparkt.");
      else return SendClientMessage(playerid, 0xFF0000FF, "Dieses Fahrzeug kann nicht geparkt werden.");



      Je nach Server ist das eine oder das andere sinnvoll. Man kann es aber auch ganz anders machen, das bleibt jedem selbst überlassen.

    • Falls sich die Farben der Fahrzeuge ändern können, dann müssen an entsprechender Stelle auch die Werte der Variablen geändert werden.
      Dies macht man beispielsweise so:




      Je nach dem an welcher Stelle das bei Dir im Code relevant ist, das können viele Stellen sein, muss aber nicht.
      Damit hätten wir den größten Teil eigentlich auch schon hinter uns. Es fehlt nur noch eine Kleinigkeit.

    • In diesem Tutorial geht es ja darum, Fraktions-Fahrzeuge zu erstellen. Momentan kann unsere Fahrzeuge aber noch jeder betreten, daher müssen wir jetzt bei OnPlayerEnterVehicle noch folgendes hinzufügen:




      Wie gesagt, dieser Code muss bei OnPlayerEnterVehicle eingefügt werden.

    • Jetzt könnten wir eigentlich den Server starten und alles funktioniert einwandfrei. Allerdings müssen wir die Daten für die Fraktions-Fahrzeuge immer mühselig manuell in die Datenbank eintragen, und das macht ja recht wenig Sinn. Deshalb erstellen wir jetzt noch einen Befehl um Fraktions-Fahrzeuge im Spiel zu erstellen und einen Befehl um Fraktions-Fahrzeuge zu löschen. Im Beispiel nutze ich ocmd. Falls Du einen anderen verwendest kannst du dies einfach umschreiben.
      Außerdem verwende ich in den Beispielen strtok, da dies ohne Plugin realsierbar ist und somit eine höhere Funktionalität gewährleistet.
      Die beiden Funktionen:





      Fraktions-Fahrzeuge erstellen:




      Fraktions-Fahrzeuge löschen:




      Und wenn wir schon dabei sind machen wir auch gleich noch den /parken Befehl komplett:

      C
      ocmd:parken(playerid)
      {
          if(!IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, 0xFF0000FF, "Du bist in keinem Fahrzeug.");
          new vehicleid = GetPlayerVehicleID(playerid);
          if(SaveFracVehCheck(vehicleid)) return SendClientMessage(playerid, 0x00FF00FF, "Fahrzeug geparkt.");
          else return SendClientMessage(playerid, 0xFF0000FF, "Dieses Fahrzeug kann nicht geparkt werden.");
      }


    • Damit wären wir durch. Es sind alle notwendigen Teile im Code vorhanden.
      Ich hoffe, das System funktioniert bei Dir jetzt wie bei mir ohne Probleme. Wenn nicht, oder wenn irgendwelche Fragen auftreten, bzw. aufgetreten sind, darfst Du diese gerne hier oder in der Scripting Base stellen.




    Für die Faulen unter uns:

    • Wie immer habe ich für die Faulen unter uns einen fertigen FilterScript.



      PasteBin.png





    Natürlich kann man das System weiter ausbauen, und weitere Daten hinzufügen, je nach dem was für den jeweiligen Server passend ist. Das könnten gefahrene Kilometer, Nummerntafeln, Tunings, etc... sein, da gibt es sehr viele Möglichkeiten. Diese kann man alle zimelich einfach hinzufügen. Falls Probleme auftreten, wie gesagt, einfach fragen!



    Viel Spaß damit! :)


    Beste Grüße,
    Jeffry 8)

    3HZXdYd.png

    7 Mal editiert, zuletzt von Jeffry () aus folgendem Grund: 22.03.2015: Dynamische Fahrzeugerstellung | 10.04.2015: Fehler in LoadFracVehicles_Data() behoben | 22.06.2015: PasteBin-Bild repariert | 08.11.2015: Code-Formatierung an WBB4 angepasst | 03.08.2016: Textanpassung auf R39-5 | 30.12.2018: Screenshots repariert | 26.12.2019: Update auf R41-4

  • Ein sehr schönes Tutorial. Meine Frage wäre jetzt, ob man mit einem ähnlichen Grundaufbau auch die Löhne einstellen könnte. Heißt die Löhne sind in einer Datenbank definiert, und man kann sie mit einem Befehl beliebig ändern, und es wird abgespeichert.

  • Wie man von Jeffry kennt das reinste Copy & Paste 8)


    Schönes Tutorial, leider für MySQL :/


    10/10 Fischen.


    Lg 8)

  • Ein sehr schönes Tutorial. Meine Frage wäre jetzt, ob man mit einem ähnlichen Grundaufbau auch die Löhne einstellen könnte. Heißt die Löhne sind in einer Datenbank definiert, und man kann sie mit einem Befehl beliebig ändern, und es wird


    Danke.
    Ja, im Grundprinzip (Laden/Speichern) ist das genau gleich.


    Wie man von Jeffry kennt das reinste Copy & Paste 8)


    Danke dir. ;)



    Information:
    In den nächsten Tagen werde ich einige Änderungen am Tutorial vornehmen um es dynamischer zu gestalten.

  • Super Tutorial Jeff ! 8)


    Hätten wir das bei mir eigentlich lassen können und ich hätte es mit deinem Tutorial machen können :p


    Weiter so, ein Haussystem auf diese Art ist mit deinem Tutorial auch machbar stimmts?



    Mit freundlichen Grüßen



    Die heutigen Noobs, sind die Profis von morgen! :thumbup:


    Danke an Jeffry für seine ständige Hilfsbereitschaft und freundliche Art. 8)

  • Plugins laufen nicht auf 100% aller Maschinen ohne Probleme. Dass es bei dir läuft heißt nicht, dass es auch auf allen anderen Maschinen läuft.
    Außerdem funktioniert sscanf nicht immer gleich, und variiert von Version zu Version. Strtok ist immer gleich und funktioniert immer.


    Sscanf darf ja gerne verwendet werden, wer will kann es ja entsprechend ändern, ist ja nicht verboten. Deshalb weise ich ja darauf hin.

  • Erstmal sehr gutes Tutorial Jeffry. Sehr gut erklärt und beschrieben.
    Ich habe nur einen kleinen Fehler den ich mir nicht erklären kann.
    Undzwar, wenn ich den /park Befehl nutze wird alles richtig in die Datenbank übergeben außer die Y Achse. In der Konsole wird sie richtig geprinted nur nicht übertragen.
    Hier der code:

    stock SaveFracVehCheck(vehicleid)
    {
    new query[256];
    for(new i=0;i<MAX_FRAC_VEHICLES;i++)
    {
    if(FracVehicle[i][f_vID] == vehicleid)
    {
    GetVehiclePos(FracVehicle[i][f_vID],FracVehicle[i][f_x],FracVehicle[i][f_y],FracVehicle[i][f_z]);
    printf("Y=%f",FracVehicle[i][f_y]);
    GetVehicleZAngle(FracVehicle[i][f_vID],FracVehicle[i][f_a]);
    format(query,sizeof(query),"UPDATE fraccars SET Modelid='%i',PosX='%f',PosY='%f',PosY='%f',PosA='%f',Color1='%i',Color2='%i',Fracid='%i' WHERE id='%i'",
    FracVehicle[i][f_modelID],FracVehicle[i][f_x],FracVehicle[i][f_y],FracVehicle[i][f_z],FracVehicle[i][f_a],FracVehicle[i][f_color1],FracVehicle[i][f_color2],FracVehicle[i][f_fracID],i);
    /*mysql_format(Handle,query,sizeof(query),"UPDATE fraccars SET Modelid='%i',PosX='%f',PosY='%f',PosY='%f',PosA='%f',Color1='%i',Color2='%i',Fracid='%i' WHERE id='%i'",
    FracVehicle[i][f_modelID],FracVehicle[i][f_x],FracVehicle[i][f_y],FracVehicle[i][f_z],FracVehicle[i][f_a],FracVehicle[i][f_color1],FracVehicle[i][f_color2],FracVehicle[i][f_fracID],i);*/
    mysql_pquery(Handle,query);
    return 1;
    }
    }
    return 0;
    }


    Struktur der Tabelle:

    Nach dem Befehl:

    In diesem Falle gibt printf aber eine ~ -1600 Koordinate aus.


    Schonmal danke im vorraus.

  • Ich hab gerade leider nicht an die Log gedacht. Aber diese gibt auch die richtigen Koordinaten aus.

    SQL
    [22:34:38] [DEBUG] mysql_pquery - connection: 1, query: "UPDATE fraccars SET Modelid='411',PosX='1472.139770',PosY='-1699", callback: "(null)", format: "(null)"


    @Mencent:


    //EDIT:
    Was ich auch gerade bemerke ist: Dass die Y Achse immer die gleiche ist egal wo man parkt.

  • Mir ist gerade aufgefallen, das du zwei mal die Position PosY abspeichern lässt (hintereinander). So muss das ganze eigentlich aussehen:
    format(query,sizeof(query),"UPDATE fraccars SET Modelid='%i',PosX='%f',PosY='%f',PosZ='%f',PosA='%f',Color1='%i',Color2='%i',Fracid='%i' WHERE id='%i'",
    Schau mal ob damit der Fehler behoben ist.


    EDIT:
    CaZe:
    Jeder kann mal was übersehen, ich habe das auch nicht direkt gesehen! :fun:

    Einmal editiert, zuletzt von AirM4X () aus folgendem Grund: Einen Satz hinzugefügt, ansonsten hätte es zur Verwirrung geführt!