Hi, I’ve been trying to add aliases to my commands, however the complexity increases when I prefer doing it in my own way, the issue with how it is set up currently, is that I can’t get the function to run if I’m using aliases, as it’s binded to the actual command name.
Any suggestions would be helpful.
Commands handler:
CommandsManager.Commands = {
commands = {
Aliases = {['c'] = 'c', ['cmds'] = 'cmds'},
Description = 'No description!',
Execute = function(Player, Args)
local RequiredRank = 'Helper'
local Command = Args[1]
local PlayerRank = Player:FindFirstChild('RankNumber')
if (PlayerRank) then
if (PlayerRank.Value >= RankManager.Ranks[RequiredRank].Rank)
then
CommandsManager.Functions.Alert(Player, table.concat(CommandsManager.Commands, '\n'))
else
CommandsManager.Functions.Alert(Player, CommandsManager.Messages.NoPermission)
end
else
CommandsManager.Functions.Alert(Player, CommandsManager.Messages.Error)
end
end
}
}
Commands runner:
Player.Chatted:Connect(function(Message)
local Args = Message:split(' ')
local Command = Args[1]
local FixedCommand = Command:gsub(CommandsManager.Settings.Prefix, ''):lower()
for Index, Value in pairs(CommandsManager.Commands) do
local Execute
if FixedCommand == Index then
Execute = CommandsManager.Commands[FixedCommand].Execute
Execute(Player, Args)
break
end
end
end)
Clearly, I’m able to add aliases if I really wanted to, but it would be way messier, I do prefer this method or something similar to it, but I don’t believe there’s any way around it due to how it’s set up currently.
I don’t know why you’d think it’d change much? simply change the table of “Aliases” to something like
Aliases = {'c', 'cmds'}
and use table.find() to check.
Player.Chatted:Connect(function(Message)
local Args = Message:split(' ')
local Command = Args[1]
local FixedCommand = Command:gsub(CommandsManager.Settings.Prefix, ''):lower()
for Index, Value in pairs(CommandsManager.Commands) do
local Execute
if FixedCommand == Index or table.find(Value.Aliases, FixedCommand) then
Execute = CommandsManager.Commands[FixedCommand].Execute
Execute(Player, Args)
break
end
end
end)
Sorry, just trying to understand your code for now.
Does this mean that CommandsManager.Commands is a dictionary of strings to commands, where a command is an object with keys Aliases, Description and Execute? So you’ve really got a command just
called “commands”? Sorry that’s just a bit confusing to me, I’m sure it makes sense in context.
Assuming this understanding is right: why not just populate the Commands dictionary with additional references to each command for each of it’s aliases? I.e.
local CommandsManager.Commands = {
commands = {
Aliases = {"c", "cmds",},
...
},
kick = {
Aliases = {"k", "yeet",},
...
}
}
--Populate command names by their keys in the Commands dictionary
for commandName, command in pairs(CommandsManager.Commands) do
command.Name = commandName
end
--Populate CommandsManager.Commands with additional refs to each command for each command alias
--Warns and ignores on duplicate names/aliases
for commandName, command in pairs(CommandsManager.Commands) do
for _, alias in ipairs(command.Aliases) do
if CommandsManager.Commands[alias] then
warn(("CommandsManager.Commands already has name %s (alias for %s) for command %s, ignoring!"):format(alias, commandName, CommandsManager.Commands[alias].Name))
else
CommandsManager.Commands[alias] = command
end
end
end
That way you can get a command by either it’s name or an alias like this:
local command = CommandsManager.Commands[daCommandName]
Does this mean that CommandsManager.Commands is a dictionary of strings to commands, where a command is an object with keys Aliases, Description and Execute? So you’ve really got a command just
called “commands”? Sorry that’s just a bit confusing to me, I’m sure it makes sense in context.
CommandsManager.Commands holds the commands.
The issue here would be that I can’t call the execute function inside the command because the command name cannot be 2 things, it’s limited to 1, which would be the command name…
Yeah I can see how that’s an issue. If I were making this, I’d keep two separate structures to solve this. One that’s just an array of commands, and another that’s a dictionary from command name/alias to command. Or you could use a single table and just keep the array and dict parts separate, but that’s not especially readable IMO.
That way you can iterate over each command uniquely, and also look them up by their name/alias in constant time. Although at this point it’s getting kinda complicated, you might want to just have a function for finding a command from it’s alias by searching through commands, like Kaiden suggested
EDIT: Oh, but I don’t think concat even works on dictionaries in the first place?
Although at this point it’s getting kinda complicated, you might want to just have a function for finding a command from it’s alias by searching through commands, like Kaiden suggested
Yes, I’m aware, but another issue will come if I do that.
I would need the aliases to be able to get to the Execute function somehow.
EDIT: Oh, but I don’t think concat even works on dictionaries in the first place?
This was just a test, it serves no functionality at the moment. Just a test command.
CommandsManager.Commands[FixedCommand].Execute won’t support aliases when indexing it like that, so no, it won’t work because it relies the command to be the command’s name, not any alias of it.
I would need to create another command just to add aliases if I want it to work like that, sadly.
Or, if it were possible to assign multiple strings to it, that would work too.
Oh sorry, forgot to change that part. Simply change CommandsManager.Commands[FixedCommand] to Value.
Player.Chatted:Connect(function(Message)
local Args = Message:split(' ')
local Command = Args[1]
local FixedCommand = Command:gsub(CommandsManager.Settings.Prefix, ''):lower()
for Index, Value in pairs(CommandsManager.Commands) do
local Execute
if FixedCommand == Index or table.find(Value.Aliases, FixedCommand) then
Execute = Value.Execute
Execute(Player, Args)
break
end
end
end)
Well, no. Execute is outside of the aliases. That wouldn’t work.
If that were to work, I’d have to copy-paste the execute inside the aliases part, which might create another problem if I don’t include the actual command name in there as well.
Honestly, just try the script, and don’t say it’s wrong UNTIL you try it. You keep saying it won’t work, what am I supposed to say if you won’t even listen to what I have to say? I’m not gonna go into this and keep responding. It’s quite literally almost 4 am for me and I’m trying to help but you won’t even take into account what I am saying.
for i, cmd in pairs(commandsManager) do
if table.find(cmd.Aliases, fixedCommand) then
– run the command
break
end
end
Both yes and no, but not what I prefer.
{“c”, “cmds”}
The issue with this is that it’s a value, and the index would be something like: [1] = ‘c’, [2] = ‘cmds’
The only way to bypass it is by giving it a name so it can be referenced.