Kleines Tutorial fьr LoginScript mit Mysql
#1

HI, wer mich nicht kennt ich bin Geramy inhaber der Vio-Server
da ich oft gefragt werde wie das mit dem mysql loginsystem geht poste ich einfach mal nen tut:

Nun gut ich mцchte euch heute hier jetzt das Mysql im Samp nдher bringen. Zuvor mцchte ich aber sagen, wenn man noch gar keine Ahnung von Mysql hat oder gerade erst am Anfang des Scriptens steht, lieber die Finger von MySql zu lassen. Dazu muss ich sagen, dass ich in diesem Script Linux verwende und dieses Mysql-Plugin: http://forum.sa-mp.com/index.php?topic=148182.0 das ich nur sehr Empfehlen kann. Die Installation eines MysqlPlugins findet ihr in anderen Tutorials in diesem Forum.
Hier geht es nun drum ein Mysql-Register/Login zu Scripten bestehend aus mehreren Gui's.

Bevor man Anfangen kann zu Scripten muss man sich ersteinmal ьberlegen was man Abspeichern mцchte in der Mysql-Datenbank (im folgenden Nenne ich die Mysqldatenbank nur noch DB). Hier in diesem Tutorial nehme ich als Beispiel fьr die Spielerdaten das Adminlevel. Desweiteren welche Informationen ьber den Spieler interessieren mich beim Registrieren (Hier im Tutorial: Nickname, Passwort, IP, Registrierdatum und E-Mail).

