chat_commands 1.1.0

Added an alias system so that a command can be called with different names.
The alias commands respects the permission system and can be used seemingly with the help and alias command.
The commands command still only lists the original/full command name, it doesn't list aliases
CreateCommand now has an addition argument commands can use: commandAliases

Added a new !alias or !aliases command
With these commands you can get the available alias(es) of a command by its original name or one of its alias
For example !alias god or !alias godmode

Some refactor to make the ChatListener function easier to read along with some comments to separate each command logic (built-in commands and "any other command")

Added CommandAliasesDoesNotExistError

Added GetCommandNameFromAlias util function
This commit is contained in:
Resxt 2023-06-17 10:25:39 +02:00
parent b3dd62f64e
commit 52820e82fc
2 changed files with 206 additions and 65 deletions

View File

@ -12,11 +12,13 @@ MP only scripts are in the [mp](mp) folder and ZM only scripts are in the [zm](z
The core script that holds the configuration, runs all the chat logic and holds utils function that are shared between all the `chat_command` scripts.
**[IMPORTANT]** Installing it is **mandatory** to make the commands work as this is the core of this whole system and all the command scripts depend on it.
**[IMPORTANT]** By default this script is made to be placed in the `scripts` folder. If you place it in the `scripts\mp` or `scripts\zm` folder instead then you will need to update the include of each command script accordingly (first line) or you will get errors.
**[IMPORTANT]** Installing `chat_commands.gsc` is **mandatory** to make the commands work as this is the core of this whole system and all the command scripts depend on it.
**[IMPORTANT]** By default `chat_commands.gsc` is made to be placed in the `scripts` folder.
If you place it in the `scripts\mp` or `scripts\zm` folder instead then you will need to update the include of each command script accordingly (first line) or you will get errors.
You simply have to replace `#include scripts\chat_commands` with `#include scripts\mp\chat_commands;` or `#include scripts\zm\chat_commands;` in each of your command script.
Also note that this script doesn't provide any command on its own. You must install at least one command script to be able to use commands. Otherwise it will always say that you don't have any command.
Also note that `chat_commands.gsc` doesn't provide any command on its own.
You must install at least one command script to be able to use commands. Otherwise it will always say that you don't have any command.
### Main features
@ -26,6 +28,7 @@ Also note that this script doesn't provide any command on its own. You must inst
- All exceptions are handled with error messages (no commands on the server, not enough arguments, command doesn't exist, command doesn't have any help message, player doesn't exist etc.)
- A `commands` command that lists all available commands on the server you're on dynamically (only lists commands you have access to if the permission system is enabled)
- A `help` command that explains how to use a given command. For example `help map` (only works on commands you have access to if the permission system is enabled)
- `alias` and `aliases` commands that list the available aliases for a command. For example `alias godmode` (only works on commands you have access to if the permission system is enabled)
- All commands that require a target work with `me`. Also it doesn't matter how you type the player's name as long as you type the full name.
- Configurable command prefix. Set to `!` by default
- A plugin system to easily allow adding/removing commands. Each command has its own GSC file to easily add/remove/review/configure your commands. This also makes contributing by creating a PR to add a command a lot easier

View File

@ -59,7 +59,7 @@ InitChatCommandsDvars()
<commandMinimumPermission> (optional, if no value is provided then anyone who's permission level is default or above can run the command) the minimum permission level required to run this command. For example if this is set to 3 then any user with permission level 3 or 4 will be able to run this command
<commandHelp> (optional) an array of the lines to print when typing the help command in the chat followed by a command name. You can also pass an array of one preset string to have it auto generated, for example: ["default_help_one_player"]
*/
CreateCommand(serverPorts, commandName, commandType, commandValue, commandMinimumPermission, commandHelp)
CreateCommand(serverPorts, commandName, commandType, commandValue, commandMinimumPermission, commandHelp, commandAliases)
{
currentPort = GetDvar("net_port");
@ -69,7 +69,7 @@ CreateCommand(serverPorts, commandName, commandType, commandValue, commandMinimu
{
level.commands[serverPort][commandName]["type"] = commandType;
if (IsDefined(commandHelp))
if (IsDefined(commandHelp) && commandHelp.size > 0)
{
commandHelpMessage = commandHelp;
commandHelpString = commandHelp[0];
@ -95,6 +95,11 @@ CreateCommand(serverPorts, commandName, commandType, commandValue, commandMinimu
level.commands[serverPort][commandName]["function"] = commandValue;
}
if (IsDefined(commandAliases) && commandAliases.size > 0)
{
level.commands[serverPort][commandName]["aliases"] = commandAliases;
}
if (IsDefined(commandMinimumPermission))
{
level.commands[serverPort][commandName]["permission"] = commandMinimumPermission;
@ -107,6 +112,35 @@ CreateCommand(serverPorts, commandName, commandType, commandValue, commandMinimu
}
}
ExecuteCommand(command, args, player)
{
if (command["type"] == "text")
{
player thread TellPlayer(command["text"], 2);
}
else if (command["type"] == "function")
{
error = player [[command["function"]]](args);
if (IsDefined(error))
{
player thread TellPlayer(error, 1.5);
}
}
}
TryExecuteCommand(commandValue, commandName, args, player)
{
if (!PermissionIsEnabled() || PlayerHasSufficientPermissions(player, commandValue["permission"]))
{
ExecuteCommand(commandValue, args, player);
}
else
{
player thread TellPlayer(InsufficientPermissionError(player GetPlayerPermissionLevel(), commandName, commandValue["permission"]), 1.5);
}
}
/* Chat section */
@ -184,10 +218,8 @@ ChatListener()
player thread TellPlayer(GetArrayKeys(level.commands[GetDvar("net_port")]), 2, true);
}
}
else
{
// help command
if (command == GetDvar("cc_prefix") + "help" && !IsDefined(level.commands[GetDvar("net_port")]["help"]) || command == GetDvar("cc_prefix") + "help" && IsDefined(level.commands[GetDvar("net_port")]["help"]) && args.size >= 1)
// help command (with args, for example help godmode)
else if (command == GetDvar("cc_prefix") + "help" && !IsDefined(level.commands[GetDvar("net_port")]["help"]) || command == GetDvar("cc_prefix") + "help" && IsDefined(level.commands[GetDvar("net_port")]["help"]) && args.size >= 1)
{
if (args.size < 1)
{
@ -219,49 +251,127 @@ ChatListener()
}
else
{
if (args[0] == "commands")
originalCommandName = GetCommandNameFromAlias(args[0]);
if (args[0] == "commands" || args[0] == "help" || args[0] == "aliases" || args[0] == "alias")
{
player thread TellPlayer(CommandHelpDoesNotExistError(args[0]), 1);
}
else
else if (args[0] == originalCommandName) // the command wasn't found while searching by its name and all the commands aliases
{
player thread TellPlayer(CommandDoesNotExistError(args[0]), 1);
}
}
}
}
// any other command
else
{
commandName = GetSubStr(command, 1);
commandValue = level.commands[GetDvar("net_port")][commandName];
commandHelp = level.commands[GetDvar("net_port")][originalCommandName]["help"];
if (IsDefined(commandHelp))
{
if (!PermissionIsEnabled() || PlayerHasSufficientPermissions(player, level.commands[GetDvar("net_port")][originalCommandName]["permission"]))
{
player thread TellPlayer(commandHelp, 1.5);
}
else
{
player thread TellPlayer(InsufficientPermissionError(player GetPlayerPermissionLevel(), args[0], level.commands[GetDvar("net_port")][originalCommandName]["permission"]), 1.5);
}
}
else
{
player thread TellPlayer(CommandHelpDoesNotExistError(args[0]), 1);
}
}
}
}
}
else if (command == GetDvar("cc_prefix") + "alias" || command == GetDvar("cc_prefix") + "aliases") // alias/aliases command
{
if (args.size < 1)
{
player thread TellPlayer(NotEnoughArgsError(1), 1.5);
}
else
{
commandValue = level.commands[GetDvar("net_port")][args[0]];
if (IsDefined(commandValue))
{
if (!PermissionIsEnabled() || PlayerHasSufficientPermissions(player, commandValue["permission"]))
{
if (commandValue["type"] == "text")
{
player thread TellPlayer(commandValue["text"], 2);
}
else if (commandValue["type"] == "function")
{
error = player [[commandValue["function"]]](args);
commandAliases = commandValue["aliases"];
if (IsDefined(error))
if (IsDefined(commandAliases) && commandAliases.size > 0)
{
player thread TellPlayer(error, 1.5);
player thread TellPlayer(commandAliases, 1.5);
}
else
{
player thread TellPlayer(CommandAliasesDoesNotExistError(args[0]), 1);
}
}
else
{
player thread TellPlayer(InsufficientPermissionError(player GetPlayerPermissionLevel(), commandName, commandValue["permission"]), 1.5);
player thread TellPlayer(InsufficientPermissionError(player GetPlayerPermissionLevel(), args[0], commandValue["permission"]), 1.5);
}
}
else
{
player thread TellPlayer(CommandDoesNotExistError(commandName), 1);
originalCommandName = GetCommandNameFromAlias(args[0]);
if (args[0] == "commands" || args[0] == "help" || args[0] == "aliases" || args[0] == "alias")
{
player thread TellPlayer(CommandAliasesDoesNotExistError(args[0]), 1);
}
else if (args[0] == originalCommandName) // the command wasn't found while searching by its name and all the commands aliases
{
player thread TellPlayer(CommandDoesNotExistError(args[0]), 1);
}
else
{
commandAliases = level.commands[GetDvar("net_port")][originalCommandName]["aliases"];
if (IsDefined(commandAliases))
{
if (!PermissionIsEnabled() || PlayerHasSufficientPermissions(player, level.commands[GetDvar("net_port")][originalCommandName]["permission"]))
{
commandAliases = AddElementToArray(commandAliases, originalCommandName);
player thread TellPlayer(commandAliases, 1.5);
}
else
{
player thread TellPlayer(InsufficientPermissionError(player GetPlayerPermissionLevel(), args[0], level.commands[GetDvar("net_port")][originalCommandName]["permission"]), 1.5);
}
}
else
{
player thread TellPlayer(CommandAliasesDoesNotExistError(args[0]), 1);
}
}
}
}
}
else // any other command
{
inputCommandName = GetSubStr(command, 1);
commandValue = level.commands[GetDvar("net_port")][inputCommandName];
if (IsDefined(commandValue)) // try to find the command by its original name
{
TryExecuteCommand(commandValue, inputCommandName, args, player);
}
else // try to find the command by one of its aliases
{
originalCommandName = GetCommandNameFromAlias(inputCommandName);
if (inputCommandName == originalCommandName) // the command wasn't found while searching by its name and all the commands aliases
{
player thread TellPlayer(CommandDoesNotExistError(inputCommandName), 1);
}
else
{
TryExecuteCommand(level.commands[GetDvar("net_port")][originalCommandName], inputCommandName, args, player);
}
}
}
@ -354,6 +464,11 @@ CommandHelpDoesNotExistError(commandName)
return array("The command " + commandName + " doesn't have any help message");
}
CommandAliasesDoesNotExistError(commandName)
{
return array("The command " + commandName + " doesn't have any alias");
}
InsufficientPermissionError(playerPermissionLevel, commandName, requiredPermissionLevel)
{
if (playerPermissionLevel == 0)
@ -530,6 +645,29 @@ PlayerHasSufficientPermissions(player, targetedPermissionLevel)
return playerPermissionLevel >= targetedPermissionLevel;
}
/*
Returns the original command name of <aliasToFind> if it exists
If <aliasToFind> is not a valid alias then it just returns itself meaning it didn't find a related command
*/
GetCommandNameFromAlias(aliasToFind)
{
foreach (commandName in GetArrayKeys(level.commands[GetDvar("net_port")]))
{
if (IsDefined(level.commands[GetDvar("net_port")][commandName]["aliases"]))
{
foreach (alias in level.commands[GetDvar("net_port")][commandName]["aliases"])
{
if (alias == aliasToFind)
{
return commandName;
}
}
}
}
return aliasToFind;
}
DvarIsInitialized(dvarName)
{
result = GetDvar(dvarName);