Guten Abend.
Mein Name lautet MiX(eP).
Ich zeig euch wie man mit MySQL R39-3 ein Register/Login System baut!
Nun, fangen wir mal damit an.
Was benötigen wir? :
- Das MySQL-Plugin: https://github.com/pBlueG/SA-MP-MySQL/releases
Das Whirlpool-Plugin: http://forum.sa-mp.com/showthread.php?t=570945
Den 0.3.7 Windows Server + den Clienten von SA-MP: http://www.sa-mp.com/download.php
Eine Datenbank zum Ausprobieren
Grundkenntnisse
Ihr fügt alles in dem Script ordner Rein (Plugins, Includes.) und fügt dann auch die Namen der Plugins in die Server.cfg ein.
Der Scripting-Part:
Als erstes erstellen wir uns ein Static, das sollte so aussehen:
static
Handle,
Name[MAX_PLAYERS][24],
IP[MAX_PLAYERS][16]
;
Dann müssen wir ja noch unsere Daten angeben. Das machen wir so:
#define M_HOST "Host"
#define M_USER "Benutzer"
#define M_DATA "Datenbank"
#define M_PASS "Passwort"
Wie kann man nun sein Script mit der Datenbank verbinden? Dazu nutzen wir mysql_connect:
http://wiki.sa-mp.com/wiki/MySQL/R33#mysql_connect
Handle = mysql_connect(M_HOST, M_USER, M_DATA, M_PASS);
So aber am besten sollte man sich 2 Sachen vergewissern, 1. Das die Verbindung steht, 2. Das der Verlauf geloggt wird.
Um zu wissen, das die Verbindung steht müssen wir mit der Funktion mysql_errno Arbeiten.
http://wiki.sa-mp.com/wiki/MySQL/R33#mysql_errno
Beispiel:
if(mysql_errno(Handle) != 0)
{
print("[M_CONNECTION] >> Die Verbindung zur Datenbank ist Fehlgeschlagen! << [M_CONNECTION]");
}
else
{
printf("[M_CONNECTION] >> Die Verbindung zur Datenbank %s wurde Erfolgreich Hergestellt! << [M_CONNECTION]",M_DATA);
}
Jetzt gucken wir mal, wie wir die Datei "mysql_log" erstellen, dazu nutzen wir mysql_log :
http://wiki.sa-mp.com/wiki/MySQL/R33#mysql_log
mysql_log(LOG_ERROR | LOG_WARNING | LOG_DEBUG);
OnGamemodeInit sollte nun so aussehen:
public OnGameModeInit()
{
//===[ M_Connection ]===//
mysql_log(LOG_ERROR | LOG_WARNING | LOG_DEBUG);
Handle = mysql_connect(M_HOST, M_USER, M_DATA, M_PASS);
if(mysql_errno(Handle) != 0)
{
print("[M_CONNECTION] >> Die Verbindung zur Datenbank ist Fehlgeschlagen! << [M_CONNECTION]");
}
else
{
printf("[M_CONNECTION] >> Die Verbindung zur Datenbank %s wurde Erfolgreich Hergestellt! << [M_CONNECTION]",M_DATA);
}
return 1;
}
So nun gehen wir zu OnPlayerConnect, das haben wir nun auch, nun kommt der Richtige Scripting-Teil:
als erstes machen wir eine Schleife die, die Spieler durchgeht. Das sieht dann so aus:
for(new i; SpielerDaten:i < SpielerDaten; i++)
{
SpielerInfo[playerid][SpielerDaten:i] = 0;
}
Gut. nun setzen wir den Spieler auf Unregistriert, das machen wir so:
IstRegistriert[playerid] = 0;
Jetzt erstellen wir einen Query, der Abfragt ob ein Eintrag
in der Datenbank existiert, vorher Fragen wir aber noch den Namen und die IP des Spielers ab. Das geht so:
GetPlayerName(playerid, Name[playerid], 24);
GetPlayerIp(playerid, IP[playerid], 16);
Nun zu den Querys, erstellt eine Variable die so aussieht:
new Query[128];
nun Formatieren wir etwas das sieht dann so aus ( Beispiel! wird noch befüllt
format(query, sizeof(query), "..", ..);
nun der Format, wie er aussehen Sollte:
mysql_format(Handle, Query, sizeof(Query), "SELECT * FROM `Spieler` WHERE `Spielername` = '%e' LIMIT 1", Name[playerid]);
mysql_tquery(Handle, Query, "OnAccountCheck", "i", playerid);
Nun das ist fertig, jetzt gehen wir zu OnPlayerDisconnect und schreiben folgendes:
if(IstRegistriert[playerid] != 0)
{
SpielerSpeichern(playerid);
}
Nun erstellen wir unser Public "OnAccountCheck", dazu schreiben wir oben erst noch:
forward OnAccountCheck(playerid);
forward OnAccountLoad(playerid);
forward OnAccountRegister(playerid);
und:
#define D_REGISTER 1
#define D_LOGIN 2
Jetzt legen wir mit OnAccountCheck los. Wir arbeiten mit cache_get_data, das soll nun so aussehen:
http://wiki.sa-mp.com/wiki/MySQL/R33#cache_get_data
public OnAccountCheck(playerid)
{
new Rows, Fields;
cache_get_data(Rows, Fields, Handle);
if(Rows)
{
Jetzt arbeiten wir weiter mit cache_get_field_content:
http://wiki.sa-mp.com/wiki/MySQL/R33#cache_get_field_content
new oldIP[16];
cache_get_field_content(0, "IP", oldIP, Handle, 16);
GetPlayerIp(playerid, oldIP, 16);
IstRegistriert[playerid] = 1;
if(strlen(IP[playerid]) != 0 && !strcmp(IP[playerid], oldIP, true))
{
OnAccountLoad(playerid);
}
else
{
cache_get_field_content(0, "Passwort", SpielerInfo[playerid][Passwort], Handle, 129);
SpielerInfo[playerid][ID] = cache_get_field_content_int(0, "ID");
printf("%s", SpielerInfo[playerid][Passwort]);
ShowPlayerDialog(playerid, D_LOGIN, DIALOG_STYLE_INPUT, "Login", "Dein Account wurde gefunden. Bitte gib nun dein Passwort ein:","Einloggen","Abbrechen");
}
}
else
{
ShowPlayerDialog(playerid, D_REGISTER, DIALOG_STYLE_INPUT, "Registrieren","Dein Account wurde nicht gefunden! Bitte gib nun dein gewünschtes Passwort ein:","Registrieren","Abbrechen");
}
return 1;
}
Nun sollte unser Public so aussehen:
public OnAccountCheck(playerid)
{
new Rows, Fields;
cache_get_data(Rows, Fields, Handle);
if(Rows)
{
new oldIP[16];
cache_get_field_content(0, "IP", oldIP, Handle, 16);
GetPlayerIp(playerid, oldIP, 16);
IstRegistriert[playerid] = 1;
if(strlen(IP[playerid]) != 0 && !strcmp(IP[playerid], oldIP, true))
{
OnAccountLoad(playerid);
}
else
{
(!strlen(IP[playerid]) || strcmp(IP[playerid], NewIP, true));
cache_get_field_content(0, "Passwort", SpielerInfo[playerid][Passwort], Handle, 129);
SpielerInfo[playerid][ID] = cache_get_field_content_int(0, "ID");
printf("%s", SpielerInfo[playerid][Passwort]);
ShowPlayerDialog(playerid, D_LOGIN, DIALOG_STYLE_INPUT, "Login", "Dein Account wurde gefunden. Bitte gib nun dein Passwort ein:","Einloggen","Abbrechen");
}
}
else
{
ShowPlayerDialog(playerid, D_REGISTER, DIALOG_STYLE_INPUT, "Registrieren","Dein Account wurde nicht gefunden! Bitte gib nun dein gewünschtes Passwort ein:","Registrieren","Abbrechen");
}
return 1;
}
So nun müssen wir zum dem Callback was für die Antwort, es eines Buttons von einem Dialog ist. Eine sogenannte Response.
Das Callback nennt sich OnDialogResponse, Dazu fragen wir die jeweilige Dialog-ID ab, das erledigen wir so:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case D_LOGIN:
{
if(!response) Kick(playerid);
new H_Pass[129];
new Query[100];
WP_Hash(H_Pass, 129, inputtext);
if(strlen(H_Pass) && !strcmp(H_Pass, SpielerInfo[playerid][Passwort]))
{
mysql_format(Handle, Query, sizeof(Query), "SELECT * FROM `Spieler` WHERE `Spielername` = '%e' LIMIT 1", Name[playerid]);
mysql_tquery(Handle, Query, "OnAccountLoad", "i", playerid);
}
else
{
ShowPlayerDialog(playerid, D_LOGIN, DIALOG_STYLE_INPUT, "Login", "Dein Account wurde gefunden. Bitte gib nun dein Passwort ein\nFalsches Passwort!", "Einloggen", "Abbrechen");
}
}
Nun fangen wir weiter an mit dem Dialog: D_REGISTER:
case D_REGISTER:
{
if(!response) return Kick(playerid);
if(strlen(inputtext) < 6) return ShowPlayerDialog(playerid, D_REGISTER, DIALOG_STYLE_INPUT, "Register", "Dein Account wurde nicht gefunden! Bitte gib nun dein gewünschtes Passwort ein.\nDein Passwort muss länger als 6 Zeichen sein!", "Registrieren", "Abbrechen");
new Query[300];
WP_Hash(SpielerInfo[playerid][Passwort], 129, inputtext);
mysql_format(Handle, Query, sizeof(Query), "INSERT INTO `Spieler` (`Spielername`, `Passwort`, `IP`, `Admin`, `VIP`,`Morde`,`Tode`,`Level`, `Geld`) VALUES ('%e', '%s', '%s', 0, 0, 0, 0, 0, 10000)", Name[playerid], SpielerInfo[playerid][Passwort], IP[playerid]);
mysql_tquery(Handle, Query, "OnAccountRegister", "i", playerid);
}
}
return 1;
}
Nun sollte auch dieses Public so aussehen:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case D_LOGIN:
{
if(!response) Kick(playerid);
new H_Pass[129];
new Query[100];
WP_Hash(H_Pass, 129, inputtext);
if(!strcmp(H_Pass, SpielerInfo[playerid][Passwort]))
{
mysql_format(Handle, Query, sizeof(Query), "SELECT * FROM `Spieler` WHERE `Spielername` = '%e' LIMIT 1", Name[playerid]);
mysql_tquery(Handle, Query, "OnAccountLoad", "i", playerid);
}
else
{
ShowPlayerDialog(playerid, D_LOGIN, DIALOG_STYLE_INPUT, "Login", "Dein Account wurde gefunden. Bitte gib nun dein Passwort ein\nFalsches Passwort!", "Einloggen", "Abbrechen");
}
}
case D_REGISTER:
{
if(!response) return Kick(playerid);
if(strlen(inputtext) < 6) return ShowPlayerDialog(playerid, D_REGISTER, DIALOG_STYLE_INPUT, "Register", "Dein Account wurde nicht gefunden! Bitte gib nun dein gewünschtes Passwort ein.\nDein Passwort muss länger als 6 Zeichen sein!", "Registrieren", "Abbrechen");
new Query[300];
WP_Hash(SpielerInfo[playerid][Passwort], 129, inputtext);
mysql_format(Handle, Query, sizeof(Query), "INSERT INTO `Spieler` (`Spielername`, `Passwort`, `IP`, `Admin`, `VIP`,`Morde`,`Tode`,`Level`, `Geld`) VALUES ('%e', '%s', '%s', 0, 0, 0, 0, 0, 50000)", Name[playerid], SpielerInfo[playerid][Passwort], IP[playerid]);
mysql_tquery(Handle, Query, "OnAccountRegister", "i", playerid);
}
}
return 1;
}
So, nun braucht ihr noch ein Native, und zwar dieses:
native WP_Hash(buffer[], len, const str[]);
Nun brauchen wir noch das Public "OnAccountLoad" und "OnAccountRegister".
Die erstellen wir so:
OnAccountLoad:
public OnAccountLoad(playerid)
{
new Score;
SpielerInfo[playerid][Admin] = cache_get_field_content_int(0, "Admin");
SpielerInfo[playerid][VIP] = cache_get_field_content_int(0, "VIP");
SpielerInfo[playerid][Geld] = cache_get_field_content_int(0, "Geld");
SpielerInfo[playerid][Morde] = cache_get_field_content_int(0,"Morde");
SpielerInfo[playerid][Tode] = cache_get_field_content_int(0, "Tode");
Score = cache_get_field_content_int(0, "Level");
SetPlayerScore(playerid, Score);
GivePlayerMoney(playerid, SpielerInfo[playerid][Geld]);
SendClientMessage(playerid, -1, "Du hast dich Erfolgreich Eingeloggt!");
return 1;
}
OnAccountRegister:
public OnAccountRegister(playerid)
{
SpielerInfo[playerid][ID] = cache_insert_id();
printf("Neuer Account Registriert | ID: %d", SpielerInfo[playerid][ID]);
SpielerInfo[playerid][Geld] = 10000;
GivePlayerMoney(playerid, 10000);
IstRegistriert[playerid] = 1;
return 1;
}
Wie können wir nun den Spieler Speichern? Wir machen das per Stock! Hier ein Beispiel das funktionsfähig ist. :
stock SpielerSpeichern(playerid)
{
new Query[256];
mysql_format(Handle, Query, sizeof(Query), "UPDATE `Spieler` SET `IP`='%s', `Admin`=%d, `VIP`=%d, `Morde`=%d, `Tode`=%d, `Level`=%d, `Geld`=%d WHERE `ID`=%d",\
IP[playerid], SpielerInfo[playerid][Admin], SpielerInfo[playerid][VIP], SpielerInfo[playerid][Morde], SpielerInfo[playerid][Tode], GetPlayerScore(playerid), SpielerInfo[playerid][Geld], SpielerInfo[playerid][ID]);
mysql_tquery(Handle, Query, "", "");
}
Jetzt fehlen uns noch Folgende Sachen:
new IstRegistriert[MAX_PLAYERS];
enum SpielerDaten
{
ID,
Passwort[129],
Admin,
VIP,
Morde,
Tode,
Level,
Geld
}
new SpielerInfo[MAX_PLAYERS][SpielerDaten];
So das war es auch schon! Hoffe es hat euch gefallen
Hier ist die Datenbank fürs ganze!
Datenbank: http://www.file-upload.net/dow…10580092/Spieler.sql.html
Hinweis! : Durch kopieren lernt ihr kein Scripten, deswegen lest es euch durch! Und versucht es mal. Scripten kann Jeder wenn er es nur Möchte!