Login Script (Der wohl einfachste & leichteste weg)

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
  • So hier die neue Version von meinem Tutorial wie ihr ein einfaches aber sicheres Login system erstellt.


    Wir brauchen als ersten das INI Plugin für SAMP was hier hier findet: >>> KLICK <<<


    Sobald wir das Plugin installiert haben, erstellen wir ein neuen Gamemode und includen die ini include datei mit


    #include <a_samp_ini>


    Als nächstes erstellen wir ein Spieler enum, das sollte so aussehen:


    enum PInfo
    {
    pPassword[16],
    pLevel,
    pMoney,
    Float:pX,
    Float:pY,
    Float:pZ,
    pIsPlayerLoggedIn
    }


    direkt unter unserm Spieler enum erstellen wir ein array + ein globalen string array wie folgt:
    new PlayerInfo[MAX_PLAYERS][PInfo];
    new str[128];


    als nächstes dirigieren wir zu dem "OnPlayerRequestSpawn" Callback und modifizieren es ein wenig, bis es so aussieht:
    public OnPlayerRequestSpawn(playerid)
    {
    if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 0)
    {
    SendClientMessage(playerid, 0xAAAAAAAA, "Du kannst nicht unangemeldet spawnen.");
    return 0;
    }
    return 1;
    }


    Erklärung: if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 0) Checkt ob der Spieler eingeloggt ist, ist der Spieler nicht eingeloggt Sendet er eine Chat nachricht und returnt 0, der return 0 verhindert das der Spieler spawnen kann solang die pIsPlayerLoggedIn variable 0 ist.


    Und nun suchen wir das OnPlayerSpawn Callback und fügen diesen Code ein:
    public OnPlayerSpawn(playerid)
    {
    if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 0)
    {
    // Die ist notwendig da man dank m0d s0beit unangemeldet spawnen kann. (Fragt nicht wie es geht, ich werde es euch nicht sagen.)
    format(str, sizeof(str), "%s wurde gekickt da er unangemeldet gespawn ist", GetPlayerNameEx(playerid));
    SendClientMessageToAll(COLOR_LIGHT_RED, str);
    return 0;
    }
    return 1;
    }
    Dieser abschnitt ist notwendig da man DANK mod so*eit ohne sich einzuloggen spawnen kann. sollte der spieler also unangemeldet spawnen, so wird er vom server gekickt.


    Wir fügen nun folgenden Makro unter den Includes ein:
    #define Command(%1) (!strcmp(cmdtext, %1, true, strlen(%1)) && strdel(cmdtext, 0, strlen(%1) + 1) == true)

    Diesen Makro brauchen wir da er die benutzen bei OnPlayerCommandText vereinfacht, und wir gehen nun zu unseren OnPlayerCommandText callback und bearbeiten es.


    public OnPlayerCommandText(playerid, cmdtext[])
    {
    if(Command("/login"))
    {
    if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 1) return SendClientMessage(playerid, COLOR_LIGHT_WHITE, "Du bist schon angemeldet.");
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    if(!fexist(str)) return SendClientMessage(playerid, COLOR_YELLOW, "Account wurde nicht gefunden, du kannst dich nicht einloggen.");
    new strPW[16];
    if(sscanf(cmdtext, "s", strPW)) return SendClientMessage(playerid, COLOR_LIGHT_WHITE, "[SERVER] Benutzung: /login [Passwort]");
    OnPlayerLogin(playerid, strPW);
    return 1;
    }

    if(Command("/register"))
    {
    if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 1) return SendClientMessage(playerid, COLOR_LIGHT_WHITE, "Du bist schon angemeldet.");
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    if(fexist(str)) return SendClientMessage(playerid, COLOR_YELLOW, "Account wurde gefunden, du kannst dich nicht registrieren.");
    new strPW[16];
    if(sscanf(cmdtext, "s", strPW)) return SendClientMessage(playerid, COLOR_LIGHT_WHITE, "[SERVER] Benutzung: /register [Passwort]");
    OnPlayerRegister(playerid, strPW);
    return 1;
    }
    return 0;
    }


    Die einzelnen Funktionen könnt ihr auf http://wiki.sa-mp.com sowieo http://wiki.sa-mp.de nachlesen, ich denke aber mal die dürften euch bekannt sein.
    Falls ihr nicht wisst was sscanf ist: hier die erklärung: >>> Klick <<<


    Wir erstellen nun ganz unten im Script ein neuen Callback namens:
    public OnPlayerRegister(playerid, password[])
    {
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    SaveString("Account", "Password", password, str);
    SaveInteger("Account", "Level", random(10), str);
    SaveInteger("Account", "Money", random(5000), str);
    SaveFloat("Account", "PosX", 1603.928466, str);
    SaveFloat("Account", "PosY", 1820.088500, str);
    SaveFloat("Account", "PosZ", 10.828001, str);

    SendClientMessage(playerid, COLOR_LIGHT_BLUE, "Du hast dich erfolgreich registriert, du wirst nun automatich eingeloggt.");
    OnPlayerLogin(playerid, password);

    return 1;
    }


    Dieser Callback wird aufgerufen sobald ein Spieler /register [Passwort] eingibt. Erklärungen zu den SaveFloat,Integer,String funktionen findet ihr in meinem Plugin Thread.


    Wir brauchen nun noch ein Login Callback:
    public OnPlayerLogin(playerid, password[])
    {
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    LoadString("Account", "Password", "0", PlayerInfo[playerid][pPassword], str);

    if(!strcmp(PlayerInfo[playerid][pPassword], password, false))
    {


    PlayerInfo[playerid][pLevel] = LoadInteger("Account", "Level", "0", str);
    PlayerInfo[playerid][pMoney] = LoadInteger("Account", "Money", "0", str);
    PlayerInfo[playerid][pX] = LoadFloat("Account", "PosX", "0.0", str);
    PlayerInfo[playerid][pY] = LoadFloat("Account", "PosY", "0.0", str);
    PlayerInfo[playerid][pZ] = LoadFloat("Account", "PosZ", "0.0", str);

    PlayerInfo[playerid][pIsPlayerLoggedIn] = 1;
    SpawnPlayer(playerid);
    SetPlayerScore(playerid, PlayerInfo[playerid][pLevel));
    GivePlayerMoney(playerid, PlayerInfo[playerid][pMoney]);
    SetPlayerPos(playerid, PlayerInfo[playerid][pX], PlayerInfo[playerid][pY], PlayerInfo[playerid][pZ);

    format(str, sizeof(str), "Willkommen zurück %s", GetPlayerNameEx(playerid));
    SendClientMessage(playerid, COLOR_WHITE, str);
    }else{
    SendClientMessage(playerid, COLOR_LIGHT_RED, "Das Passwort war nocht korrekt.");
    Kick(playerid);
    }
    return 1;
    }


    Erklärung: OnPlayerLogin lädt das Passwort als erstes aus der ini Datei, sollte das ausgelesene Passwort nicht mit dem eingegeben Passwort übereinstimmen, wird der User gekickt. sollte das Passwort doch übereinstimmen werden alle gespeicherten Daten auf den Splieler Enum zugewiesen.


    Jetzt brauchen wir noch ein Callback was alles Speichert sobald der Spieler den Server verlässt:
    public OnPlayerSave(playerid)
    {
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    SaveString("Account", "Password", PlayerInfo[playerid][pPassword], str);
    SaveInteger("Account", "Level", PlayerInfo[playerid][pLevel], str);
    SaveInteger("Account", "Money", PlayerInfo[playerid][pMoney], str);

    new Float:X, Float:Y, Float:Z
    GetPlayerPos(playerid, X, Y, Z);

    SaveFloat("Account", "PosX", X, str);
    SaveFloat("Account", "PosY", Y, str);
    SaveFloat("Account", "PosZ", Z, str);

    return 1;
    }


    Wir dirigieren nun zu dem OnPlayerDisconnect callback und bearbeiten es:
    public OnPlayerDisconnect(playerid, reason)
    {
    if(PlayerInfo[playerid][pIsPlayerLoggedIn] == 1)
    {
    OnPlayerSave(playerid);
    PlayerInfo[playerid][pPassword] = 0;
    PlayerInfo[playerid][pLevel] = 0;
    PlayerInfo[playerid][pMoney] = 0;
    PlayerInfo[playerid][pX] = 0.0;
    PlayerInfo[playerid][pY] = 0.0;
    PlayerInfo[playerid][pZ] = 0.0;
    PlayerInfo[playerid][pIsPlayerLoggedIn] = 0;
    }
    return 1;
    }


    Erklärung: Sollte ein Spieler eingeloggt sein, so werden alle Daten aus dem Spieler Enum gespeichert sobald der Spieler den Server verlässt, dabei spielt die Art des Disconnects keine rolle.
    Zur Sicherheit um Bugs zu vermeiden werden nach dem Speichern die gesammten Variablen aus dem Spieler Enum auf 0 gesetzt.


    Zu guter letzt müssten wir noch unsere GetPlayerNameEx und die sscanf Funktionen erstellen:
    stock GetPlayerNameEx(playerid)
    {
    new _NAME[MAX_PLAYER_NAME];
    GetPlayerName(playerid, _NAME, sizeof(_NAME));
    return _NAME;
    }


    Natührlich müssen wir unsere neuen 3 Callbacks auch forwarden, dazu schreiben wir folgendes einfach unter den Includes:
    forward OnPlayerLogin(playerid, password[]);
    forward OnPlayerRegister(playerid, password[]);
    forward OnPlayerSave(playerid);


    Das war es eigentlich auch schon, hoffe jetzt gibt es nicht mehr so viel zu meckern wegen meinem Tutorial.


    Hier der Link zum vollen Code: >>> Klick <<<


    Edit: Tutorial wurde komplett überarbeitet.
    Edit: Rechtschreibung

    SA-MP Scripting Hilfe/Erklärungen bekommt ihr auf der SA-MP Wikipedia

    4 Mal editiert, zuletzt von .#~Momo ()

  • Sieht aus als wäre es Dynamisch. Weil so in hinsicht kompliziert aussieth. Aber Trotz dem Nice


    10/10

  • Sieht ganz nett aus aber wäre es so nicht einacher?


    public OnPlayerLogin(playerid, password[])
    {
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));
    LoadString("Account", "Password", "0", PlayerInfo[playerid][pPassword], str);

    if(!strcmp(PlayerInfo[playerid][pPassword], password, false))
    {
    SpawnPlayer(playerid);
    PlayerInfo[playerid][pIsPlayerLoggedIn] = 1;
    SetPlayerScore(playerid, LoadInteger("Account", "Level", "0", str));
    GivePlayerMoney(playerid,LoadInteger("Account", "Money", "0", str));
    SetPlayerPos(playerid, LoadFloat("Account", "PosX", "0.0", str), LoadFloat("Account", "PosY", "0.0", str), LoadFloat("Account", "PosZ", "0.0", str));
    PlayerInfo[playerid][pIsPlayerLoggedIn] = 1;
    format(str, sizeof(str), "Willkommen zurück %s", GetPlayerNameEx(playerid));
    SendClientMessage(playerid, COLOR_WHITE, str);
    }else{
    SendClientMessage(playerid, COLOR_LIGHT_RED, "Das Passwort war nocht korrekt.");
    Kick(playerid);
    }
    return 1;
    }

  • Ob SpawnPlayer oben oder unten ist, das macht kein unterschied, ich selber erstelle lieber erst alle files und lass den spieler dann spawnen.


    Edit: aaaaaaaah, hab dein Code nicht durchgelesen, klar so geht es auch, aber dann hast du den Wert nicht in dem Spieler Enum, es gibt 2 wege, hier ein bsp. mit SetPlayerScore:


    New Score = LoadInteger("Account", "Score", "0", "Accounts\\Momo5000.ini");
    SetPlayerScore(playerid, Score);


    Oder einfach so:
    SetPlayerScore(playerid, LoadInteger("Account", "Score", "0", "Accounts\\Momo5000.ini");


    Der unterschied ist der, falls du ein Spieler Enum hast, wird der Wert dort nicht gespeichert, sondern du setzt den Spieler Score sofort auf den Wert, den er aus der INI bekommt.


    Weg 1 ist somit schon etwas besser, MFG

    SA-MP Scripting Hilfe/Erklärungen bekommt ihr auf der SA-MP Wikipedia

    Einmal editiert, zuletzt von .#~Momo ()

  • Aber bei
    new score =
    SetPlayerScore(playerid, score);
    wird ja auch nichts in eine gewisse Struktur gespeichert, damit wäre es nur Ressourcenverschwendung diese zwischenspeichern zu lassen ;)

  • Sieht aus als wäre es Dynamisch. Weil so in hinsicht kompliziert aussieth. Aber Trotz dem Nice
    10/10


    Ich übe mal Kritik. Es sieht nicht nur schwer aus, für Anfänger ist es das auch - daher könntest du ruhig das ganze erklären.
    Dann sind mir noch so zwei Dinge aufgefallen, einmal
    format(str, sizeof(str), "Accounts\\%s.ini", GetPlayerNameEx(playerid));

    müsste das nicht "Accounts/%s.ini heißen? Ansonsten hast du noch einen Rechtschreibfehler gemacht ;)

    Zitat

    SendClientMessage(playerid, COLOR_LIGHT_RED, "Das Passwort war nocht korrekt.");


    Lg ;)

  • Das ist doch kein Tutorial.. das ist garnichts..
    Das ist nur "hingeklatschter" code, der dazu nicht mal der einfachste weg ist...
    Wenn du keine lust hast, es zu erklären hast du auch keine Lust ein Tutorial zu schreiben, und somit hättest du dir das sparen können.


    Von mir 0,5/10

    PAWNit gratis nutzen?
    Geschenkcode: 2017VQXPKB8V3KA

    Hier könnte Ihre Werbung stehen.

  • keine lust hast, es zu erklären hast du auch keine Lust ein Tutorial zu schreiben, und somit hättest du dir das sparen


    Was gibt es auch großartig zu erklären? Jeder Scripter der auch nur ein bisschen hirn hat wird den Code ja sofort beim ersten mal verstehen, wer es nicht versteht ist zu dumm und brauch erst garnicht anfangen zu Scripten, sorry aber das ist nun mal meine meinung.



    Man kann auch Accounts/%s.ini benutzen, bleibt jedem selbst überlassen. ^^


    Edit: Zitat eingefügt.

    SA-MP Scripting Hilfe/Erklärungen bekommt ihr auf der SA-MP Wikipedia

    Einmal editiert, zuletzt von .#~Momo ()

  • Momo du verstehst es anscheinend nicht?
    Es gibt auch Neulinge beim Scripten die hier nichts verstehen dafür gibt es Tutorials wo etwas erklärt wird du gibst einfach nur etwas an, naja ich halte davon echt nichts.


    0\10

    Why do programmers always mix up Halloween and Christmas?
    Oct 31 == Dec 25

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen

  • Was gibt es auch großartig zu erklären? Jeder Scripter der auch nur ein bisschen hirn hat wird den Code ja sofort beim ersten mal verstehen


    Das hat mit Hirn NICHTS zu tun. Du bist einfach in der Position eines erfahrenen Scripters und bist unfähig, dich an deine Anfänge zurück zu versetzen.


    Das ist einfach kein Tutorial und du scheinst auch nicht zu verstehen, was ein Tutorial ist und wie man ein Gutes schreibt.
    Und für wen schreibst du dieses Tutorial hauptsächlich? Für die Leser und nicht für dich. Und wenn die Leser eben ein richtiges Tutorial mit Erklärungen wollen, dann machst du auch eins oder lässt es ganz bleiben.


    Ich habe es nicht so gemeint wie es sich anhört :) Soll kein Angriff sein, nur konstruktive Kritik.

    ICQ Scripting - Support 495961653
    Montags-Freitags ab 15 Uhr

  • hi
    ich krieg da immer errors
    C:\Users\user\Desktop\samp0.3bserver\gamemodes\testscript1.pwn(4) : fatal error 100: cannot read from file: "a_samp_ini"
    die zeile llautet
    #include <a_samp_ini>
    und wernn ich dini.dtest kompilieren wil bekomm ich den gleiche error was soll ihc da machen?