Cmdr: A fully extensible and type safe command console for Roblox Developers

image
Cmdr Website

Cmdr is a fully extensible and type safe command console for Roblox developers.

  • Great for admin commands, but does much more.
  • Make commands that tie in specifically with your game systems.
  • Intelligent autocompletion and instant validation.
  • Run commands programmatically on behalf of the local user.
  • Bind commands to user input.
  • Secure: the client and server both validate input separately.
  • Embedded commands: dynamically use the output of an inner command when running a command.

Demo:

Cmdr is designed specifically so that you can write your own commands and argument types, so that it can fit right in with the rest of your game. In addition to the standard moderation commands (teleport, kill, kick, ban), Cmdr is also great for debug commands in your game (say, if you wanted to have a command to give you a weapon, reset a round, teleport you between places in your universe).

Cmdr has a robust and friendly type validation system (making sure strings are strings, players are players, etc), which can give end users real time command validation as they type, and automatic error messages. By the time the command actually gets to your code, you can be assured that all of the arguments are present and of the correct type.

GitHub Repository, installation instructions, and docs

Key Features

Potential use cases

Cmdr will work out of the box with minimal configuration, filling the role of admin commands in your game instantly, and doing a great job at it. But Cmdr can also be your best friend when debugging a game, making use of custom commands that can print information to the console based on certain parameters or force game state so you can test a specific scenario. The intelligent and type-safe auto-completion makes it great for commands that manage or modify player data.

But it doesn’t stop there. Cmdr can also be deeply integrated into the core of your game. For example, we can bind commands to any user input. This is very powerful: You could define a command, like cast_ability, which casts a certain move in your game. Then, you could have a keybindings menu that allows the user to rebind keys, and whenever they do, it runs bind KEY cast_ability ABILITYNAME in the background. By separating the user input from our hypothetical ability code, our code is made more robust as we can now trigger abilities from a number of possible events and places in our code, in addition to the bound key.

As another example of the versatile meta-commands, we could make Cmdr run any chat message you send as a command if it starts with !, with the following command:

bind @me runif startsWith ! $1

One more: We can make a command that kills whatever player we are hovering our mouse over by making use of the built-in hover command, which outputs the name of whatever player you’re currently hovering over. Not too useful by itself, but by using it as an embedded command, we can do something quite special:

alias kill_hover_target kill ${hover}

This creates a new command called “kill_hover_target”, which when run does exactly what it says on the tin. Since embedded commands are just normal commands that you can define yourself, the possibilities here really are endless.

Closing thoughts

I’ve been iterating on Cmdr for the past few months, and I’m very excited to have finally arrived at a point that I’m comfortable calling “version 1”. I’ve had great success and productivity boosts using Cmdr in my own projects, and I hope that you can as well. The documentation is quite detailed, but if you have any questions or problems please feel free to create an issue on the GitHub repository and I will do my best to help out. Contributions to the project are welcome as well :slight_smile:

That’s all for now! Evaera, out.

193 Likes

I really recommend this, it’s awesome. Command management and interface done right for once. Really easy to use as well.

14 Likes

This is amazing :open_mouth:

2 Likes

I was going to make a system like this very soon because my custom moderation console is quite outdated. I definitely plan on using this. :smiley:

2 Likes

Incredible

2 Likes

That’s so smart!

2 Likes

This looks amazing!

2 Likes

Looks amazing. Well done!

1 Like

evaera does it again. This is awesome.

4 Likes

Admin commands on steroids? Sounds really cool! :grinning:

5 Likes

I’m going to be using this a lot! It’s going to help me so much!

2 Likes

Brilliant!

Can you upload it as a Model so it’s easy to take and also make is accessible by uploading it as a module so people can just do require(id)

I don’t like RoStrap, so I’m not going to use it, and I know you have a download in the releases section but I think it’s better to provide multiple ways to access it.

(I’m just trying to convince you to upload it as a model not trying to be a hater or anything like that)


nvm

1 Like

12 Likes

This is amazing! So useful

1 Like

Looks really nice! Will certainly save a lot of people a lot of time, including myself, when considering creating their own ingame command systems; I’m sure it works and looks a lot better than most custom ones too!

1 Like

I like the environment but I have my own command language which is a sort of much worse version of Lisp. How hard would it be to change the command syntax?

1 Like

Cmdr v1.1

Cmdr’s first major update introduces a number of exciting new features and changes!

Command history

  • Up/down arrow now traverses command history when you haven’t entered any text.
  • New history utility command which dynamically returns your previously-entered commands based on a number index.
  • New alias ! <number> to re-run previous commands.
    • ! -1 re-reruns your last command.
    • ! 2 re-runs your second command.
  • New alias !! to re-run your last command.
  • New alias ^ <search> <replace> to re-run your last command with string substitution, replacing search with replace.

