Coding
Da wir jetzt die Verbindung aufgebaut haben, können wir mit dem eigentlich wichtigen Teil beginnen, nämlich dem Speichersystem für die Benutzer Deines Servers, schließlich sollen deren Daten ja gespeichert werden. Hierzu benötigen wir diverse Code-Teile, die ich im folgenden Abschnitt erkläre. Wir gehen chronologisch vom Betreten des Servers bis zum Verlassen des Servers vor, und beginnen bei der Deklaration der Variablen.
Um die Daten zur Laufzeit temporär zu speichern, ohne jedes mal auf die Datenbank zugreifen zu müssen legen wir ein Array mit den Spielerdaten an. Für eine komfortablere Bedienung nutzen wir ein Enum. Füge hierzu unter den Includes - also ganz oben in Deinem Gamemode/Filterscript - diese Deklaration ein:
enum pDataEnum
{
p_id,
bool:pLoggedIn,
pName[MAX_PLAYER_NAME],
pLevel,
pMoney,
pKills,
pDeaths
}
new PlayerInfo[MAX_PLAYERS][pDataEnum];
Alles anzeigen
Anschließend gehst Du zu OnPlayerConnect. Wenn der Spieler den Server betritt, dann soll er initialisiert werden, sprich die Variablen werden sicherheitshalter zurückgesetzt. Dazu benötigst Du diesen Code:
public OnPlayerConnect(playerid)
{
PlayerInfo[playerid][p_id] = 0;
PlayerInfo[playerid][pLoggedIn] = false;
PlayerInfo[playerid][pLevel] = 0;
PlayerInfo[playerid][pMoney] = 0;
PlayerInfo[playerid][pKills] = 0;
PlayerInfo[playerid][pDeaths] = 0;
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
return 1;
}
Alles anzeigen
Als nächstes kommt der Spieler in die Class-Selection. Hier wird OnPlayerRequestClass aufgerufen. Dort fragen wir in der Datenbank ab, ob der Spieler bereits registriert ist. Dies geht so:
public OnPlayerRequestClass(playerid)
{
//Wenn der Spieler die Class-Selection betritt prüfe, ob er bereits eingeloggt ist
if(!PlayerInfo[playerid][pLoggedIn])
{
//Wenn nicht, dann prüfe ob der Spieler ein Konto hat
//Dazu wird ein Query gesendet und ein neues Callback aufgerufen
//%e steht für einen geprüften String (sollte anstatt %s in Queries verwendet werden)
new query[128];
mysql_format(handle, query, sizeof(query), "SELECT id FROM users WHERE name = '%e'", PlayerInfo[playerid][pName]);
//Das Query wird abgesendet und die playerid an OnUserCheck übergeben
mysql_pquery(handle, query, "OnUserCheck", "d", playerid);
}
return 1;
}
Alles anzeigen
Außerdem benötigen wir nun das Callback OnUserCheck, welches Du am besten ganz unten in Deinem Gamemode/Filterscript einfügst.
forward OnUserCheck(playerid);
public OnUserCheck(playerid)
{
//Query wurde ausgeführt und das Ergebnis im Cache gespeichert
if(cache_get_row_count() == 0)
{
//Der Spieler konnte nicht gefunden werden, er muss sich registrieren
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", "Bitte registriere Dich:", "Ok", "Abbrechen");
}
else
{
//Es existiert ein Ergebnis, das heißt der Spieler ist registriert und muss sich einloggen
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmeldung", "Bitte logge Dich ein:", "Ok", "Abbrechen");
}
return 1;
}
Alles anzeigen
Damit der Code ohne Fehler kompiliert, musst Du unter den Includes die beiden Dialoge definieren:
//Dialog IDs (gegebenenfalls ändern, falls bereits belegt)
#define DIALOG_REGISTER 1403
#define DIALOG_LOGIN 2401
Da dem Spieler nun Dialoge angezeigt werden benötigst Du das Callback OnDialogResponse. Dort trägst Du ein, was passiert, wenn der Spieler sich registrieren oder einloggen will, je nach dem welchen Dialog der Spieler angezeigt bekommen hat.
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
if(dialogid == DIALOG_REGISTER)
{
//Spieler hat Abbrechen gewählt
if(!response) return Kick(playerid);
//Wenn der Spieler kein, oder ein zu kurzes, Passwort eingegeben hat
if(strlen(inputtext) < 3) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", "Bitte registriere Dich:\n{FF0000}Mindestens 3 Zeichen!", "Ok", "Abbrechen");
//Wenn alles passt wird der Spieler in der Datenbank angelegt
//Als Verschlüsselung für das Passwort wird MD5 verwendet
new query[256];
mysql_format(handle, query, sizeof(query), "INSERT INTO users (name, password) VALUES ('%e', MD5('%e'))", PlayerInfo[playerid][pName], inputtext);
//Das Query wird abgesendet und die playerid an OnUserRegister übergeben
mysql_pquery(handle, query, "OnUserRegister", "d", playerid);
return 1;
}
if(dialogid == DIALOG_LOGIN)
{
//Spieler hat Abbrechen gewählt
if(!response) return Kick(playerid);
//Wenn der Spieler kein, oder ein zu kurzes, Passwort eingegeben hat
if(strlen(inputtext) < 3) return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmeldung", "Bitte logge Dich ein:\n{FF0000}Mindestens 3 Zeichen!", "Ok", "Abbrechen");
//Wenn alles passt wird die Datenbank ausgelesen
new query[256];
mysql_format(handle, query, sizeof(query), "SELECT * FROM users WHERE name = '%e' AND password = MD5('%e')", PlayerInfo[playerid][pName], inputtext);
//Das Query wird abgesendet und die playerid an OnUserLogin übergeben
mysql_pquery(handle, query, "OnUserLogin", "d", playerid);
return 1;
}
return 0;
}
Alles anzeigen
Auch hier benötigst Du die beiden neuen Callbacks, die Du wieder ganz unten in Deinem Gamemode/Filterscript einfügst:
forward OnUserRegister(playerid);
public OnUserRegister(playerid)
{
//Der Spieler wurde in die Datenbank eingetragen, es wird die id ausgelesen
PlayerInfo[playerid][p_id] = cache_insert_id();
SendClientMessage(playerid, 0x00FF00FF, "[Konto] Registration erfolgreich.");
return 1;
}
forward OnUserLogin(playerid);
public OnUserLogin(playerid)
{
//Query wurde ausgeführt und das Ergebnis im Cache gespeichert
if(cache_get_row_count() == 0)
{
//Der Spieler hat ein falsches Passwort eingegeben
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Anmeldung", "Bitte logge Dich ein:\n{FF0000}Falsches Passwort!", "Ok", "Abbrechen");
}
else
{
//Es existiert ein Ergebnis, das heißt der Spieler hat das richtige Passwort eingegeben
//Wir lesen nun die erste Zeile des Caches aus (ID 0)
PlayerInfo[playerid][p_id] = cache_get_field_content_int(0, "id", handle);
PlayerInfo[playerid][pLevel] = cache_get_field_content_int(0, "level", handle);
PlayerInfo[playerid][pMoney] = cache_get_field_content_int(0, "money", handle);
PlayerInfo[playerid][pKills] = cache_get_field_content_int(0, "kills", handle);
PlayerInfo[playerid][pDeaths] = cache_get_field_content_int(0, "deaths", handle);
PlayerInfo[playerid][pLoggedIn] = true;
SendClientMessage(playerid, 0x00FF00FF, "[Konto] Eingeloggt.");
GivePlayerMoney(playerid, PlayerInfo[playerid][pMoney]);
}
return 1;
}
Alles anzeigen
So, jetzt hast Du es fast geschafft. Es fehlt nur noch die Speicherung der Spielerdaten, wenn der Spieler den Server wieder verlässt.
public OnPlayerDisconnect(playerid, reason)
{
//Speichere den Spieler wenn er der Server verlässt
SaveUserStats(playerid);
return 1;
}
Für die Speicherung nutzen wir dann diese Funktion:
stock SaveUserStats(playerid)
{
//Wenn der Spieler nicht eingeloggt ist, dann speichere seine Statistiken nicht
if(!PlayerInfo[playerid][pLoggedIn]) return 1;
//Ansonsten speichere sie
new query[256];
mysql_format(handle, query, sizeof(query), "UPDATE users SET level = '%d', money = '%d', kills = '%d', deaths = '%d' WHERE id = '%d'",
PlayerInfo[playerid][pLevel], PlayerInfo[playerid][pMoney], PlayerInfo[playerid][pKills], PlayerInfo[playerid][pDeaths], PlayerInfo[playerid][p_id]);
//Das Query wird abgesendet
mysql_pquery(handle, query);
return 1;
}
Alles anzeigen
Damit wären wir so gut wie durch. Um die Funktionen auch testen zu können schreiben wir noch etwas bei OnPlayerDeath rein:
public OnPlayerDeath(playerid, killerid, reason)
{
//Beispielcode
if(killerid != INVALID_PLAYER_ID)
{
PlayerInfo[killerid][pKills]++;
GivePlayerMoney(killerid, 10);
PlayerInfo[killerid][pMoney] += 10;
if(PlayerInfo[killerid][pKills] > 3)
{
PlayerInfo[killerid][pLevel] = 1;
}
}
PlayerInfo[playerid][pDeaths]++;
return 1;
}
Alles anzeigen
Damit sind wir durch. Kompiliere Deinen Code und starte den Server neu.
Der Spieler kann sich nun registrieren, einloggen und seine Statistiken werden beim Verlassen des Servers gespeichert. Die Statistiken kannst Du gegebenenfalls auch in einem Timer oder in einem Befehl speichern lassen, das bleibt Dir überlassen.
Wenn der Spieler nun den Server betritt, dann wird ihm der Register-/Login-Dialog angezeigt.
In der Datenbank sieht ein neuer Spieler nach der Registration so aus:

Und nachdem er ein paar Dinge gemacht hat und den Server verlässt, sieht es so aus:

Aktualisiere (F5), falls nötig, die Ansicht, damit die Daten korrekt angezeigt werden.
Dieses Register-/Login-System kannst Du nun nach Belieben ausbauen, da es ja noch recht spartanisch ist. Aber Du weißt jetzt wie es geht und kannst Dich ohne Probleme durch die Materie arbeiten.