Hallo alle zusammen und Willkommen zu meinem 3. Tutorial.
Hier möchte ich euch erklären, wie ihr ein auf Dialogen aufgebauetes Login-/Registersystem mit einer ingame Passwort-vergessen Funktion schreiben könnt.
Ich weiß natürlich, dass es genug Tutorials zu dialogbezogenen Login-/Registersystemen auf Dini gibt, deshalb werde ich auf diese Punkte garnicht allzu viel näher eingehen, sondern eher das Hauptaugenmerk auf die eben angemerkte "Sonderfunktion" legen.
Ablauf
- Spieler registriert sich mit Passwort, geheimer Frage & geheimer Antwort.
- Spieler vergisst sein Passwort und gibt ingame /passwortvergessen ein.
- Spieler gibt die Antwort auf seine geheime Frage ein.
- Wenn richtig wird ein neues Passwort (zufällig aus einer Liste vorgegebener Passwörter) erstellt und ihm zugewiesen.
- Spieler kann sich mit diesem Passwort einloggen und danach mit /pwändern ein neues zuweisen.
Dann fangen wir mal an. Das erste was wir benötigen sind die Defines der Dialoge- Nicht zu vergessen natürlich die implementierte Dini-Include, was ihr aber wissen solltet.
#define login 1
#define register1 2
#define register2 3
#define register3 4
#define lostpw 5
#define pwchange 6
Kurze Erklärung: login ist unser Dialog für den Login. In register1 gibt man sein Passwort ein, in register2 kann man seine geheime Frage wählen und in register3 die Antwort dazu eintragen. lostpw ist natürlich dann der Dialog um die Antwort abzufragen. Und zu guter letzt kommt pwchange was den Dialog zum Ändern des Passwortes darstellt.
Als nächstes wollen wir eine Liste mit Passwörtern erstellen, die dem Nutzer zufällig zugewiesen werden.
new lostpws[][] =
{
"Ivamdub",
"gimfves",
"Fb53Ac",
"Every90",
"Deutschland",
"Gefaafny",
"Ftgenrl",
"Oranan",
"Lituania",
"UwAff3",
"fhhalc",
"fhn76",
"75hd",
"a7jvjmz",
"fsdhr"
};
In diesem Fall sind es 15 Passwörter. Diese Zahl müssen wir uns für später noch merken. Welche Passwörter ihr verwendet ist grundsätzlich egal, ich hab im Moment einfach mal ein paar Nonsense-Wörter eingetragen.
Nun gehen wir zum Callback OnPlayerConnect, wo wir überprüfen ob der Spieler registriert ist und ihm dementsprechend schreiben ob er sich einloggen oder registrieren soll.
new name[MAX_PLAYER_NAME], path[128];
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
format(path, 128, "/spieler/%s.ini", name);
if(dini_Exists(path)) SendClientMessage(playerid, COLOR_ORANGE, "Willkommen zurück! Logge dich bitte mit /login ein.");
else SendClientMesssage(playerid, COLOR_ORANGE, "Willkommen auf unserem Server. Du bist noch nicht registriert. Erledige das bitte mit /register.");
Das sollte es für den Moment tun. Zuerst erstellen wir den Pfad zur Spielerdatei im Userfiles-Ordner (Pfad auf jeden Fall erstellen. In diesem Fall den Ordner "spieler"!) und überprüfen dann ob eine Datei mit dem Namen des Spielers bereits existiert. Wenn ja, geben wir ihm die Nachricht zum einloggen, ansonsten zum registrieren. COLOR_ORANGE muss natürlich auch als solche definiert sein.
Jetzt geht es zu den eigentlichen Commands unter OnPlayerCommandText.
if (strcmp(cmd, "/login", true) == 0)
{
new name[MAX_PLAYER_NAME], path[128];
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
format(path, 128, "/spieler/%s.ini", name);
if(dini_Exists(path)) ShowPlayerDialog(playerid, login, DIALOG_STYLE_INPUT, "Bitte einloggen.", "Willkommen zurück auf unserem Server.\r\nBitte logge dich ein.", "Annehmen", "Abbrechen");
else SendClientMessage(playerid, COLOR_RED, "Du bist noch nicht registriert. Bitte erledige das mit /register.");
return 1;
}
if (strcmp(cmd, "/register", true) == 0)
{
new name[MAX_PLAYER_NAME], path[128];
GetPlayerName(playerid, name, MAX_PLAYER_NAME);
format(path, 128, "/spieler/%s.ini", name);
if(!dini_Exists(path)) ShowPlayerDialog(playerid, register1, DIALOG_STYLE_INPUT, "Registrierung.", "Willkommen auf unserem Server.\r\nBitte gib hier dein gewünschtes Passwort ein (nachträglich änderbar).", "Weiter", "Abbrechen");
else SendClientMessage(playerid, COLOR_RED, "Du bist bereits registriert. Bitte logge dich mit /login ein");
return 1;
}
if (strcmp(cmd, "/pwändern", true) == 0)
{
if(GetPVarInt(playerid, "loggedin") == 1)
{
ShowPlayerDialog(playerid, pwchange, DIALOG_STYLE_INPUT, "Passwort ändern", "Bitte gebe hier dein gewünschtes neues Passwort ein.", "Annehmen", "Abbrechen");
}
else SendClientMessage(playerid, COLOR_RED, "Du bist nicht eingeloggt.");
return 1;
}
Wie ihr seht habe ich gleich alle 3 Commands die wir brauchen werden eingetragen. Kurze Erklärung zu den einzelnen:
/login - Der Pfad der Spielerdatei wird gesucht. Wenn er existiert, wird der Dialog zum Login aufgerufen, ansonsten der Verweis auf /register.
/register - Der Pfad der Spielerdatei wird gesucht. Wenn er nicht existiert, wird der Dialog zum Register aufgerufen, ansonsten der Verweis auf /login.
/pwändern - Es wird überprüft ob der Spieler eingeloggt ist (Durch PVar, welche später beim Login gesetzt wird). Wenn dem so ist, wird der Login zum Passwortändern aufgerufen.
Das war es zum leichten Teil. Nun kommen die Dialogabfragen. Anfangen tun wir diesmal auch mit dem Login. Wir setzen den Code in OnDialogResponse.
new name[MAX_PLAYER_NAME], path[128];
GetPlayerName(playerid, name, MAX_PLAYER_NAME];
format(path, 128, "/spieler/%s.ini", name);
if(dialogid == login && response)
{
new pw[256];
pw = dini_Get(path, "PW");
if(strcmp(pw, inputtext)) SendClientMessage(playerid, COLOR_RED, "Das eingegebene Passwort ist falsch.");
else
{
SetPVarInt(playerid, "loggedin", 1);
// Was immer nun passieren soll
}
return 1;
}
Da wir den Pfad der Spielerdatei nun öfter benutzen, schreibe ich ihn nicht jedes Mal neu, sondern einfach lokal für das gesamte Callback.
Eigentlich ganz leicht. Zuerst überprüfen wir ob die Dialogid Login ist und eine Antwort (Button "Akzeptieren" gedrückt) gegeben wurde. Danach holen wir uns das Passwort des Spielers aus der Dini-Datei und speichern es in der Variable pw. Wenn pw und der eingegebene Text nicht gleich sind, wird die Nachricht gesendet, ansonsten wird die PVar "loggedin" auf 1 gesetzt und ihr könnt tun was immer ihr nun tun möchtet.
Jetzt zu den einzelnen register-Dialogen, welche auch in OnDialogResponse gesetzt werden.
if(dialogid == register1 && response)
{
dini_Create(path);
dini_Set(path, "PW", inputtext);
ShowPlayerDialog(playerid, register2, DIALOG_STYLE_LIST, "Geheime Frage auswählen", "Wie ist der Name deiner Mutter?\r\nWie heißt dein Haustier?\r\nWo bist du geboren?", "Weiter", "Abbrechen");
return 1;
}
if(dialogid == register2)
{
if(!response) dini_Remove(path);
else
{
switch(listitem)
{
case 0:
{
dini_Set(path, "Frage", "Mutter");
ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, wie deine Mutter heißt.", "Akzeptieren", "Abbrechen");
}
case 1:
{
dini_Set(path, "Frage", "Haustier");
ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, wie dein Haustier heißt.", "Akzeptieren", "Abbrechen");
}
case 2:
{
dini_Set(path, "Frage", "Geburtsort");
ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, was dein Geburtsort ist.", "Akzeptieren", "Abbrechen");
}
}
}
return 1;
}
if(dialogid == register3)
{
if(!response) dini_Remove(path);
else
{
dini_Set(path, "Antwort", inputtext);
SendClientMessage(playerid, COLOR_GREEN, "Herzlichen Glückwunsch! Du bist nun erfolgreich auf unserem Server registriert.");
}
return 1;
}
Das sieht auf den ersten Blick vielleicht etwas wirr aus, ist aber eigentlich ganz einfach. Im ersten Teil (register1) wird die Dini-Datei erstellt und das eingegebene Passwort dort hinein geschrieben. Danach wird der Dialog register2 als ListBox geöffnet, in dem man seine geheime Frage auswählen kann (Momentan Name der Mutter, - des Haustieres und Geburtsort, natürlich beliebig erweiterbar).
Wenn dieser abgebrochen wird, wird die Dini wieder gelöscht, ansonsten wird durch einen switch die Frage (oder zumindest eine Kurzform davon) in die Dini gespeichert und gleichzeitig der neue Dialog gestartet.
Wenn dieser abgebrochen wird, wird die Dini natürlich auch wieder gelöscht. Falls nicht, wird die Antwort auch in die Dini geschrieben und die Nachricht, dass man nun erfolgreich registriert ist, wird wiedergegeben.
Nun fehlt es uns eigentlich nurnoch an 2 Dialogen, dann sind wir fertig. Das ist einmal der Dialog für das vergessene Passwort und zum Ändern des Passwortes.
if(dialogid == lostpw && response)
{
new answer[256];
answer = dini_Get(path, "Antwort");
if(!strcmp(answer,inputtext))
{
dini_Set(path, "PW", lostpws[random(15)]);
new string[128], pw[256];
pw = dini_Get(path, "PW");
format(string, 128, "Dir wurde das Passwort \"%s\" zugeteilt. Ändere dies bitte nach dem Login mit /pwändern.", pw);
SendClientMessage(playerid, COLOR_GREEN, string);
}
else SendClientMessage(playerid, COLOR_RED, "Deine Antwort war nicht korrekt.");
return 1;
}
Hier läuft das ganze eigentlich auch recht einfach ab. Beim vergessenen Passwort wird zuerst die Antwort aus der Dini geladen und überprüft, ob sie mit der eingegebenen Antwort übereinstimmt. Ansonsten wird eine Nachricht ausgegeben. Wenn dem allerdings der Fall ist, dann wird aus dem Array lostpws den wir oben ja mit unseren Passwörtern definiert haben ein zufälliges von der Zahl 1-15 rausgepickt. Deshalb sollten wir uns die 15 merken. Wenn ihr 20 Passwörter eintragt, müsst ihr dies nämlich auf 20 ändern. Dieses Passwort wird in der Dini gespeichert und danach abgefragt. Wenn das Speichern nicht geklappt haben sollte, steht nun nochmal das alte Passwort da, das ja noch in der Dini eingetragen wäre.
if(dialogid == pwchange && response)
{
new string[128];
dini_Set(path, "PW", inputtext);
format(string, 128, "Dein Passwort wurde erfolgreich auf \"%s\" geändert.", inputtext);
SendClientMessage(playerid, COLOR_GREEN, string);
return 1;
}
Nun, das ist wohl der leichteste Dialog. Zuerst wird das neue Passwort gespeichert, dann die Nachricht formatiert und dem Spieler gesendet.
Achtung: Die Passwörter werden unverschlüsselt gespeichert und deshalb von Hackern oder Leuten mit Zugriff auf den Server einsehbar. Wenn ihr Sicherheit wollt, müsst ihr noch MD5-Crypt o. andere Verschlüsselungsverfahren einbauen.
MD5: http://www.file-upload.net/download-3726477/md5.inc.html
Whirlpool: http://forum.sa-mp.com/showthread.php?t=65290
(Danke an Dudalus für die Links )
Das war es dann schon mit dem Tutorial. Ich hoffe es hat euch gefallen, geholfen und wenn ja- empfehlt es gerne weiter
Mit freundl. Grüßen
Padarom