• Finding player SteamID in table
    7 replies, posted
I am trying to make a table with players SteamIDs that checks if the player is the right rank...but it appears that this does not work...is this the right method to storing player ranks? Or is file based storage better? [lua] local ply = FindMetaTable('Player') Rank = { SteamID = "STEAM_0:0:000000000" } function ply:IsRank() for k,v in pairs(Rank) do if table.HasValue( Rank, ply:SteamID ) then return true else return false end end end [/lua]
There's a lot of things wrong with this code... like checking table.HasValue when looping through the same table and using ply instead of self within the function. Couldn't you use ULX or another permission system?
I would probaby store the information in files. So when a player connects to the server you load the information and cache it from a file. Wrote this in a couple of minutes. [CODE]--Check if we need to create a folder where we will store all players data. if !file.Exists("permissionsystem","DATA") then --Create a folder to save all peoples data in if it didn't exist. file.CreateDir("permissionsystem") end --Hook will check permission and cache it on join. hook.Add("PlayerInitialSpawn","LoadPermission",function( ply ) --Check if the permissionfile of the player exists. if file.Exists("permissionsystem/" .. ply:SteamID64() .. ".txt","DATA") then --Cache the permission. ply.PermissionSystem = { HasPermission = true } --Return to make the last code not run as we already found the permission. return end --Set the permission to false as the code would have been stopped if we had permission. ply.PermissionSystem = { HasPermission = false } end) --Saving player metatable to create functions. local PLAYER = FindMetaTable('Player') --Create a function to set the players permission. function PLAYER:SetPermission( bool ) --Cache the filepath. local path = "permissionsystem/" .. self:SteamID64() .. ".txt" --Check if we should have permission or not. if bool == true then --Create a file that shows we got permission file.Write(path,"") --Update the cached var that says if we got permission or not. ply.PermissionSystem.HasPermission = true else --Remove the file if it exists and we are removing permission. if file.Exists(path,"DATA") then file.Delete(path) --Update the cached var that says if we got permission or not. ply.PermissionSystem.HasPermission = false end end end[/CODE]
[QUOTE=Stardust342;52480558]Couldn't you use ULX or another permission system?[/QUOTE] You don't always need a permission system. Could be something like VIP groups that you would want to have separate from the server's permission system First - The function is a metafunction, so instead of calling [B]ply:SteamID()[/B] you should call [B]self:SteamID()[/B], also - remember to include the brackets when calling a function. Then, you can optimize your code by [URL="http://wiki.garrysmod.com/page/Tables:_Bad_Habits"]setting the table properly[/URL] [lua]local ply = FindMetaTable('Player') local Rank = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, } function ply:IsRank() return Rank[self:SteamID()] or "No Rank" -- Thanks James end[/lua] Alternatively, if you want multiple ranks (I gave the rank names to make it more readable) [lua]local ply = FindMetaTable('Player') local Ranks = { Medium = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, }, High = { "STEAM_0:0:000000002" = true, "STEAM_0:0:000000003" = true, }, Master = { "STEAM_0:0:000000004" = true, "STEAM_0:0:000000005" = true, }, } function ply:IsRank( rank ) return Ranks[rank] and Ranks[rank][self:SteamID()] or "No Rank" -- Thanks James end function ply:GetRank() local sid = self:SteamID() for RankName, RankTable in pairs( Ranks ) do if RankTable[sid] then return RankName end end return "No Rank" -- Thanks James end[/lua]
[QUOTE=JasonMan34;52481282]You don't always need a permission system. Could be something like VIP groups that you would want to have separate from the server's permission system First - The function is a metafunction, so instead of calling [B]ply:SteamID()[/B] you should call [B]self:SteamID()[/B], also - remember to include the brackets when calling a function. Then, you can optimize your code by [URL="http://wiki.garrysmod.com/page/Tables:_Bad_Habits"]setting the table properly[/URL] [lua]local ply = FindMetaTable('Player') local Rank = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, } function ply:IsRank() return Rank[self:SteamID()] end[/lua] Alternatively, if you want multiple ranks (I gave the rank names to make it more readable) [lua]local ply = FindMetaTable('Player') local Ranks = { Medium = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, }, High = { "STEAM_0:0:000000002" = true, "STEAM_0:0:000000003" = true, }, Master = { "STEAM_0:0:000000004" = true, "STEAM_0:0:000000005" = true, }, } function ply:IsRank( rank ) return Ranks[rank][self:SteamID()] end function ply:GetRank() local sid = self:SteamID() for RankName, RankTable in pairs( Ranks ) do if RankTable[sid] then return RankName end end end[/lua][/QUOTE] This will error if anyone enters an invalid rank. Instead, do this: [lua] function ply:IsRank( rank ) return Ranks[rank] and Ranks[rank][self:SteamID()] or false end [/lua]
[QUOTE=JasonMan34;52481282]You don't always need a permission system. Could be something like VIP groups that you would want to have separate from the server's permission system First - The function is a metafunction, so instead of calling [B]ply:SteamID()[/B] you should call [B]self:SteamID()[/B], also - remember to include the brackets when calling a function. Then, you can optimize your code by [URL="http://wiki.garrysmod.com/page/Tables:_Bad_Habits"]setting the table properly[/URL] [lua]local ply = FindMetaTable('Player') local Rank = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, } function ply:IsRank() return Rank[self:SteamID()] or "No Rank" -- Thanks James end[/lua] Alternatively, if you want multiple ranks (I gave the rank names to make it more readable) [lua]local ply = FindMetaTable('Player') local Ranks = { Medium = { "STEAM_0:0:000000000" = true, "STEAM_0:0:000000001" = true, }, High = { "STEAM_0:0:000000002" = true, "STEAM_0:0:000000003" = true, }, Master = { "STEAM_0:0:000000004" = true, "STEAM_0:0:000000005" = true, }, } function ply:IsRank( rank ) return Ranks[rank] and Ranks[rank][self:SteamID()] or "No Rank" -- Thanks James end function ply:GetRank() local sid = self:SteamID() for RankName, RankTable in pairs( Ranks ) do if RankTable[sid] then return RankName end end return "No Rank" -- Thanks James end[/lua][/QUOTE] Returning "No Rank" if it's not set is a terrible idea, because that would pass an if statement as true, so if someone didn't have their rank set, any if statement would act as if they did when using that function. Instead just return false if it's not defined. Actually, if you didn't have the or, I don't think it would error and I think it would just return nil, which would work just fine.
[QUOTE=monkeymacman;52482033]Returning "No Rank" if it's not set is a terrible idea, because that would pass an if statement. Instead just return false if it's not defined. Actually, if you didn't have the or, I don't think it would error and I think it would just return nil, which would work just fine.[/QUOTE] [B]Ranks[rank][self:SteamID()][/B] will error for an invalid rank because you can't index [B]Ranks[nil][/B], [B]Table[nil][key][/B] will return an "Attempt to index global '...' (a nil value)" error
[QUOTE=JasonMan34;52482421][B]Ranks[rank][self:SteamID()][/B] will error for an invalid rank because you can't index [B]Ranks[nil][/B], [B]Table[nil][key][/B] will return an "Attempt to index global '...' (a nil value)" error[/QUOTE] It only errors if you try to find the value of a key in a nil table (which, btw, has a different error message than the one you described), but it won't try to index it because you have the "return Ranks[rank] and"... so it won't try to index it if the rank doesn't exist. (I have tested it and it gets no errors...) Also, complete sidenote, your code errors anyway, because you can't have "String" = (whatever) in a table, only ["String"] = (whatever) [editline]18th July 2017[/editline] As for the ply:GetRank() function, you literally have "if RankTable[sid] then" which would error if you really couldn't index a key that doesn't exist. [editline]18th July 2017[/editline] Here's an actual working ([b]TESTED[/b]) version of the code that also doesn't mess up in normal if statements if you want to hardcode your SteamIDs into a table [code] local PLYMETA = FindMetaTable('Player') local Rank = { ["STEAM_0:0:000000000"] = true, ["STEAM_0:0:000000001"] = true, } function PLYMETA:IsRank() return Rank[self:SteamID()] end [/code] Or, of course, if you want to have different ranks [code] local PLYMETA = FindMetaTable('Player') local Ranks = { Rank1 = { ["STEAM_0:0:000000000"] = true, ["STEAM_0:0:000000001"] = true, }, Rank2 = { ["STEAM_0:0:000000002"] = true, ["STEAM_0:0:000000003"] = true, } } function PLYMETA:IsRank(rankCheck) return Ranks[rankCheck] and Ranks[rankCheck][self:SteamID()] end function PLYMETA:GetRank() for RankName, RankTable in pairs(Ranks) do if RankTable[self:SteamID()] then return RankName end end return "User" end [/code] [editline]18th July 2017[/editline] Of course, I'd still rather use ULX (which also wouldn't require checking groups, just register an access string and check if a player has that) instead of making a whole separate system, but if you'd rather not, this works. [editline]19th July 2017[/editline] Actually... Here's a MUCH simpler version involving no loops. [code] local Ranks = { ["SteamID1"] = "Rank1", ["SteamID2"] = "Rank2", } local PLYMETA = FindMetaTable("Player") function PLYMETA:IsRank(rankCheck) return Ranks[self:SteamID()] == rankCheck end function PLYMETA:GetRank() return Ranks[self:SteamID()] or "User" end [/code]
Sorry, you need to Log In to post a reply to this thread.