Still have questions? Join our Discord server and get real time help.
0

# How do I index an abbreviated name?

Edited 7 months 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 User#19524 2 — 7mo
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 — 7mo
0
oh. for that you'll need string.sub User#19524 2 — 7mo

1
ozzyDrive 625
7 months 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 — 7mo
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 625 — 7mo