|
@@ -3,10 +3,14 @@
|
|
|
|
|
|
#include "atcommand.hpp"
|
|
|
|
|
|
+#include <set>
|
|
|
+#include <unordered_map>
|
|
|
+
|
|
|
#include <math.h>
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
#include "../common/cbasetypes.hpp"
|
|
|
+#include "../common/database.hpp"
|
|
|
#include "../common/cli.hpp"
|
|
|
#include "../common/conf.hpp"
|
|
|
#include "../common/malloc.hpp"
|
|
@@ -50,11 +54,12 @@
|
|
|
#include "storage.hpp"
|
|
|
#include "trade.hpp"
|
|
|
|
|
|
+using namespace rathena;
|
|
|
+
|
|
|
#define ATCOMMAND_LENGTH 50
|
|
|
#define ACMD_FUNC(x) static int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
|
|
|
|
|
|
typedef struct AtCommandInfo AtCommandInfo;
|
|
|
-typedef struct AliasInfo AliasInfo;
|
|
|
|
|
|
int atcmd_binding_count = 0;
|
|
|
|
|
@@ -73,9 +78,10 @@ struct AtCommandInfo {
|
|
|
uint8 restriction; /// Restrictions see enum e_restict
|
|
|
};
|
|
|
|
|
|
-struct AliasInfo {
|
|
|
+struct s_atcommand_alias_info{
|
|
|
AtCommandInfo *command;
|
|
|
- char alias[ATCOMMAND_LENGTH];
|
|
|
+ std::set<std::string> aliases;
|
|
|
+ std::string help;
|
|
|
};
|
|
|
|
|
|
|
|
@@ -83,8 +89,100 @@ char atcommand_symbol = '@'; // first char of the commands
|
|
|
char charcommand_symbol = '#';
|
|
|
|
|
|
static DBMap* atcommand_db = NULL; //name -> AtCommandInfo
|
|
|
-static DBMap* atcommand_alias_db = NULL; //alias -> AtCommandInfo
|
|
|
-static config_t atcommand_config;
|
|
|
+
|
|
|
+static AtCommandInfo* get_atcommandinfo_byname( const char* name );
|
|
|
+
|
|
|
+class AtcommandAliasDatabase : public TypesafeYamlDatabase<std::string, s_atcommand_alias_info>{
|
|
|
+private:
|
|
|
+ std::unordered_map<std::string, std::string> aliases;
|
|
|
+
|
|
|
+public:
|
|
|
+ AtcommandAliasDatabase() : TypesafeYamlDatabase( "ATCOMMAND_DB", 1 ){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void clear();
|
|
|
+ const std::string getDefaultLocation();
|
|
|
+ uint64 parseBodyNode( const YAML::Node& node );
|
|
|
+ const char* checkAlias( const char* alias );
|
|
|
+};
|
|
|
+
|
|
|
+void AtcommandAliasDatabase::clear(){
|
|
|
+ TypesafeYamlDatabase::clear();
|
|
|
+ this->aliases.clear();
|
|
|
+}
|
|
|
+
|
|
|
+const std::string AtcommandAliasDatabase::getDefaultLocation(){
|
|
|
+ return std::string(conf_path) + "/atcommands.yml";
|
|
|
+}
|
|
|
+
|
|
|
+uint64 AtcommandAliasDatabase::parseBodyNode( const YAML::Node& node ){
|
|
|
+ std::string command;
|
|
|
+
|
|
|
+ if( !this->asString( node, "Command", command ) ){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ AtCommandInfo* commandinfo = get_atcommandinfo_byname( command.c_str() );
|
|
|
+
|
|
|
+ if( commandinfo == nullptr ){
|
|
|
+ this->invalidWarning( node["Command"], "Command %s does not exist.\n", command.c_str() );
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::shared_ptr<s_atcommand_alias_info> info = this->find( command );
|
|
|
+ bool exists = info != nullptr;
|
|
|
+
|
|
|
+ if( !exists ){
|
|
|
+ info = std::make_shared<s_atcommand_alias_info>();
|
|
|
+ info->command = commandinfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ if( this->nodeExists( node, "Help" ) ){
|
|
|
+ std::string help;
|
|
|
+
|
|
|
+ if( !this->asString( node, "Help", help ) ){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ info->help = help;
|
|
|
+ }
|
|
|
+
|
|
|
+ if( this->nodeExists( node, "Aliases" ) ){
|
|
|
+ const YAML::Node& aliasesNode = node["Aliases"];
|
|
|
+
|
|
|
+ if( !aliasesNode.IsSequence() ){
|
|
|
+ this->invalidWarning( aliasesNode, "Aliases should be a sequence.\n" );
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ for( const auto& subNode : aliasesNode ){
|
|
|
+ std::string alias = subNode.as<std::string>();
|
|
|
+
|
|
|
+ info->aliases.insert( alias );
|
|
|
+ this->aliases[alias] = command;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if( !exists ){
|
|
|
+ this->put( command, info );
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+const char* AtcommandAliasDatabase::checkAlias( const char* alias ){
|
|
|
+ std::string alias_str( alias );
|
|
|
+ std::string* command = util::umap_find( this->aliases, alias_str );
|
|
|
+
|
|
|
+ if( command == nullptr ){
|
|
|
+ return alias;
|
|
|
+ }else{
|
|
|
+ return command->c_str();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+AtcommandAliasDatabase atcommand_alias_db;
|
|
|
|
|
|
static char atcmd_output[CHAT_SIZE_MAX];
|
|
|
static char atcmd_player_name[NAME_LENGTH];
|
|
@@ -93,7 +191,6 @@ const char *parent_cmd;
|
|
|
struct atcmd_binding_data** atcmd_binding;
|
|
|
|
|
|
static AtCommandInfo* get_atcommandinfo_byname(const char *name); // @help
|
|
|
-static const char* atcommand_checkalias(const char *aliasname); // @help
|
|
|
static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand); // @help
|
|
|
static void warp_get_suggestions(struct map_session_data* sd, const char *name); // @rura, @warp, @mapmove
|
|
|
|
|
@@ -115,34 +212,25 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
|
|
|
* @param name the name of the command to retrieve help information for
|
|
|
* @return the string associated with the command, or NULL
|
|
|
*/
|
|
|
-static const char* atcommand_help_string(const char* command)
|
|
|
-{
|
|
|
- const char* str = NULL;
|
|
|
- config_setting_t* info;
|
|
|
-
|
|
|
- if( *command == atcommand_symbol || *command == charcommand_symbol )
|
|
|
- {// remove the prefix symbol for the raw name of the command
|
|
|
- command ++;
|
|
|
+static const char* atcommand_help_string( const char* command ){
|
|
|
+ // remove the prefix symbol for the raw name of the command
|
|
|
+ if( *command == atcommand_symbol || *command == charcommand_symbol ){
|
|
|
+ command++;
|
|
|
}
|
|
|
|
|
|
// convert alias to the real command name
|
|
|
- command = atcommand_checkalias(command);
|
|
|
+ command = atcommand_alias_db.checkAlias( command );
|
|
|
|
|
|
// attempt to find the first default help command
|
|
|
- info = config_lookup(&atcommand_config, "help");
|
|
|
-
|
|
|
- if( info == NULL )
|
|
|
- {// failed to find the help property in the configuration file
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ std::shared_ptr<s_atcommand_alias_info> info = atcommand_alias_db.find( command );
|
|
|
|
|
|
- if( !config_setting_lookup_string( info, command, &str ) )
|
|
|
- {// failed to find the matching help string
|
|
|
- return NULL;
|
|
|
+ // failed to find the help property in the configuration file
|
|
|
+ if( info == nullptr ){
|
|
|
+ return nullptr;
|
|
|
}
|
|
|
|
|
|
// push the result from the method
|
|
|
- return str;
|
|
|
+ return info->help.c_str();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1265,7 +1353,7 @@ ACMD_FUNC(item)
|
|
|
nullpo_retr(-1, sd);
|
|
|
memset(item_name, '\0', sizeof(item_name));
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (!strcmpi(parent_cmd,"itembound")) {
|
|
|
if (!message || !*message || (
|
|
@@ -1342,7 +1430,7 @@ ACMD_FUNC(item2)
|
|
|
|
|
|
memset(item_name, '\0', sizeof(item_name));
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (!strcmpi(parent_cmd+1,"itembound2")) {
|
|
|
if (!message || !*message || (
|
|
@@ -1570,27 +1658,17 @@ ACMD_FUNC(joblevelup)
|
|
|
/*==========================================
|
|
|
* @help
|
|
|
*------------------------------------------*/
|
|
|
-ACMD_FUNC(help)
|
|
|
-{
|
|
|
- config_setting_t *help;
|
|
|
- const char *text = NULL;
|
|
|
- const char *command_name = NULL;
|
|
|
- const char *default_command = "help";
|
|
|
+ACMD_FUNC(help){
|
|
|
+ const char *command_name = nullptr;
|
|
|
|
|
|
nullpo_retr(-1, sd);
|
|
|
|
|
|
- help = config_lookup(&atcommand_config, "help");
|
|
|
- if (help == NULL) {
|
|
|
- clif_displaymessage(fd, msg_txt(sd,27)); // "Commands help is not available."
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
if (!message || !*message) {
|
|
|
- command_name = default_command; // If no command_name specified, display help for @help.
|
|
|
+ command_name = "help"; // If no command_name specified, display help for @help.
|
|
|
} else {
|
|
|
if (*message == atcommand_symbol || *message == charcommand_symbol)
|
|
|
++message;
|
|
|
- command_name = atcommand_checkalias(message);
|
|
|
+ command_name = atcommand_alias_db.checkAlias(message);
|
|
|
}
|
|
|
|
|
|
if (!pc_can_use_command(sd, command_name, COMMAND_ATCOMMAND)) {
|
|
@@ -1600,7 +1678,12 @@ ACMD_FUNC(help)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (!config_setting_lookup_string(help, command_name, &text)) {
|
|
|
+ // attempt to find the first default help command
|
|
|
+ std::shared_ptr<s_atcommand_alias_info> info = atcommand_alias_db.find( command_name );
|
|
|
+
|
|
|
+ const char* text = info != nullptr ? info->help.c_str() : nullptr;
|
|
|
+
|
|
|
+ if( text == nullptr ){
|
|
|
sprintf(atcmd_output, msg_txt(sd,988), atcommand_symbol, command_name); // There is no help for %c%s.
|
|
|
clif_displaymessage(fd, atcmd_output);
|
|
|
atcommand_get_suggestions(sd, command_name, true);
|
|
@@ -1611,23 +1694,17 @@ ACMD_FUNC(help)
|
|
|
clif_displaymessage(fd, atcmd_output);
|
|
|
|
|
|
{ // Display aliases
|
|
|
- DBIterator* iter;
|
|
|
- AtCommandInfo *command_info;
|
|
|
- AliasInfo *alias_info = NULL;
|
|
|
StringBuf buf;
|
|
|
bool has_aliases = false;
|
|
|
|
|
|
StringBuf_Init(&buf);
|
|
|
StringBuf_AppendStr(&buf, msg_txt(sd,990)); // Available aliases:
|
|
|
- command_info = get_atcommandinfo_byname(command_name);
|
|
|
- iter = db_iterator(atcommand_alias_db);
|
|
|
- for (alias_info = (AliasInfo *)dbi_first(iter); dbi_exists(iter); alias_info = (AliasInfo *)dbi_next(iter)) {
|
|
|
- if (alias_info->command == command_info) {
|
|
|
- StringBuf_Printf(&buf, " %s", alias_info->alias);
|
|
|
- has_aliases = true;
|
|
|
- }
|
|
|
+
|
|
|
+ for( const std::string& alias : info->aliases ){
|
|
|
+ StringBuf_Printf( &buf, " %s", alias.c_str() );
|
|
|
+ has_aliases = true;
|
|
|
}
|
|
|
- dbi_destroy(iter);
|
|
|
+
|
|
|
if (has_aliases)
|
|
|
clif_displaymessage(fd, StringBuf_Value(&buf));
|
|
|
StringBuf_Destroy(&buf);
|
|
@@ -2126,7 +2203,7 @@ ACMD_FUNC(monster)
|
|
|
if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit)
|
|
|
number = battle_config.atc_spawn_quantity_limit;
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (strcmp(parent_cmd, "monstersmall") == 0)
|
|
|
size = SZ_MEDIUM; // This is just gorgeous [mkbu95]
|
|
@@ -2201,7 +2278,7 @@ ACMD_FUNC(killmonster)
|
|
|
map_id = sd->bl.m;
|
|
|
}
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
drop_flag = strcmp(parent_cmd, "killmonster2");
|
|
|
|
|
@@ -2977,7 +3054,7 @@ ACMD_FUNC(char_ban)
|
|
|
memset(atcmd_output, '\0', sizeof(atcmd_output));
|
|
|
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (strcmpi(parent_cmd,"charban") == 0)
|
|
|
bantype = CHRIF_OP_BAN;
|
|
@@ -3058,7 +3135,7 @@ ACMD_FUNC(char_unban){
|
|
|
memset(atcmd_output, '\0', sizeof(atcmd_output));
|
|
|
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (strcmpi(parent_cmd,"charunban") == 0)
|
|
|
unbantype = CHRIF_OP_UNBAN;
|
|
@@ -3846,13 +3923,6 @@ ACMD_FUNC(reload) {
|
|
|
|
|
|
config_destroy(&run_test);
|
|
|
|
|
|
- if (conf_read_file(&run_test, ATCOMMAND_CONF_FILENAME)) {
|
|
|
- clif_displaymessage(fd, msg_txt(sd,1037)); // Error reading atcommand_athena.conf, reload failed.
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- config_destroy(&run_test);
|
|
|
-
|
|
|
atcommand_doload();
|
|
|
pc_groups_reload();
|
|
|
clif_displaymessage(fd, msg_txt(sd,254)); // GM command configuration has been reloaded.
|
|
@@ -8463,7 +8533,7 @@ ACMD_FUNC(cash)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if( !strcmpi(parent_cmd,"cash") )
|
|
|
{
|
|
@@ -8534,7 +8604,7 @@ ACMD_FUNC(clone)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if (strcmpi(parent_cmd, "clone") == 0)
|
|
|
flag = 1;
|
|
@@ -8718,7 +8788,7 @@ ACMD_FUNC(itemlist)
|
|
|
|
|
|
nullpo_retr(-1, sd);
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
if( strcmp(parent_cmd, "storagelist") == 0 ) {
|
|
|
location = "storage";
|
|
@@ -9291,7 +9361,7 @@ ACMD_FUNC(addperm) {
|
|
|
bool add;
|
|
|
int i;
|
|
|
|
|
|
- parent_cmd = atcommand_checkalias(command+1);
|
|
|
+ parent_cmd = atcommand_alias_db.checkAlias(command+1);
|
|
|
|
|
|
add = (strcmpi(parent_cmd, "addperm") == 0);
|
|
|
|
|
@@ -10390,20 +10460,10 @@ static AtCommandInfo* get_atcommandinfo_byname(const char *name)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static const char* atcommand_checkalias(const char *aliasname)
|
|
|
-{
|
|
|
- AliasInfo *alias_info = NULL;
|
|
|
- if ((alias_info = (AliasInfo*)strdb_get(atcommand_alias_db, aliasname)) != NULL)
|
|
|
- return alias_info->command->command;
|
|
|
- return aliasname;
|
|
|
-}
|
|
|
-
|
|
|
/// AtCommand suggestion
|
|
|
static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand) {
|
|
|
DBIterator* atcommand_iter;
|
|
|
- DBIterator* alias_iter;
|
|
|
AtCommandInfo* command_info = NULL;
|
|
|
- AliasInfo* alias_info = NULL;
|
|
|
AtCommandType type = atcommand ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND;
|
|
|
char* full_match[MAX_SUGGESTIONS];
|
|
|
char* suggestions[MAX_SUGGESTIONS];
|
|
@@ -10415,7 +10475,6 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
|
|
|
return;
|
|
|
|
|
|
atcommand_iter = db_iterator(atcommand_db);
|
|
|
- alias_iter = db_iterator(atcommand_alias_db);
|
|
|
|
|
|
// Build the matches
|
|
|
for (command_info = (AtCommandInfo*)dbi_first(atcommand_iter); dbi_exists(atcommand_iter); command_info = (AtCommandInfo*)dbi_next(atcommand_iter)) {
|
|
@@ -10431,16 +10490,25 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- for (alias_info = (AliasInfo *)dbi_first(alias_iter); dbi_exists(alias_iter); alias_info = (AliasInfo *)dbi_next(alias_iter)) {
|
|
|
- match = strstr(alias_info->alias, name);
|
|
|
- can_use = pc_can_use_command(sd, alias_info->command->command, type);
|
|
|
- if ( prefix_count < MAX_SUGGESTIONS && match == alias_info->alias && can_use) {
|
|
|
- suggestions[prefix_count] = alias_info->alias;
|
|
|
- ++prefix_count;
|
|
|
- }
|
|
|
- if ( full_count < MAX_SUGGESTIONS && match != NULL && match != alias_info->alias && can_use ) {
|
|
|
- full_match[full_count] = alias_info->alias;
|
|
|
- ++full_count;
|
|
|
+ for( auto& pair : atcommand_alias_db ){
|
|
|
+ std::shared_ptr<s_atcommand_alias_info> info = pair.second;
|
|
|
+
|
|
|
+ if( pc_can_use_command( sd, info->command->command, type ) ){
|
|
|
+ for( const std::string& alias_str : info->aliases ){
|
|
|
+ char* alias = const_cast<char *>(alias_str.c_str());
|
|
|
+
|
|
|
+ match = strstr( alias, name );
|
|
|
+
|
|
|
+ if( prefix_count < MAX_SUGGESTIONS && match == alias ){
|
|
|
+ suggestions[prefix_count] = alias;
|
|
|
+ ++prefix_count;
|
|
|
+ }
|
|
|
+
|
|
|
+ if( full_count < MAX_SUGGESTIONS && match != NULL && match != alias ){
|
|
|
+ full_match[full_count] = alias;
|
|
|
+ ++full_count;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -10467,7 +10535,6 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
|
|
|
}
|
|
|
|
|
|
dbi_destroy(atcommand_iter);
|
|
|
- dbi_destroy(alias_iter);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -10543,7 +10610,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|
|
if (n < 1)
|
|
|
return false; // No command found. Display as normal message.
|
|
|
|
|
|
- info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
|
|
|
+ info = get_atcommandinfo_byname(atcommand_alias_db.checkAlias(command + 1));
|
|
|
if (!info || info->char_groups[sd->group_pos] == 0) // If we can't use or doesn't exist: don't even display the command failed message
|
|
|
return false;
|
|
|
}
|
|
@@ -10599,7 +10666,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|
|
}
|
|
|
|
|
|
//Grab the command information and check for the proper GM level required to use it or if the command exists
|
|
|
- info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
|
|
|
+ info = get_atcommandinfo_byname(atcommand_alias_db.checkAlias(command + 1));
|
|
|
if (info == NULL) {
|
|
|
if (pc_get_group_level(sd) == 0) // TODO: remove or replace with proper permission
|
|
|
return false;
|
|
@@ -10647,98 +10714,6 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-/*==========================================
|
|
|
- *
|
|
|
- *------------------------------------------*/
|
|
|
-static void atcommand_config_read(const char* config_filename)
|
|
|
-{
|
|
|
- config_setting_t *aliases = NULL, *help = NULL;
|
|
|
- const char *symbol = NULL;
|
|
|
- int num_aliases = 0;
|
|
|
-
|
|
|
- if (conf_read_file(&atcommand_config, config_filename))
|
|
|
- return;
|
|
|
-
|
|
|
- // Command symbols
|
|
|
- if (config_lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) {
|
|
|
- if (ISPRINT(*symbol) && // no control characters
|
|
|
- *symbol != '/' && // symbol of client commands
|
|
|
- *symbol != '%' && // symbol of party chat
|
|
|
- *symbol != '$' && // symbol of guild chat
|
|
|
- *symbol != charcommand_symbol)
|
|
|
- atcommand_symbol = *symbol;
|
|
|
- }
|
|
|
-
|
|
|
- if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) {
|
|
|
- if (ISPRINT(*symbol) && // no control characters
|
|
|
- *symbol != '/' && // symbol of client commands
|
|
|
- *symbol != '%' && // symbol of party chat
|
|
|
- *symbol != '$' && // symbol of guild chat
|
|
|
- *symbol != atcommand_symbol)
|
|
|
- charcommand_symbol = *symbol;
|
|
|
- }
|
|
|
-
|
|
|
- // Command aliases
|
|
|
- aliases = config_lookup(&atcommand_config, "aliases");
|
|
|
- if (aliases != NULL) {
|
|
|
- int i = 0;
|
|
|
- int count = config_setting_length(aliases);
|
|
|
-
|
|
|
- for (i = 0; i < count; ++i) {
|
|
|
- config_setting_t *command;
|
|
|
- const char *commandname = NULL;
|
|
|
- int j = 0, alias_count = 0;
|
|
|
- AtCommandInfo *commandinfo = NULL;
|
|
|
-
|
|
|
- command = config_setting_get_elem(aliases, i);
|
|
|
- if (config_setting_type(command) != CONFIG_TYPE_ARRAY)
|
|
|
- continue;
|
|
|
- commandname = config_setting_name(command);
|
|
|
- if (!atcommand_exists(commandname)) {
|
|
|
- ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname);
|
|
|
- continue;
|
|
|
- }
|
|
|
- commandinfo = get_atcommandinfo_byname(commandname);
|
|
|
- alias_count = config_setting_length(command);
|
|
|
- for (j = 0; j < alias_count; ++j) {
|
|
|
- const char *alias = config_setting_get_string_elem(command, j);
|
|
|
- if (alias != NULL) {
|
|
|
- AliasInfo *alias_info;
|
|
|
- if (strdb_exists(atcommand_alias_db, alias)) {
|
|
|
- ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias);
|
|
|
- continue;
|
|
|
- }
|
|
|
- CREATE(alias_info, AliasInfo, 1);
|
|
|
- alias_info->command = commandinfo;
|
|
|
- safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias));
|
|
|
- strdb_put(atcommand_alias_db, alias, alias_info);
|
|
|
- ++num_aliases;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Commands help
|
|
|
- // We only check if all commands exist
|
|
|
- help = config_lookup(&atcommand_config, "help");
|
|
|
- if (help != NULL) {
|
|
|
- int count = config_setting_length(help);
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < count; ++i) {
|
|
|
- config_setting_t *command;
|
|
|
- const char *commandname;
|
|
|
-
|
|
|
- command = config_setting_get_elem(help, i);
|
|
|
- commandname = config_setting_name(command);
|
|
|
- if (!atcommand_exists(commandname))
|
|
|
- ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ShowStatus("Done reading '" CL_WHITE "%d" CL_RESET "' command aliases in '" CL_WHITE "%s" CL_RESET "'.\n", num_aliases, config_filename);
|
|
|
- return;
|
|
|
-}
|
|
|
void atcommand_db_load_groups(int* group_ids) {
|
|
|
DBIterator *iter = db_iterator(atcommand_db);
|
|
|
AtCommandInfo* cmd;
|
|
@@ -10778,18 +10753,15 @@ void atcommand_db_clear(void) {
|
|
|
|
|
|
db_destroy(atcommand_db);
|
|
|
}
|
|
|
- if (atcommand_alias_db != NULL)
|
|
|
- db_destroy(atcommand_alias_db);
|
|
|
|
|
|
- config_destroy(&atcommand_config);
|
|
|
+ atcommand_alias_db.clear();
|
|
|
}
|
|
|
|
|
|
void atcommand_doload(void) {
|
|
|
atcommand_db_clear();
|
|
|
atcommand_db = stridb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA), ATCOMMAND_LENGTH);
|
|
|
- atcommand_alias_db = stridb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA), ATCOMMAND_LENGTH);
|
|
|
atcommand_basecommands(); //fills initial atcommand_db with known commands
|
|
|
- atcommand_config_read(ATCOMMAND_CONF_FILENAME);
|
|
|
+ atcommand_alias_db.load();
|
|
|
}
|
|
|
|
|
|
void do_init_atcommand(void) {
|