Nach diesen Ьberlegungen gehst du nun in das Verwaltungssystem deiner DB (z.B. PhpMyAdmin) und erstellst eine Datenbank in der die Tabellen des Scriptes gespeichert werden sollen (Hier im Beispiel: BeispielDatenbank). AnschlieЯen erstellst du 2 Tabellen. Eines fьr die Userdaten und eine fьr die Accountdaten. (Man kann alles auch in einem machen, habe mich aber fьr 2 Entschieden um eine schnellere Ьbersicht zu haben wenn ich mal nach Accounts suche oder anderem). In den Tabellen legst du die wьnschenswerten Spalten an. Denk daran das du eine Spalte ID mit autoincrement benцtigen kцnntest und das du die Spalten im Richtigen Format einstellst. (zB eine Spalte Adminleven mit Int(50).

Hier im Scirptbeispiel des Tutorials benцtigst du folgende Tabellen und Spalten:
1. Tabelle "players" mit den Spalten: ID (autoincrement Int(50), Nickname(varchar(255)),Passwort(varchar(255)),IP(v archar(255)),Register(varchar(255)),EMail(varchar( 255))
2. Tabelle "userdata" mit den Spalten: ID(autoincrement Int(50)),Nickname(varchar(255)),Adminlevel(int(50) )

Als nдchstes solltet ihr in wie ganz oben schon gesagt im Samp-Server euer Mysql-Plugin installiert haben.
Hier im Tut: http://forum.sa-mp.com/index.php?topic=148182.0
Nun kцnnen wir beginnen zu Scripten. Beginnen wir erstmal mit der Festlegung unserer Variablen und Definitionen und einbauen des Notwendigen includes.
--> Das Include
Dazu fьgst du ganz oben den Scriptcode ein:
Code:
#include <mysql>
Zunдchst brauchen wir auch 2 Farben. Eine fьr Erfolgreich und eine fьr Fehler. Dafьr nehmen wir Grьn und Rot.
Diese mьsst ihr ebenfals ganz oben einbauen. Am besten gleich unter den #include befehlen:
Code:
#define COLOR_ERROR 0xFF0000FF //Fehler
#define COLOR_SUCCESSFUL 0x00FF00FF //erfolgreich
Um es Spдter zu erleichten das Mysql-Script ein zubauen benцtigen wir 4 weitere Definitionen. Den Mysqluser, dessen Passwort, die datenbank und den Host(IP zur DB):
Code:
#define datahost "localhost"
#define datauser "BeispielUser"
#define datapass "BeispielPasswort"
#define database "BeispielDatenbank"
Desweiteren ist es Ratsam um spдter alles Schnell дndern zu kцnnen ebenfals eine Definition fьr den Timer, der zum Speichern der Userdaten da ist, anzulegen:
Code:
#define update_time 600000 //Zeitintervall des Timers in Millisekunden d.h. um Minuten zu bekommen Minuten *60000 Hier: 10 min
Kommen wir nun zu den Variablen. Wir brauchen zuerst eine Variable fьr die Registrationsdaten Hier nennen wir sie RegInfo sie braucht noch einen Index mit der SpielerID und eine InfoIndex (Keine Zahl sondern Text wie der Index rIP) diese InfoIndexe kann man ьber enums anlegen. DIe Zweite ist fьr die Spielerdaten und funktioniert genauso:
Code:
enum rInfo{
EMail[255],
Passwort[255],
IP[255],
RegisterDatum[255],
};
new RegInfo[MAX_PLAYERS][rInfo];

enum pInfo{
pLogged,
pAdmin
};
new PlayerInfo[MAX_PLAYERS][pInfo];
Um spдter die Accountdaten alle 10 Minuten (oder wie die Variable update_time eingestellt ist) zu Speichern benцtigen wir einen Timer. Dieser wird unter OnGameModeInit() plaziert. gleich kцnnen wir dort das Script um zur DB zu verbinden einbauen und den Log befehl fьr das Mysql.
Syntax der Funktionen:
--> mysql_connect(Hostadresse, Datenbankuser, Datenbankpasswort, Name der Samp-Datenbank, Automatisches Reconnecten bei Verbindungsverlust(mit einer Boolean-Variable true/false)); ==> Boolean := Wahrheitswert
--> mysql_log(LogType); ==> hat noch weitere Optionale Parameter
Nachlesen kцnnt ihr auch weitere Informationen ьber die Syntax auf der Website des DB-Plugins.
Script:
Code:
mysql_log(1); //diesen empfehle ich spдter auf mysql_log(0); zu setzen oder ganz zu lцschen wenn das Script funktioniert
mysql_connect(datahost,datauser,datapass,database,true);
SetTimer("Updater",update_time,true);
Baut man eine Verbindung auf muss man diese auch beenden. Daher bauen wir eine Funktion zum schlieЯen der Verbindung in OnGameModeExit ein. Desweiteren muss dort das letzte mal unsere Userdaten aller spieler gespeichert werden.
Code:
Updater();
mysql_close();
Jetzt ist schon die ganze Zeit im Script die Sprache von der Public Updater(). Diese mьssen wir natьrlich erst anlegen. Spдter werden die Userdaten in einer Public UserUpdate(playerid); gespeichert. Aber um sie fьr alle auszufьhren mьssen in unserer Updatefunktion alle Spieler durchgegangen werden und gespeichert. D.h. in einer Schleife. Dazu eignet sich besonders gut die for-to-do-Schleife.
Unsere Public mьsste wie folgt aussehen:
Code:
public Updater()
{
for(new i=0;i<MAX_PLAYERS;i++) //solange fьr i um eins erhцht von i=0 aus gilt,dass i kleiner der Maximalen Spielerzahl ist wird durchgefьhrt:
{
UserUpdate(i);// die Updatefunktion des Spielers
}

}
Dies sind erstmal alle Funktionen gewesen die soweit ohne Mysql funktioniert haben oder nur wenig enthalten haben. Aber um das eigentliche Script zu schreiben brauchen wir 3 Funktionen fьr unser Script:
1. Eine Zum Laden von Daten aus einer Tabelle
2. Eine Zum Ьberprьfen ob es die Date gibt (eventuell das auslesen einzellner Daten)
3. und das Speichern von Daten in der DB

die 1. und die 2. kann man zusammenfassen zu einer Funktion. Dies habe ich auch im Script getan wie ihr gleich sehen werden. Allerdings wird um Ressourcen zu sparen unser Loginsystem spдter mit einer eigenenstдndigen abfrage funktionieren.
Kommen wir nun zu Abfrage und Ьberprьfung:
Code:
public mysqlget(table[],bedien[],abfrag[],data[]) //Funktion: mysqlget(In welcher Tabelle befindet sich die Datei?, Welche Bedienung gilt? (zB ID des Spielers oder bekannte daten), Welche Spalte soll abgefragt werden?, Variable in der gespeichert wird)
{
new query[256]; //Query = Abfrage String muss definiert werden
format(query,sizeof(query),"SELECT %s FROM %s WHERE %s",abfrag,table,bedien);
// entspricht: Frage "abfrag" ab in der Tabelle "table" mit der Bedienung "bedien"
mysql_query(query); // sende die Abfrage
mysql_store_result(); //Liste die Ergebnisse auf
if(mysql_num_rows()) //Wie viele Zeilen hat das Ergebnis (Keine Zeile = Kein Ergebnis)
{
mysql_fetch_field(abfrag, data); //Frage das Feld "abfrag" ab (Feld entspricht dem Spalte in einer ErgebnisZEILE) und speichere in data
mysql_free_result(); //gibt den Speicher fьr weitere Abfragen wieder frei
return true; //gibt true=Wahr zurьck wenn die Date existiert und abgefragt werden konnte
}
else
{
mysql_free_result(); //siehe oben
return false; //gibt false zurьck wenn Date nicht existiert oder nicht Abgefragt werden konnte
}
}
Nun zur 3. Funktion der Speicherung der Daten. Da es im Script 3 wichtige Datentypen gibt (String, Integer und Float) muss man beachten das man entweder 3 Funktionen anlegt oder bei unserer Variante beim Ausfьhren der mysqlupdate-Funktion vorher die Variable in einen String umgewandelt hat.

Code:
public mysqlupdate(table[],bedien[],spalte[],data[])
{//Syntax: mysqlupdate( die Tabelle in der DB, Die Bedienung, Die Spalte, die Variable als String)
new query[256];
format(query,sizeof(query),"UPDATE %s SET %s='%s' WHERE %s",table,spalte,data,bedien);
//entspricht: Update die Tabelle "table" Setze "Spalte" den Wert "data" wo die Bedienung "bedien" gilt
//Es MUSS beachtet werden das zu speichernde Variablen im Query immer mir ' ' umschlossen werden mьssen daher '%s'
mysql_query(query); //senden des Querys
mysql_free_result(); //Freigabe des Speichers
}
Da wir nun die 2 Funktionen haben kцnnen wir uns an das eigentliche Login System machen:
die Login und die Registerfunktion:
Code:
public Login(playerid,playername[])
{
new query[256];
new data[255];
new bedienung[256];
format(bedienung,sizeof(bedienung),"Nickname='%s'",playername);
format(query,sizeof(query),"SELECT * FROM userdata WHERE %s",bedienung); //Nehme ALLE Daten aus userdata bei der die Bedienung "bedienung" gilt --> * steht immer fьr ALLE
mysql_query(query); // senden der ABfrage
mysql_store_result();//abfragen des ergebnisses
if(mysql_num_rows())//auflisten der zeilen
{
mysql_fetch_field("Adminlevel",data); //abfragen des felden Adminlevel und zwischen speichern in data
PlayerInfo[playerid][pAdmin]=strval(data);//umwandeln von data in die Spielervariable (ACHTUNG!! alle abfragten Daten sind erst Strings --> daher strval um es in einen Integer zu wandeln
if(PlayerInfo[playerid][pAdmin]>0)
{
SendClientMessage(playerid,COLOR_SUCCESSFUL,"Willkommen Admin!");
}
mysql_free_result();//freigabe des Speichers
PlayerInfo[playerid][pLogged]=1;//spieler ist eingeloggt
}
else
{
SendClientMessage(playerid,COLOR_ERROR,"Es ist ein Fehler mit deinem Account aufgetretten!");
Kick(playerid);
}
return 0;
}



public Register(playerid)
{
new playername[256];
GetPlayerName(playerid,playername,sizeof(playername));
new query[256];
format(query,sizeof(query),"INSERT INTO players (Nickname,Passwort,EMail,IP,Register) VALUES ('%s','%s','%s','%s','%s')",//Fьge in players ein mit den Spalten Nickname,Passwort,Email,Ip,Register der Werte.... sind (die Reihen folge in den Klammern muss die selbe bleiben)
playername,
RegInfo[playerid][Passwort],
RegInfo[playerid][EMail],
RegInfo[playerid][IP],
RegInfo[playerid][RegisterDatum]);
mysql_query(query); //senden
format(query,sizeof(query),"INSERT INTO userdata (Nickname) VALUES ('%s')",playername);
mysql_query(query);//einfьgen des Datensatzen in userdata mit Spalte Nickname deren wert der Speilername ist
mysql_free_result();
ShowPlayerDialog(playerid,3,1,"Loginsystem","Dein Account wurde erfolgreich angelegt \n Bitte logge dich ein!","Abbrechen","Login!");//anzeigen des Loginguis
}
Jetzt haben wir zwar einen Login und eine Registrierung aber die Speicherung der Daten fehlt noch also fьgen wir noch die UserUpdate(playerid) funktion ein:
Code:
public UserUpdate(playerid)
{
if(IsPlayerConnected(playerid))//ist spieler verbunden
{
if(PlayerInfo[playerid][pLogged]==1)//ist spieler eingeloggt?
{
new playername[255];
GetPlayerName(playerid,playername,sizeof(playername));
new bedien[256];
new updatestring[256];
format(updatestring,256,"%d",PlayerInfo[playerid][pAdmin]);//Umwandeln der Variable in einen String damit Updatefuntkion geht
format(bedien,sizeof(bedien),"Nickname='%s'",playername);//wieder die Bedienung
mysqlupdate("userdata",bedien,"Adminlevel",updatestring);//funktion mysqlupdate ausfьhren syntax siehe oben
}
}
}
Fehlt natьrlich auch noch das die Daten gespeichert werden wenn der User den Server verlдsst:
Code:
public OnPlayerDisconnect(playerid, reason)
{
UserUpdate(playerid);
PlayerInfo[playerid][pLogged]=0;
return 1;
}
Zu allerletzt mьsst ihr ganz oben noch die forward der Funktionen einbauen:
Code:
forward mysqlget(table[],bedien[],abfrag[],data[]);
forward Login(playerid,playername[]);
forward Register(playerid);
forward mysqlupdate(table[],bedien[],spalte[],data[]);
forward UserUpdate(playerid);
forward Updater();
Es fehlen jetzt nur noch 3 Dinge.
1. OnPlayerConnect
Es muss ein Gui erstellt werden wenn der Spieler drauf kommt:
Code:
public OnPlayerConnect(playerid)
{
new bedienung[256];
new playername[256];
GetPlayerName(playerid,playername,sizeof(playername));
format(bedienung,sizeof(bedienung),"Nickname='%s'",playername);
new daten[256];
if(mysqlget("players",bedienung,"Passwort",daten))//abfrage es gibt true zurьck oder false variable daten ist unwichtig
{
SendClientMessage(playerid,COLOR_SUCCESSFUL,"Du hast bereits einen Account");
ShowPlayerDialog(playerid,3,1,"Loginsystem","Du hast bereits einen Account \n Bitte logge dich ein!","Abbrechen","Login!");
}
else
{
SendClientMessage(playerid,COLOR_ERROR,"Du hast noch keinen Account");
ShowPlayerDialog(playerid,1,1,"Loginsystem","Du hast noch keinen Account \n Bitte gebe dein Passwort ein!","Abbrechen","Bestдtigen!");
}
return 1;
}
Die Funktion Disconnect (um Userdaten zu speichern + Spieler nicht mehr eingeloggt zu setzen:
Code:
public OnPlayerDisconnect(playerid, reason)
{
UserUpdate(playerid);
PlayerInfo[playerid][pLogged]=0;
return 1;
}
und zu letzt die Antwort auf die Gui's:

Code:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid==1)//registergui 1.Teil
{
if(response==1){Kick(playerid);}
else
{
format(RegInfo[playerid][Passwort],255,"%s",inputtext); //gewдhltes Passwort zwischenspeichern
ShowPlayerDialog(playerid,2,1,"Loginsystem","Um die Registration abzuschlieЯen gebe bitte noch deine Email an!","Abbrechen","Registrieren!");
}
}
if(dialogid==2)//registergui 2. Teil
{
if(response==1){Kick(playerid);}
else
{
format(RegInfo[playerid][EMail],255,"%s",inputtext);//zwischenspeichern der eingegeben email
GetPlayerIp(playerid,RegInfo[playerid][IP],255);//zwischenspeichern ip
new Year, Month, Day;
getdate(Year, Month, Day);
format(RegInfo[playerid][RegisterDatum],255,"%02d.%02d.%d", Day, Month, Year);//zwischenspeichern registrierungsdatum
Register(playerid);//registerfunktion ausfьhren
}
}
if(dialogid==3)//logingui
{
if(response==1){Kick(playerid);}
else
{
new playername[256];
GetPlayerName(playerid,playername,sizeof(playername));
new string[256];
format(string,sizeof(string),"Nickname='%s'",playername);
new data[255];
mysqlget("players",string,"Passwort",data);//abfrage passwort
if(!strcmp(data,inputtext,false))//auswertung ob pw's ьbereinsteimmen oder nicht
{
Login(playerid,playername);
}
else
{
ShowPlayerDialog(playerid,3,1,"Loginsystem","Dieses Passwort ist falsch. \n Bitte gib das richtige ein!","Abbrechen","Login!");
}
}
}

return 1;
}
Bitte Informiert euch ьber die Guis in anderen Tutorials da es hier mehr um die Mysql-Funktionen geht.

Vielen Dank fьrs Lesen, bei Anregungen Tipps Fragen oder sollte ich Fehler gemacht haben einfach Posten ich lese es gern und antworte auch gerne (bei bedarf kann ich auch eine Scriptdatei hochladen in der die Funktionen gespeichert sind)
Reply
#2

Sehr gutes Tutorial, Dankeschцn.
Reply
#3

Bei mir klappt das nicht mit den Database Tabellen -.-
Hier mein befehl
Quote:

CREATE TABLE IF NOT EXISTS `players` (
`ID` Int(50) NOT NULL,
`Nickname` VARCHAR(255) NOT NULL,
`Password` VARCHAR(255) NOT NULL,
`IP` VARCHAR(255) NOT NULL
`Register` VARCHAR(255) NOT NULL,
`EMAIL` VARCHAR(255) NOT NULL,
);

Hier die Fehlermeldung
Quote:

[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`Register` VARCHAR(255) NOT NULL,
`EMAIL` VARCHAR(255) NOT NULL,
)' at line 6
[Err] CREATE TABLE IF NOT EXISTS `players` (
`ID` Int(50) NOT NULL,
`Nickname` VARCHAR(255) NOT NULL,
`Password` VARCHAR(255) NOT NULL,
`IP` VARCHAR(255) NOT NULL
`Register` VARCHAR(255) NOT NULL,
`EMAIL` VARCHAR(255) NOT NULL,
);
[Msg] Finished - Unsuccessfully
--------------------------------------------------

Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)