New utility commands

  • history (see above)
  • position [player]: Returns the Vector3 position of a player (or yourself if omitted) as a string X,Y,Z.
  • replace <haystack> <needle> <replacement>: Substitutes text inside haystack matching Lua pattern needle with replacement.
  • discard <command string>: Identical to run, except the return value is discarded (always returns "").
  • clear: Clears the console

New default types

  • Plural primitives (strings, numbers, integers, booleans)
    • Plural types simply resolve into an array of the named type.
  • brickColor(s)
  • teamColor(s): Resolve into a BrickColor based on the color of a Team
  • color3(s)
  • hexColor3(s): Resolve into a Color3 from a hexadecimal color
  • brickColor3(s): Resolve into a Color3 from a BrickColor
  • vector3(s), vector(2)s
  • duration(s): Resolve human-readable times like 20Minutes, 2Hours, 1Year into a number of seconds.

Usage improvements

  • Cmdr now supports escape sequences
    • \\ for escaping a literal backslash
    • \" and \' for escaping quotes inside of strings
    • \t
      • Tab stops display as expected when \t is present in a line on the console
    • \n
      • New lines are not displayed in the console as of right now and are displayed as a space. However, \n literals may still be useful for custom commands.
    • \xA9 (2-digit) and \u2661 (4-digit) hexadecimal unicode escapes
    • \$ for escaping argument replacements and embedded commands in command strings only.
    • Invalid escape sequences are left in-place.
  • help command now lists command aliases
  • teleport and to now accept a Vector3 with the @ prefix

API Improvements and Changes

  • Cmdr now enforces that types begin with a lowercase letter or digit for consistency.
  • Dispatcher:RegisterHooksIn, RegisterTypesIn, and RegisterCommandsIn now allow nesting via folders.
  • Dispatcher:AddHook has been renamed to Dispatcher:RegisterHook. The old name still exists as a fallback, but is undocumented and may be removed in the future.
  • Cmdr now throws an error if a command has both Data and Run (not a bug, but if someone is doing this then they are confused)
  • Hooks now have an optional third parameter priority. Hooks run in order of priority; lower numbers run first. The default priority is 0.
  • CommandContexts now have an empty State table. This is intended to be used in combination with the BeforeRun hook to allow you to add custom information to this command that you can consume inside of your command logic or other hooks.
    • For example, if you want many commands to have different behavior based on someone’s rank, you can add their rank in the State table for your commands to consume and branch off of.
  • New function CmdrClient:SetMashToEnable(true) to enable Mash to Enable mode, which requires the player to press the activation key 7 times in quick succession to open the Cmdr menu for the first time. This is not meant as a security feature, but rather as a way to ensure that the console is not accidentally obtrusive to regular players of your game.
  • New client-only function Dispatcher:GetHistory() to get an array of the local user’s command history. This only includes commands actually typed by the user, no embedded or programmatically run commands.
  • Dispatcher:EvaluateAndRun now accepts an options table in the third parameter rather than Data.
  • Automatic Execution: Commands can now contain an AutoExec table which contains commands to execute immediately as the command is registered.
    • This is useful for registering aliases associated with your command or initializing state.
    • Commands listed in AutoExec are deferred until the end of the Lua cycle, which eliminates any possibility of ordering issues caused by commands being registered out of order.

Utility methods

  • Util.MakeEnumType and Util.MakeFuzzyFinder now accept Enums and arrays of tables with a Name key. (These functions can already accept: array of strings, array of Instances, array of EnumItems, or a single Instance whose children are used).
  • New functions Util.Map and Util.Each for mapping values of an array and tuple respectively.
  • New function Util.MakeSequenceType for quickly creating a type that contains a value sequence, like Vector3 or Color3. The delimeter can be either , or whitespace, checking , first.
  • New functions Util.SplitPrioritizedDelimeter, Util.ParseEscapeSequences, and Util.EmulateTabstops.

Bug fixes

  • announce command text is now filtered through chat filter
  • Added an additional check that RoStrap is being used to help prevent false positives
  • Fixed a bug preventing command data from being accessible

roblox-ts npm package

Cmdr is now available as an npm package for usage in roblox-ts.

Future road map

Here is a preview of some planned changes and features looking ahead to the next major version:

  • Separate bind states for running commands on keyup/keydown
  • Major update to meta-commands
    • runif will receive a full suite of comparison operations
    • General support of && in all command strings (not just alias), with ability to escape &&
    • Bind commands to network events
  • Automatically extrapolating number of arguments present in an alias, with ability to specify inline types for alias arguments.
  • Ability to override functions from the type definition on a per-command basis, enabling command-specific autocomplete functionality
  • Visual indication of available prefix types

Contributors

Thanks to the following developers for contributing changes to Cmdr:

21 Likes

That’s an amazing thingo. May use in the future.

You’re a machine! There’s some excellent work done in this update (in other words, time for me to install)

2 Likes