• Get Player Object By Nick
    8 replies, posted
When creating a chat command that accepts a player name as an input - for example !kick [name] - what's the most efficient way to get the player object from the nickname? Do you have to loop through all users and check name, then get player object? Or can you get it more directly. For example, [CODE] for k, v in pairs(player.GetAll()) do if v:Nick() == "Semajnad" then playerObject = v end end [/CODE]
Seriously Daniel.
Just some tips: - Use [B]ipairs[/B] instead of pairs since player.GetAll() returns a table that is always numerically indexed in order (starting from index 1). - If you want the searches to be case insensitive, make sure to v:Nick():[B]lower()[/B] and name[B]:lower()[/B] prior to checking. - If you want to check for multiple players with the same partial name, you need to keep track of the number of players found. For example, if there are 2 players with the name "John Smith" and "John Doe" and you only search with "John", you need to define what you want to happen. Should it only return the first match it finds, e.g. "John Smith"? Or should it return an error stating that multiple players were found with the name "John", and that the user needs to be more specific. What if one of the players' names really is just "John", but "John Smith" was found first? Should it return an error, or maybe just return the "John" player since it was an exact match? You need to be able to define the behavior that you want.
[URL]http://wiki.garrysmod.com/page/string/find[/URL] Build a table of players that match it then execute your command on the entry where the string occurs earliest while also there's least extra letters. In result, specifying longer text will reduce the table entries count. Ergo: 5 players -Red -Ted -Teredy -Ed -Edy Looking for "Edy" would return the 5th player, because its found in Teredy and Edy but starts earlier in Edy. Looking for "ed" would return all of the players, but would only execute it on "Ed" due to least extra digits. Looking for "Red" would return Red and Teredy, but execute it on Red due to string being found earlier than in Teredy and with no extra letters. You get the idea. [editline]19th August 2015[/editline] Also this what Mista says, it's smart and allows no error, altho I am sure if you use my way you can figure out easily how to tweak it to your likings. This part especially [quote]What if one of the players' names really is just "John", but "John Smith" was found first? Should it return an error, or maybe just return the "John" player since it was an exact match?[/quote] That can be solved by looking for the match with least extra letters.
[QUOTE=Mista Tea;48492145]- Use [B]ipairs[/B] instead of pairs since player.GetAll() returns a table that is always numerically indexed in order (starting from index 1). [/QUOTE] Honest question: Is there any advantages of using ipairs over pairs? In my mind this just spawns more confusion for beginners/people who copy paste code not knowing what it does.
[QUOTE=Robotboy655;48492198]Honest question: Is there any advantages of using ipairs over pairs? In my mind this just spawns more confusion for beginners/people who copy paste code not knowing what it does.[/QUOTE] He's no begineer. Thus my first post, he mostly asks me about lua related stuff.. but a fair point.
[QUOTE=Netheous;48492237]He's no begineer. Thus my first post, he mostly asks me about lua related stuff.. but a fair point.[/QUOTE] I mean the people who lurk in these threads copy pasting the code and editing in tables that do not start with 1 and contain string keys, etc. Plus I see no advantages of ipairs over pairs.
[QUOTE=Robotboy655;48492244]I mean the people who lurk in these threads copy pasting the code and editing in tables that do not start with 1 and contain string keys, etc. Plus I see no advantages of ipairs over pairs.[/QUOTE] Ipairs is usually faster than pairs. Did a benchmark: [code] local wat = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} local t0 = SysTime() for i = 1, 1e6 do for _, z in ipairs(wat) do -- do some shit end end local t1 = SysTime() for i = 1, 1e6 do for _, z in pairs(wat) do -- do some shit end end local t2 = SysTime() print(adv.StrFormat{"IPairs $1\nPairs $2", t1-t0, t2-t1}) -- Output: -- IPairs 0.042690150012561 -- Pairs 0.15366555219987 [/code]
Whatever, I got you some example Daniel since I know you'll make your own. Mind that it can be done more efficiently. [code]hook.Add( "PlayerSay", "hookerino", function( sender, text, isTeamOnly ) text = string.lower( text ) local matched = {} for i, ply in pairs ( player.GetAll() ) do local startpos, endpos = string.find( string.lower( ply:Nick() ), text, 0, true ) if startpos and endpos then matched[ table.Count( matched ) + 1 ] = { ply = ply, startpos = startpos, endpos = endpos, extra = string.len( string.lower( ply:Nick() ) ) - ( endpos - startpos ) } end end local bestResult = matched[ 1 ] if table.Count( matched ) > 1 then for i, matchData in pairs( matched ) do if matchData.extra < bestResult.extra then bestResult = matched[ i ] end end end end )[/code] Ignore the hook, it's just to pass you the idea.
Sorry, you need to Log In to post a reply to this thread.