/** * @brief Add a new command to the script interface * @param[in] cmd_name The name the command is available via script interface * @param[in] function The function pointer * @param[in] desc A usually(?) one-line description of what the cmd does * @sa Cmd_RemoveCommand */ void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *desc) { cmd_function_t *cmd; unsigned int hash; if (!cmd_name || !cmd_name[0]) return; /* fail if the command is a variable name */ if (Cvar_GetString(cmd_name)[0]) { Com_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name); return; } /* fail if the command already exists */ hash = Com_HashKey(cmd_name, CMD_HASH_SIZE); for (cmd = cmd_functions_hash[hash]; cmd; cmd = cmd->hash_next) { if (Q_streq(cmd_name, cmd->name)) { Com_DPrintf(DEBUG_COMMANDS, "Cmd_AddCommand: %s already defined\n", cmd_name); return; } } cmd = (cmd_function_t *)Mem_PoolAlloc(sizeof(*cmd), com_cmdSysPool, 0); cmd->name = cmd_name; cmd->description = desc; cmd->function = function; cmd->completeParam = NULL; HASH_Add(cmd_functions_hash, cmd, hash); cmd->next = cmd_functions; cmd_functions = cmd; }
/** * @brief Init or return a cvar * @param[in] var_name The cvar name * @param[in] var_value The standard cvar value (will be set if the cvar doesn't exist) * @param[in] flags CVAR_USERINFO, CVAR_LATCH, CVAR_SERVERINFO, CVAR_ARCHIVE and so on * @param[in] desc This is a short description of the cvar (see console command cvarlist) * @note CVAR_ARCHIVE: Cvar will be saved to config.cfg when game shuts down - and * will be reloaded when game starts up the next time * @note CVAR_LATCH: Latched cvars will be updated at the next map load * @note CVAR_SERVERINFO: This cvar will be send in the server info response strings (server browser) * @note CVAR_NOSET: This cvar can not be set from the commandline * @note CVAR_USERINFO: This cvar will be added to the userinfo string when changed (network synced) * @note CVAR_DEVELOPER: Only changeable if we are in development mode * If the variable already exists, the value will not be set * The flags will be or'ed in if the variable exists. */ cvar_t* Cvar_GetOrCreate (const char* var_name, const char* var_value, int flags, const char* desc) { const unsigned hash = Com_HashKey(var_name, CVAR_HASH_SIZE); if (flags & (CVAR_USERINFO | CVAR_SERVERINFO)) { if (!Cvar_InfoValidate(var_name)) { Com_Printf("invalid info cvar name\n"); return nullptr; } } if (cvar_t* const var = Cvar_FindVar(var_name)) { if (!var->defaultString && (flags & CVAR_CHEAT)) var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0); var->flags |= flags; if (desc) { Mem_Free(var->description); var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0); } return var; } if (!var_value) return nullptr; if (flags & (CVAR_USERINFO | CVAR_SERVERINFO)) { if (!Cvar_InfoValidate(var_value)) { Com_Printf("invalid info cvar value '%s' of cvar '%s'\n", var_value, var_name); return nullptr; } } cvar_t* const var = Mem_PoolAllocType(cvar_t, com_cvarSysPool); var->name = Mem_PoolStrDup(var_name, com_cvarSysPool, 0); var->string = Mem_PoolStrDup(var_value, com_cvarSysPool, 0); var->oldString = nullptr; var->modified = true; var->value = atof(var->string); var->integer = atoi(var->string); if (desc) var->description = Mem_PoolStrDup(desc, com_cvarSysPool, 0); HASH_Add(cvarVarsHash, var, hash); /* link the variable in */ var->next = cvarVars; cvarVars = var; if (var->next) var->next->prev = var; var->flags = flags; if (var->flags & CVAR_CHEAT) var->defaultString = Mem_PoolStrDup(var_value, com_cvarSysPool, 0); for (CvarListeners::iterator i = cvarListeners.begin(); i != cvarListeners.end(); ++i) { (*i)->onCreate(var); } return var; }
static void CL_ParseMessageID (const char* name, const char** text) { /* get it's body */ const char* token = Com_Parse(text); if (!*text || *token != '{') { Com_Printf("CL_ParseMessageID: msgid \"%s\" without body ignored\n", name); return; } /* search for game types with same name */ int i; for (i = 0; i < numMsgIDs; i++) if (Q_streq(token, msgIDs[i].id)) break; if (i == numMsgIDs) { msgid_t* msgid = &msgIDs[numMsgIDs++]; if (numMsgIDs >= MAX_MSGIDS) Sys_Error("CL_ParseMessageID: MAX_MSGIDS exceeded"); OBJZERO(*msgid); msgid->id = Mem_PoolStrDup(name, cl_msgidPool, 0); const unsigned int hash = Com_HashKey(msgid->id, MAX_MSGIDHASH); HASH_Add(msgIDHash, msgid, hash); do { const char* errhead = "CL_ParseMessageID: unexpected end of file (msgid "; token = Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; if (Q_streq(token, "text")) { /* found a definition */ token = Com_EParse(text, errhead, name, msgIDText, MSGIDSIZE); if (!*text) break; if (token[0] == '_') token++; if (token[0] != '\0') msgid->text = _(token); else msgid->text = token; if (msgid->text == token) { msgid->text = Mem_PoolStrDup(token, cl_msgidPool, 0); Com_Printf("no translation for %s\n", msgid->id); } } } while (*text); } else { Com_Printf("CL_ParseMessageID: msgid \"%s\" with same already exists - ignore the second one\n", name); Com_SkipBlock(text); } }