/* * This file handles command interpreting */ #include <sys/types.h> #include <stdio.h> /* include main header file */ #include "mud.h" #include "utils.h" #include "character.h" #include "socket.h" #include "room.h" #include "commands.h" #include "action.h" //***************************************************************************** // mandatory modules //***************************************************************************** #include "scripts/scripts.h" //***************************************************************************** // optional modules //***************************************************************************** #ifdef MODULE_FACULTY #include "faculty/faculty.h" #endif #ifdef MODULE_ALIAS #include "alias/alias.h" #endif //***************************************************************************** // local variables and functions //***************************************************************************** NEAR_MAP *cmd_table = NULL; void init_commands() { cmd_table = newNearMap(); //*************************************************************************** // This is for core functions ONLY! If you have a module that adds new // functions to the MUD, they should be added in the init_xxx() function // associated with your module. //*************************************************************************** add_cmd("back", NULL, cmd_back, "player", FALSE); add_cmd("commands", NULL, cmd_commands, "player", FALSE); add_cmd("compress", NULL, cmd_compress, "player", FALSE); add_cmd("groupcmds", NULL, cmd_groupcmds,"player", FALSE); add_cmd("look", "l", cmd_look, "player", FALSE); add_cmd("more", NULL, cmd_more, "player", FALSE); add_cmd_check("look", chk_conscious); } bool cmd_exists(const char *cmd) { return nearMapKeyExists(cmd_table, cmd); } void remove_cmd(const char *cmd) { CMD_DATA *old_cmd = nearMapRemove(cmd_table, cmd); if(old_cmd) deleteCmd(old_cmd); } void add_cmd(const char *cmd, const char *sort_by, COMMAND(func), const char *user_group, bool interrupts) { // if we've already got a command named this, remove it remove_cmd(cmd); // add in the new command nearMapPut(cmd_table, cmd, sort_by, newCmd(cmd, func, user_group, interrupts)); } void add_py_cmd(const char *cmd, const char *sort_by, void *pyfunc, const char *user_group, bool interrupts) { // if we've already got a command named this, remove it remove_cmd(cmd); // add in the new command nearMapPut(cmd_table, cmd, sort_by, newPyCmd(cmd, pyfunc, user_group, interrupts)); } void add_cmd_check(const char *cmd, CMD_CHK(func)) { CMD_DATA *data = nearMapGet(cmd_table, cmd, FALSE); if(data != NULL) cmdAddCheck(data, func); } void add_py_cmd_check(const char *cmd, void *pyfunc) { CMD_DATA *data = nearMapGet(cmd_table, cmd, FALSE); if(data != NULL) cmdAddPyCheck(data, pyfunc); } // show the character all of the commands in the specified group(s). void show_commands(CHAR_DATA *ch, const char *user_groups) { BUFFER *buf = newBuffer(MAX_BUFFER); NEAR_ITERATOR *near_i = newNearIterator(cmd_table); const char *abbrev = NULL; CMD_DATA *cmd = NULL; int col = 0; // go over all of our buckets ITERATE_NEARMAP(abbrev, cmd, near_i) { if(is_keyword(user_groups, cmdGetUserGroup(cmd), FALSE)) { bprintf(buf, "%-13.13s", cmdGetName(cmd)); if (!(++col % 6)) bufferCat(buf, "\r\n"); } } deleteNearIterator(near_i); // do room commands as well if(roomGetCmdTable(charGetRoom(ch)) != NULL) { near_i = newNearIterator(roomGetCmdTable(charGetRoom(ch))); abbrev = NULL; cmd = NULL; bufferCat(buf, "{c"); ITERATE_NEARMAP(abbrev, cmd, near_i) { if(is_keyword(user_groups, cmdGetUserGroup(cmd), FALSE)) { bprintf(buf, "%-13.13s", cmdGetName(cmd)); if (!(++col % 6)) bufferCat(buf, "\r\n"); } } deleteNearIterator(near_i); bufferCat(buf, "{n"); } // tag on our last newline if neccessary, and show commands if (col % 6) bprintf(buf, "\r\n"); text_to_char(ch, bufferString(buf)); deleteBuffer(buf); } // tries to pull a usable command from the near-table and use it. Returns // TRUE if a usable command was found (even if it failed) and false otherwise. bool try_use_cmd_table(CHAR_DATA *ch, NEAR_MAP *table, const char *command, char *arg, bool abbrev_ok) { if(abbrev_ok == FALSE) { CMD_DATA *cmd = nearMapGet(table, command, FALSE); if(cmd == NULL || !is_keyword(bitvectorGetBits(charGetUserGroups(ch)), cmdGetUserGroup(cmd), FALSE)) return FALSE; else { charTryCmd(ch, cmd, arg); return TRUE; } } else { // try to look up the possible commands LIST *cmd_list = nearMapGetAllMatches(table, command); bool cmd_found = FALSE; if(cmd_list != NULL) { LIST_ITERATOR *cmd_i = newListIterator(cmd_list); CMD_DATA *cmd = NULL; ITERATE_LIST(cmd, cmd_i) { if(is_keyword(bitvectorGetBits(charGetUserGroups(ch)), cmdGetUserGroup(cmd), FALSE)) { charTryCmd(ch, cmd, arg); cmd_found = TRUE; break; } } deleteListIterator(cmd_i); deleteList(cmd_list); } return cmd_found; } } void handle_cmd_input(SOCKET_DATA *dsock, char *arg) { CHAR_DATA *ch; if ((ch = socketGetChar(dsock)) == NULL) return; do_cmd(ch, arg, TRUE); } void do_cmd(CHAR_DATA *ch, char *arg, bool aliases_ok) { char command[MAX_BUFFER]; // make sure we've got a command to try if(!arg || !*arg) return; // if we are leading with a non-character, we are trying to do a short-form // command (e.g. ' for say, " for gossip). Just take the first character // and use the rest as the arg if(isalpha(*arg) || isdigit(*arg)) arg = one_arg(arg, command); else { *command = *arg; *(command+1) = '\0'; arg++; // and skip all spaces while(isspace(*arg)) arg++; } #ifdef MODULE_ALIAS if(aliases_ok && try_alias(ch, command, arg)) return; #endif // check to see if it's a faculty command #ifdef MODULE_FACULTY if(try_use_faculty(ch, command)) return; #endif // first try room commands then world commands if(!charGetRoom(ch) || !try_use_cmd_table(ch,roomGetCmdTable(charGetRoom(ch)),command,arg,FALSE)) if(!try_use_cmd_table(ch, cmd_table, command, arg, TRUE)) text_to_char(ch, "No such command.\r\n"); }