Simples Accountsystem

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Simples Accountsystem

      Wie macht man ein Accountsystem? und wie bringt man alles in ein einfaches Tutorial?
      Ganz einfach. Wir halten das ganze so simpel wie möglich. "Und wie?" Mit Lua.

      Die neue Version (L1.3, release:kurz nach 0.7.0) des N-Server bringt einige Neuerungen mit. Zum einen ist es seit dieser Version möglich dass auch Standard Clients auf einen N-Server können und zum anderen haben wir eine Datenbank-Schnittstelle in Lua eingebaut. Das ganze ist so simpel wie möglich gehalten und ermöglicht es jedem ein Accountsystem zu erstellen, dass NICHT auf TEXTFILES sonder auf eine SQLITE3-Datenbank basiert. Wie das möglich ist und was erforderlich ist zeige ich in diesem Tutorial:

      Als erstes müssen wir und den neusten N-Server von github runterladen und kompilieren oder hier(Release, Debug) ein Dev-Version downloaden.
      Die Lua(mit allen fixes) kann hier heruntergeladen werden: hier

      Wenn dies erledigt ist geht es auch direkt ans Coden. Wir erstellen einfach eine mod die die Punkte der spieler in einer Datenbank speichert!

      Der ganz folgende code kommt in die server.lua in den lua ordner:


      Quellcode

      1. db = sql.create("accounts.db")
      2. sql.query(db, "CREATE TABLE IF NOT EXISTS `users` (`uid` INTEGER PRIMARY KEY, `username`, `password`, `playername`, `kills` INTEGER DEFAULT 0, `deaths` INTEGER DEFAULT 0)")

      Öffnen der Datenbank und erstellen der Tabelle `users`


      Quellcode

      1. AddEventListener("OnChat", "Chat")
      2. AddEventListener("OnClientConnect", "ClientConnect")
      3. AddEventListener("OnDie", "Kill")
      4. AddEventListener("OnPlayerJoinTeam", "PlayerJoinTeam")
      5. AddEventListener("OnClientDrop", "Leave")

      Hinzufügen der EventListener
      Chat für Chatcommands
      ClientConnect zum zurücksetzten beim join
      Leave um den Account beim verlassen zu speichern


      Quellcode

      1. Accounts = {}

      Erstellen eines leeren Arrays für die eingeloggten Accounts


      Quellcode

      1. iTick = 0
      2. function Tick(Time, ServerTick)
      3. iTick = iTick + 1
      4. end
      5. function TickDefered(Time, ServerTick)
      6. end
      7. function PostTick(Time, ServerTick)
      8. end

      Tick funktionen. Hierbei nicht benötigt.


      Quellcode

      1. function EscapeString(str)
      2. str = tostring(str)
      3. str = str:replace("\\", "\\\\")
      4. str = str:replace("'", "''")
      5. return str
      6. end

      Escape Funktion - um SQL-Injection zu vermeiden


      Quellcode

      1. function CheckAccount(Name)
      2. result = sql.query(db, "SELECT * FROM `users` WHERE `username` = '" .. EscapeString(Name) .. "'")
      3. if (result[1] and result[1]["uid"]) then
      4. return true
      5. end
      6. return false
      7. end

      Diese Funktion testet ob es den Account schon gibt. Wir fragen ab ob es einen Account mit dem Name "Name" gibt


      Quellcode

      1. function GetParameter(Text, Number)
      2. for i = 1, Number do
      3. s = Text:find(" ")
      4. if (s == nil) then
      5. return nil
      6. end
      7. Text = Text:sub(s + 1)
      8. end
      9. s = Text:find(" ")
      10. if (s ~= nil) then
      11. s = s - 1
      12. end
      13. Text = Text:sub(1, s)
      14. return Text
      15. end
      Alles anzeigen

      Trennt Chat-Parameter voneinander und gib den Gewünschten zurück
      Die For-Schleife springt immer zum nächsten Parameter. Der Code nach der For-Schneidet den Rest ab.


      Quellcode

      1. function Update(ClientID)
      2. if (Accounts[ClientID]["uid"] == nil) then
      3. return
      4. end
      5. sql.query(db, "UPDATE `users` SET `playername` = '" .. EscapeString(GetPlayerName(ClientID)) .. "', `kills` = '" .. EscapeString(Accounts[ClientID]["kills"]) .. "', `deaths` = '" .. EscapeString(Accounts[ClientID]["deaths"]) .. "' WHERE `uid` = '" .. Accounts[ClientID]["uid"] .. "'")
      6. end

      Speichert die Änderungen an dem Account mit der angegebenen ClientID.


      Quellcode

      1. function Chat(Text, ID, Team)
      2. if (Text:sub(1, 1) == "/") then --prüfe auf chat command[/color]
      3. if (Text:sub(1, 9) == "/register" and Accounts[ID]["uid"] == nil) then --prüfe auf register
      4. Username = GetParameter(Text, 1) --frage username ab
      5. Password = GetParameter(Text, 2) --frage password ab
      6. if (Username == nil or Password == nil) then --prüfe ob username und password vorhanden sind
      7. SendChatTarget(ID, "Usage: /register username password!") --meldung
      8. elseif (CheckAccount(Username) == false) then --prüfe ob account vorhanden sind
      9. sql.query(db, "INSERT INTO `users` (`username`, `password`, `playername`) VALUES ('" .. EscapeString(Username) .. "', '" .. EscapeString(Password) .. "', '" .. EscapeString(GetPlayerName(ID)) .. "')") --erstelle account
      10. SendChatTarget(ID, "Account created successfully!") --meldung
      11. else
      12. SendChatTarget(ID, "This account already exist!") --meldung
      13. end
      14. elseif (Text:sub(1, 6) == "/login" and Accounts[ID]["uid"] == nil) then --prüfe auf login
      15. Username = GetParameter(Text, 1) --frage username ab
      16. Password = GetParameter(Text, 2) --frage password ab
      17. if (Username == nil or Password == nil) then --prüfe ob username und password vorhanden sind
      18. SendChatTarget(ID, "Usage: /login username password!") --meldung
      19. else
      20. result = sql.query(db, "SELECT * FROM `users` WHERE `username` = '" .. EscapeString(Username) .. "' AND `password` = '" .. EscapeString(Password) .. "'") --hole userdaten aus der Datebank
      21. if (result[1] and result[1]["uid"]) then --wenn account vorhanden
      22. Accounts[ID] = result[1] --kopiere account daten
      23. SendChatTarget(ID, "Logged in successfully!") --meldung
      24. SetPlayerScore(ID, Accounts[ID]["kills"]) --player die punkte zuweisen
      25. SetPlayerTeam(ID, 0) --player in Team 0 setzten[/color]
      26. else
      27. SendChatTarget(ID, "The username or the password is wrong!") --meldung
      28. end
      29. end
      30. elseif (Text:sub(1, 7) == "/logout" and Accounts[ID]["uid"] ~= nil) then --prüfe auf logout
      31. Accounts[ID] = {}
      32. SendChatTarget(ID, "Successfully logged out!") --meldung
      33. SetPlayerTeam(ID, -1)
      34. else
      35. SendChatTarget(ID, "Unknown command") --meldung
      36. SendChatTarget(ID, "/register") --meldung
      37. SendChatTarget(ID, "/login") --meldung
      38. SendChatTarget(ID, "/logout") --meldung
      39. end
      40. return true --chat verstecken
      41. end
      42. end
      Alles anzeigen

      Kommentare im code.


      Quellcode

      1. function Kill(Killer, Victim, Weapon)
      2. if (Killer ~= Victim) then
      3. Accounts[Killer]["kills"] = Accounts[Killer]["kills"] + 1
      4. end
      5. Accounts[Victim]["deaths"] = Accounts[Killer]["deaths"] + 1
      6. end

      Kills und Deaths zählen.


      Quellcode

      1. function ClientConnect(ClientID)
      2. Accounts[ClientID] = {}
      3. SetPlayerTeam(ClientID, -1) --spieler im spec setzten
      4. end

      Zurücksetzten/Löschen des Accounts wenn Spieler den Server betritt.

      Quellcode

      1. function Leave(ID, Reason)
      2. Update(ID)
      3. end

      Update Account wenn Spieler den Server verlässt


      Quellcode

      1. function PlayerJoinTeam(ClientID, Team)
      2. if (Accounts[ClientID]["uid"]) then
      3. return
      4. end
      5. SendChatTarget(ClientID, "You are not logged in!")
      6. return true
      7. end

      Join Sperre wenn nicht eingeloggt



      Nun noch die Config-file:

      Quellcode

      1. sv_name Name
      2. sv_lua 1
      3. add_lua_file server.lua
      4. sv_map dm1




      So das war jetzt einiges an code. Eure eigenen Werte könnt ihr in diesen Zeilen hinzufügen:
      Erstellen der Tabelle:
      sql.query(db, "CREATE TABLE IF NOT EXISTS `users` (`uid` INTEGER PRIMARY KEY, `username`, `password`, `playername`, `kills` INTEGER DEFAULT 0, `deaths` INTEGER DEFAULT 0)")

      Update des Accounts:
      sql.query(db, "UPDATE `users` SET `playername` = '" .. EscapeString(GetPlayerName(ClientID)) .. "', `kills` = '" .. EscapeString(Accounts[ClientID]["kills"]) .. "', `deaths` = '" .. EscapeString(Accounts[ClientID]["deaths"]) .. "' WHERE `uid` = '" .. Accounts[ClientID]["uid"] .. "'")


      Auf grundlage dieser Mod/dieses Tutorials kann man mit ein bisschen übung eine ganze Levelmod programmieren.

      Wenn ihr fragen oder anregungen habt schreibt mir diese.

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von MAP94 ()

    • [Bugfix] Neuer Command und es ist nicht mehr möglich, dass 2 Leute in den selben Account gleichzeitig eingeloggt sein können.

      Heyho,

      ich habe bei dem System von Map einige Mängel gefunden. Einer davon war, dass sich 2 Leute gleichzeitig in ein und den selben Account zur gleichen Zeit einloggen können. Somit habe ich mich rangesetzt und den Bug erfolgreich behoben. Dazu habe ich einen Command hinzugefügt, undzwar stats. In dem werden deine Kills und Deaths und sogar deine K/D Rate angezeigt. Viel Spaß damit :)

      Überarbeitetes Lua Accountsystem von Map

      Quellcode

      1. db = sql.create("accounts.db")
      2. sql.query(db, "CREATE TABLE IF NOT EXISTS `users` (`uid` INTEGER PRIMARY KEY, `username`, `password`, `playername`, `kills` INTEGER DEFAULT 0, `deaths` INTEGER DEFAULT 0, `logged_in` INTEGER DEFAULT 0)")
      3. AddEventListener("OnChat", "Chat")
      4. AddEventListener("OnClientConnect", "ClientConnect")
      5. AddEventListener("OnDie", "Kill")
      6. AddEventListener("OnPlayerJoinTeam", "PlayerJoinTeam")
      7. AddEventListener("OnClientDrop", "Leave")
      8. Accounts = {}
      9. KDRate = 0
      10. iTick = 0
      11. function Tick(Time, ServerTick)
      12. iTick = iTick + 1
      13. end
      14. function TickDefered(Time, ServerTick)
      15. end
      16. function PostTick(Time, ServerTick)
      17. end
      18. function EscapeString(str)
      19. str = tostring(str)
      20. str = str:replace("\\", "\\\\")
      21. str = str:replace("'", "''")
      22. return str
      23. end
      24. function CheckAccount(Name)
      25. result = sql.query(db, "SELECT * FROM `users` WHERE `username` = '" .. EscapeString(Name) .. "'")
      26. if (result[1] and result[1]["uid"]) then
      27. return true
      28. end
      29. return false
      30. end
      31. function GetParameter(Text, Number)
      32. for i = 1, Number do
      33. s = Text:find(" ")
      34. if (s == nil) then
      35. return nil
      36. end
      37. Text = Text:sub(s + 1)
      38. end
      39. s = Text:find(" ")
      40. if (s ~= nil) then
      41. s = s - 1
      42. end
      43. Text = Text:sub(1, s)
      44. return Text
      45. end
      46. function Update(ClientID)
      47. if (Accounts[ClientID]["uid"] == nil) then
      48. return
      49. end
      50. sql.query(db, "UPDATE `users` SET `playername` = '" .. EscapeString(GetPlayerName(ClientID)) .. "', `kills` = '" .. EscapeString(Accounts[ClientID]["kills"]) .. "', `deaths` = '" .. EscapeString(Accounts[ClientID]["deaths"]) .. "', `logged_in` = '".. EscapeString(Accounts[ClientID]["logged_in"]) .."' WHERE `uid` = '" .. Accounts[ClientID]["uid"] .. "'")
      51. end
      52. function MakeLoggedIn(ClientID)
      53. sql.query(db, "UPDATE `users` SET `playername` = '" .. EscapeString(GetPlayerName(ClientID)) .. "', `logged_in` = '"..EscapeString(Accounts[ClientID]["logged_in"]).."' WHERE `uid` = '" .. Accounts[ClientID]["uid"] .. "'")
      54. end
      55. function Chat(Text, ID, Team)
      56. if (Text:sub(1, 1) == "/") then
      57. if (Text:sub(1, 9) == "/register" and Accounts[ID]["uid"] == nil) then
      58. Username = GetParameter(Text, 1)
      59. Password = GetParameter(Text, 2)
      60. if (Username == nil or Password == nil) then
      61. SendChatTarget(ID, "Usage: /register username password!")
      62. elseif (CheckAccount(Username) == false) then
      63. sql.query(db, "INSERT INTO `users` (`username`, `password`, `playername`) VALUES ('" .. EscapeString(Username) .. "', '" .. EscapeString(Password) .. "', '" .. EscapeString(GetPlayerName(ID)) .. "')")
      64. SendChatTarget(ID, "Account created successfully!")
      65. else
      66. SendChatTarget(ID, "This account already exist!")
      67. end
      68. elseif (Text:sub(1, 6) == "/login" and Accounts[ID]["uid"] == nil) then
      69. Username = GetParameter(Text, 1)
      70. Password = GetParameter(Text, 2)
      71. if (Username == nil or Password == nil) then
      72. SendChatTarget(ID, Username)
      73. SendChatTarget(ID, Password)
      74. SendChatTarget(ID, "Usage: /login username password!")
      75. else
      76. result = sql.query(db, "SELECT * FROM `users` WHERE `username` = '" .. EscapeString(Username) .. "' AND `password` = '" .. EscapeString(Password) .. "'")
      77. if (result[1] and result[1]["uid"]) then
      78. if (result[1]["logged_in"] == 1) then
      79. SendChatTarget(ID, "Account already logged in!")
      80. else
      81. Accounts[ID] = result[1]
      82. Print("kills", result[1]["kills"])
      83. Print("deaths", result[1]["deaths"])
      84. result[1]["logged_in"] = 1
      85. Update(ID)
      86. SendChatTarget(ID, "Logged in successfully!")
      87. SetPlayerScore(ID, Accounts[ID]["kills"])
      88. SetPlayerTeam(ID, 0)
      89. end
      90. else
      91. SendChatTarget(ID, "The username or the password is wrong!")
      92. end
      93. end
      94. elseif (Text:sub(1, 6) == "/stats" and (Text:len() == 6)) then
      95. SendChatTarget(ID, "Kills: "..Accounts[ID]["kills"])
      96. SendChatTarget(ID, "Deaths: "..Accounts[ID]["deaths"])
      97. if(Accounts[ID]["kills"] == 0 or Accounts[ID]["deaths"] == 0) then
      98. KDRate = 0
      99. else
      100. KDRate = ((Accounts[ID]["kills"])/(Accounts[ID]["deaths"]))
      101. end
      102. SendChatTarget(ID, "K/D: "..KDRate)
      103. elseif (Text:sub(1, 7) == "/logout" and Accounts[ID]["uid"] ~= nil) then
      104. Accounts[ID]["logged_in"] = 0
      105. Update(ID)
      106. Accounts[ID] = {}
      107. SendChatTarget(ID, "Successfully logged out!")
      108. SetPlayerTeam(ID, -1)
      109. else
      110. SendChatTarget(ID, "Unknown command")
      111. SendChatTarget(ID, "/cmdlist")
      112. end
      113. return true
      114. end
      115. end
      116. function Kill(Killer, Victim, Weapon)
      117. if (Killer ~= Victim) then
      118. Accounts[Killer]["kills"] = Accounts[Killer]["kills"] + 1
      119. end
      120. Accounts[Victim]["deaths"] = Accounts[Killer]["deaths"] + 1
      121. end
      122. function Leave(ID, Reason)
      123. Accounts[ID]["logged_in"] = 0
      124. Update(ID)
      125. end
      126. function ClientConnect(ClientID)
      127. Print("Clear", ClientID)
      128. Accounts[ClientID] = {}
      129. SetPlayerTeam(ClientID, -1)
      130. end
      131. function PlayerJoinTeam(ClientID, Team)
      132. if (Accounts[ClientID]["uid"]) then
      133. return
      134. end
      135. SendChatTarget(ClientID, "You are not logged in!")
      136. return true
      137. end
      Alles anzeigen


      lg.