local Players = game:GetService("Players")
if not game:IsLoaded() then
game.Loaded:Wait()
end
local treasures = Players.LocalPlayer:WaitForChild("Treasures")
return function(registry)
local Util = registry.Cmdr.Util
local treasureNames = Util.GetNames(treasures:GetChildren())
table.sort(treasureNames) -- Guarantees the same order in the list
registry:RegisterType("treasure",
Util.MakeEnumType(
"TreasureName",
treasureNames
)
)
end
I’m currently stuck on something with Cmdr. I’m trying to make a command that utilizes multiple custom types. However I want one of the arguments to pick a specific type depending on it’s previous argument.
Here’s a picture to show what I mean.
Any help is super appreciated!!
Thanks in advance!
There’s two things that I would like for my project, are these able to be done on cmdr or is there an alternative with these that I could use?
Is there a way to have optional arguments? like you could set it to this or that, or just leave it blank to do both.
Is there a way to have a system where if you press enter and you don’t have a valid command typed in, instead of executing it will autocomplete the top result?
Autocomplete Example
If I were to press enter here, it would put the whole “clear” command into the box
(NOT EXECUTE IT)
I didn’t see any replies here mentioning support for Player’s DisplayNames, so I thought I’d include my remake of the Player type. The AutoComplete now includes DisplayNames in the format “DisplayName @Username”.
New Player type module
local Util = require(script.Parent.Parent.Shared.Util)
local Players = game:GetService("Players")
local function GetDisplayNamePair(list)
local names = {}
for _,player in list do
table.insert(names, `{player.DisplayName} @{player.Name}`)
end
return names
end
local playerType = {
Transform = function (text)
local findPlayer = Util.MakeFuzzyFinder(Players:GetPlayers())
local result = findPlayer(text)
if not result or #result == 0 then
local list = GetDisplayNamePair(Players:GetPlayers())
findPlayer = Util.MakeFuzzyFinder(list)
local fResult = findPlayer(text)
result = {}
for _,found in fResult do
table.insert(result, Players:FindFirstChild(found:split("@")[2]))
end
end
return result
end;
Validate = function (players)
return #players > 0, "No player with that name could be found."
end;
Autocomplete = function (players)
return GetDisplayNamePair(players)
end;
Parse = function (players)
return players[1]
end;
Default = function(player)
return player.Name
end;
ArgumentOperatorAliases = {
me = ".";
all = "*";
others = "**";
random = "?";
};
}
return function (cmdr)
cmdr:RegisterType("player", playerType)
cmdr:RegisterType("players", Util.MakeListableType(playerType, {
Prefixes = "% teamPlayers";
}))
end
This is especially useful if your game displays Players with only their DisplayName, and you want to avoid the extra effort of opening the Roblox menu to check who’s who.
I’m having an issue with creating types. I’ve tried everything.
Each time Autocomplete (except for the initial function) is called, this error is called.
00:41:36.568 ReplicatedStorage.CmdrClient.CmdrInterface.AutoComplete:122: attempt to perform arithmetic (sub) on nil and number - Client - AutoComplete:122
00:41:36.568 Stack Begin - Studio
00:41:36.568 Script 'ReplicatedStorage.CmdrClient.CmdrInterface.AutoComplete', Line 122 - function Show - Studio - AutoComplete:122
00:41:36.568 Script 'ReplicatedStorage.CmdrClient.CmdrInterface', Line 84 - function OnTextChanged - Studio - CmdrInterface:84
00:41:36.568 Script 'ReplicatedStorage.CmdrClient.CmdrInterface.Window', Line 328 - Studio - Window:328
00:41:36.568 Stack End - Studio
Here is the type code:
ANOMALYTYPAGE = {
[1] = "ItsPlasmaRBLX2",
[2] = "Packages",
[3] = "Spigot",
[4] = "Brick"
}
local Util = require(script.Parent.Parent.Shared.Util)
local anomalyTypageFinder = Util.MakeFuzzyFinder(ANOMALYTYPAGE)
local storedKeyType = {
Validate = function(anomalyName : string)
if typeof(anomalyName) == "string" then
return ANOMALYTYPAGE[anomalyName] ~= nil, "No anomaly with that name could be found."
end;
return false, "Anomaly name must be a string"
end;
Transform = function(text)
return anomalyTypageFinder(text)
end;
Autocomplete = function(anomalyName)
return Util.GetNames(ANOMALYTYPAGE)
end;
Parse = function(anomalyName : string)
return anomalyName
end;
}
return function (cmdr)
cmdr:RegisterType("anomaly", storedKeyType)
cmdr:RegisterType("anomalies", Util.MakeListableType(storedKeyType))
end
Side note, even if the Autocomplete function is called it will throw an error, regardless of what is in the function. This means if the function is blank, it will still throw an error.
That’s because for safety, you can’t run any commands until you setup a BeforeRun hook. Read the documentation to learn more on how to set it up. The link will take you to the beta version of the Cmdr docs. For clarification, a BeforeRun hook is what you will use for command permissions. It will check if the player attempting to execute the command is allowed to but you can define custom behavior/logic because you’re going to be the one writing it.
Then you probably didn’t do it correctly. The error clearly says you didn’t set up the BeforeRun hook. How did you set it up? Can you provide the code you used?
I’m having a very weird issue with Cmdr. I am making a viewstats command so that my Moderators can view other players stats by typing their username with the auto-complete menu if they’re in the server or use the @ prefix to type their full username if they’re not in the server. However, the issue is that when Cmdr gets to a point where it needs to return something inside the command, it just doesn’t. And that happens for every command for some really weird reason. After using commands a bunch more times, the very delayed command responses I should’ve gotten ages ago finally appear.
I tried using print statements and they got where they needed to. Once it gets to a return statement, it just self destructs.
Note: The game uses ProfileService and the game is called RoKarate. You can search it using the search bar and it’ll be the first game. I have confirmed that every variable gives what it’s supposed to such as the DataManager existing and the DataManager giving the current profile if they are in the server and all that.
Here is the following code I used:
return {
Name = "viewstats",
Aliases = {"stats"},
Description = "View a players stats.",
Group = "Moderator",
Args = {
{
Type = "player @ string",
Name = "player @ username",
Description = "The full username of the player."
}
}
}
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataManager = require(ServerStorage.DataManager) -- This does exist
local Format = require(ReplicatedStorage.Modules.FormatNumber.Simple) -- This does exist
local function toDHMS(seconds)
local days = math.floor(seconds / 86400)
local hours = math.floor((seconds % 86400) / 3600)
local minutes = math.floor((seconds % 3600) / 60)
local seconds = math.floor(seconds % 60)
return ("%i:%02i:%02i:%02i"):format(days,hours,minutes,seconds)
end
return function(context, player)
if typeof(player) == "Instance" then
local profile = DataManager:GetProfile(player) -- This does work
context:Reply(player.Name.."'s stats:")
context:Reply("---------------------------------------------")
context:Reply("Belt: "..profile.Data.Belt)
context:Reply("Strength: "..Format.Format(profile.Data.Strength))
context:Reply("Health: "..Format.Format(profile.Data.Health))
context:Reply("MaxStamina: "..Format.Format(profile.Data.MaxStamina))
context:Reply("Wins: "..Format.Format(profile.Data.Wins))
context:Reply("Kills: "..Format.Format(profile.Data.TotalKills))
context:Reply("Robux Donated: "..Format.Format(profile.Data.RobuxDonated))
context:Reply("Playtime: "..toDHMS(profile.Data.Playtime))
context:Reply("---------------------------------------------")
return "Successfully retrieved the players stats."
elseif typeof(player) == "string" then
local gotUserId, userId = pcall(function()
return Players:GetUserIdFromNameAsync(player)
end)
if not gotUserId then
return `Failed to get UserId associated with {player}.\nError: {userId}`
end
local profileStore = DataManager:GetProfileStore()
local profile = profileStore:ViewProfileAsync("Player_"..userId)
if profile == nil then
return player.." does not have any data!"
end
context:Reply(player.."'s stats:")
context:Reply("---------------------------------------------")
context:Reply("Belt: "..profile.Data.Belt)
context:Reply("Strength: "..Format.Format(profile.Data.Strength))
context:Reply("Health: "..Format.Format(profile.Data.Health))
context:Reply("MaxStamina: "..Format.Format(profile.Data.MaxStamina))
context:Reply("Wins: "..Format.Format(profile.Data.Wins))
context:Reply("Kills: "..Format.Format(profile.Data.TotalKills))
context:Reply("Robux Donated: "..Format.Format(profile.Data.RobuxDonated))
context:Reply("Playtime: "..toDHMS(profile.Data.Playtime))
context:Reply("---------------------------------------------")
return "Successfully retrieved the players stats."
end
end
I’m having an issue where the mobile keyboard constantly flickers on/off. Looks like it changes every frame. This starts happening when you tap the command panel.
All I’m doing is ‘:Toggle()’ once to open the gui.
this is incredible and i love it
however, i would like a feature where only a few people (like moderators, admins) can toggle the UI
cause right now any player can just press a given key to toggle the UI which is eh