Ad
Log in to vote
0

How do I index an abbreviated name?

Asked by 10 days ago
Edited 10 days ago

I'm creating a custom admin script and I'm at lost with finding abbreviated names.

This is what I currently have where you have to type the full username.

function findPlayer(name)
    local players = {}

    for _, player in ipairs(game.Players:GetPlayers()) do
         -- if Data[player.Name .. "'s Data"].FakeName.Value:lower() == name:lower() then --
        if player.Name:lower() == name:lower() then
            table.insert(players, player)
        end
    end

    if "all" == name:lower() then 
        for i,v in pairs(game.Players:GetPlayers()) do
            table.insert(players, v)
        end
    end

    return players
end

In addition I want to also index fake usernames that will often times have spaces in them or maybe even be similar.

Ex: We have three fake names in game: Sarah Law, Sarah Lau, and Jimmy Neutron

:Kill Jimmy - kills Jimmy Neutron

:Kill Sarah - returns invalid because there are two names starting with sarah

:Kill Sarah Law - kills stated name

0
Don't use names for admin commands, use UserId incapaz 5465 — 10d
0
I have, this is for finding in-game players. ":Kill Sarah L" I want this to be able to find Sarah Law. ICosmicReaver 30 — 10d
0
oh. for that you'll need string.sub incapaz 5465 — 10d

1 answer

Log in to vote
1
Answered by
ozzyDrive 167
10 days ago

You can take a substring of a string with the string.sub function. If you have string A equal to "Player1" and string B equal to "pla", you can take a substring of string A with the length of string B. These two strings can then be lowered with the string.lower function and compared.

local stringA = "Player1"
local stringB = "pla"
local abbreviatedA = stringA:sub(1, #stringB)
print(abbreviatedA:lower() == stringB:lower())

This functionality is quite simple to implement into your program:

local Players = game:GetService("Players")

local findPlayerKeywords = {
    all = function()
        local players = {}
        for _, player in next, Players:GetPlayers() do
            table.insert(players, player)
        end
        return players
    end,
}

local function getPlayersWithMatchingName(str)
    str = str:lower()   --  the findPlayer function has already lowered the passed string but not doing so here is considered a bad practice as we cannot assume all other functions to do it for us
    local matches = {}
    for _, player in next, Players:GetPlayers() do
        local abbreviatedName = player.Name:sub(1, #str)
        if abbreviatedName:lower() == str then
            table.insert(matches, player)
        end
    end
    return matches
end

local function findPlayer(str, allowMultipleMatches)
    str = str:lower()
    if findPlayerKeywords[str] then
        return findPlayerKeywords[str]()
    else
        local players = getPlayersWithMatchingName(str)
        if allowMultipleMatches or #players <= 1 then
            return players
        else
            return {}   --  alternatively nil can be returned, just keep in mind all the functions calling "findPlayer" have to take that possible outcome into account
        end
    end
end

Your code and actual question did have two contradicting statements. Your code hints that you do want to get a table of players as the output, yet your text states you either want nothing or possibly a player object. Thus I added the allowMultipleMatches option.

0
Would there be anyway to not cache the stuff after the name. So :place Jimmy Neutron 454364634. Without the str being the whole lines after the name? ICosmicReaver 30 — 10d
0
You'd need to split the string into multiple substrings (the command, the target(s), the parameters). It is up to you to decide the rules on how the string is split. You can use the string.gmatch iterator and string patterns to grab all the parts you want. You'd then call "findPlayer" with the "target" substring. ozzyDrive 167 — 9d
Ad

Answer this question