/** Creates a command name that replaces another command. */ static void COM_Alias_f(void) { cmdalias_t *a; char cmd[1024]; size_t i, c; if (COM_Argc() < 3) { CONS_Printf("alias <name> <command>\n"); return; } a = ZZ_Alloc(sizeof *a); a->next = com_alias; com_alias = a; a->name = Z_StrDup(COM_Argv(1)); // copy the rest of the command line cmd[0] = 0; // start out with a null string c = COM_Argc(); for (i = 2; i < c; i++) { strcat(cmd, COM_Argv(i)); if (i != c) strcat(cmd, " "); } strcat(cmd, "\n"); a->value = Z_StrDup(cmd); }
/** Adds a console command. * * \param name Name of the command. * \param func Function called when the command is run. */ void COM_AddCommand(const char *name, com_func_t func) { xcommand_t *cmd; // fail if the command is a variable name if (CV_StringValue(name)[0] != '\0') { I_Error("%s is a variable name\n", name); return; } // fail if the command already exists for (cmd = com_commands; cmd; cmd = cmd->next) { if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { I_Error("Command %s already exists\n", name); return; } } cmd = ZZ_Alloc(sizeof *cmd); cmd->name = name; cmd->function = func; cmd->next = com_commands; com_commands = cmd; }
/** Adds a console command for Lua. * No I_Errors allowed; return a negative code instead. * * \param name Name of the command. */ int COM_AddLuaCommand(const char *name) { xcommand_t *cmd; // fail if the command is a variable name if (CV_StringValue(name)[0] != '\0') return -1; // command already exists for (cmd = com_commands; cmd; cmd = cmd->next) { if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { // replace the built in command. cmd->function = COM_Lua_f; return 1; } } // Add a new command. cmd = ZZ_Alloc(sizeof *cmd); cmd->name = name; cmd->function = COM_Lua_f; cmd->next = com_commands; com_commands = cmd; return 0; }
/** Adds a console command. * * \param name Name of the command. * \param func Function called when the command is run. */ void COM_AddCommand(const char *name, com_func_t func) { xcommand_t *cmd; // fail if the command is a variable name if (CV_StringValue(name)[0] != '\0') { I_Error("%s is a variable name\n", name); return; } // fail if the command already exists for (cmd = com_commands; cmd; cmd = cmd->next) { if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase! { // don't I_Error for Lua commands // Lua commands can replace game commands, and they have priority. // BUT, if for some reason we screwed up and made two console commands with the same name, // it's good to have this here so we find out. if (cmd->function != COM_Lua_f) I_Error("Command %s already exists\n", name); return; } } cmd = ZZ_Alloc(sizeof *cmd); cmd->name = name; cmd->function = func; cmd->next = com_commands; com_commands = cmd; }
/** Adds command text and executes it immediately. * * \param ptext The text to execute. A newline is automatically added. * \sa COM_BufAddText */ void COM_BufInsertText(const char *ptext) { char *temp = NULL; size_t templen; // copy off any commands still remaining in the exec buffer templen = com_text.cursize; if (templen) { temp = M_Memcpy(ZZ_Alloc(templen), com_text.data, templen); VS_Clear(&com_text); } // add the entire text of the file (or alias) COM_BufAddText(ptext); COM_BufExecute(); // do it right away // add the copied off data if (templen) { VS_Write(&com_text, temp, templen); Z_Free(temp); } }
// Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { static struct hook_s hook = {NULL, 0, 0, {0}, false}; hook_p hookp, *lastp; hook.type = luaL_checkoption(L, 1, NULL, hookNames); lua_remove(L, 1); luaL_checktype(L, 1, LUA_TFUNCTION); if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); switch(hook.type) { // Take a mobjtype enum which this hook is specifically for. case hook_MobjSpawn: case hook_MobjCollide: case hook_MobjMoveCollide: case hook_TouchSpecial: case hook_MobjFuse: case hook_MobjThinker: case hook_BossThinker: case hook_ShouldDamage: case hook_MobjDamage: case hook_MobjDeath: case hook_BossDeath: case hook_MobjRemoved: case hook_HurtMsg: hook.s.mt = MT_NULL; if (lua_isnumber(L, 2)) hook.s.mt = lua_tonumber(L, 2); break; case hook_BotAI: hook.s.skinname = NULL; if (lua_isstring(L, 2)) { // lowercase copy const char *s = lua_tostring(L, 2); char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1); do { *p = tolower(*s); ++p; } while(*(++s)); *p = 0; } break; case hook_LinedefExecute: // Linedef executor functions { // uppercase copy const char *s = luaL_checkstring(L, 2); char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1); do { *p = toupper(*s); ++p; } while(*(++s)); *p = 0; } break; default: break; } lua_settop(L, 1); // lua stack contains only the function now. hooksAvailable[hook.type/8] |= 1<<(hook.type%8); // iterate the hook metadata structs // set hook.id to the highest id + 1 // set lastp to the last hook struct's "next" pointer. lastp = &roothook; hook.id = 0; for (hookp = roothook; hookp; hookp = hookp->next) { if (hookp->id >= hook.id) hook.id = hookp->id+1; lastp = &hookp->next; } // allocate a permanent memory struct to stuff hook. hookp = ZZ_Alloc(sizeof(struct hook_s)); memcpy(hookp, &hook, sizeof(struct hook_s)); // tack it onto the end of the linked list. *lastp = hookp; // set the hook function in the registry. lua_pushfstring(L, FMT_HOOKID, hook.id); lua_pushvalue(L, 1); lua_settable(L, LUA_REGISTRYINDEX); return 0; }