123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- /* GCSx
- ** CONSOLE.CPP
- **
- ** Console command support
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- // Command structures
- enum {
- PARAM_NONE = 0,
- PARAM_STRING,
- PARAM_INT,
- PARAM_LINE, // Remainder of line as a string
- };
- struct ConsoleParam {
- string valueS; // Always set
- int valueI;
- };
- #define MAX_PARAM 3
- struct ConsoleCommand {
- const char* cmd;
- int gameMode;
- int editorMode;
- int param[MAX_PARAM];
- void (*function)(ConsoleParam* params);
- };
- // Forward declarations
- void cWorldQuery(ConsoleParam* params);
- void cWorldSet(ConsoleParam* params);
- void cDebugLevelSet(ConsoleParam* params);
- void cDebugLevelQuery(ConsoleParam* params);
- void cUndoBufferSet(ConsoleParam* params);
- void cUndoBufferQuery(ConsoleParam* params);
- void cMemExcept(ConsoleParam* params);
- void cUndoExcept(ConsoleParam* params);
- void cHelpAll(ConsoleParam* params);
- void cHelpCommand(ConsoleParam* params);
- void cClear(ConsoleParam* params);
- void cOpenGLTest(ConsoleParam* params);
- void cConfigList(ConsoleParam* params);
- void cConfigQuery(ConsoleParam* params);
- void cConfigSet(ConsoleParam* params);
- void cTextureTest(ConsoleParam* params);
- void cCompile(ConsoleParam* params);
- void cDecompile(ConsoleParam* params);
- // Valid commands and parameters
- ConsoleCommand commands[] = {
- { "clear", 1, 1, { PARAM_NONE, }, cClear },
- { "compile", 0, 1, { PARAM_LINE, PARAM_NONE }, cCompile },
- { "config", 1, 1, { PARAM_NONE, }, cConfigList },
- { "config", 1, 1, { PARAM_STRING, PARAM_NONE }, cConfigQuery },
- { "config", 1, 1, { PARAM_STRING, PARAM_INT, PARAM_NONE }, cConfigSet },
- { "config", 1, 1, { PARAM_STRING, PARAM_LINE, PARAM_NONE }, cConfigSet },
- { "debuglevel", 1, 1, { PARAM_NONE, }, cDebugLevelQuery },
- { "debuglevel", 1, 1, { PARAM_INT, PARAM_NONE }, cDebugLevelSet },
- { "decompile", 0, 1, { PARAM_LINE, PARAM_NONE }, cDecompile },
- { "help", 1, 1, { PARAM_NONE, }, cHelpAll },
- { "help", 1, 1, { PARAM_STRING, PARAM_NONE }, cHelpCommand },
- { "opengltest", 1, 1, { PARAM_NONE, }, cOpenGLTest },
- { "undobuffer", 0, 1, { PARAM_NONE, }, cUndoBufferQuery },
- { "undobuffer", 0, 1, { PARAM_INT, PARAM_NONE }, cUndoBufferSet },
- { "world", 0, 1, { PARAM_NONE, }, cWorldQuery },
- { "world", 0, 1, { PARAM_INT, PARAM_NONE }, cWorldSet },
- #ifdef MEMDEBUG
- { "memexcept", 1, 1, { PARAM_INT, PARAM_NONE }, cMemExcept },
- #endif
- #ifndef NDEBUG
- { "texturetest",1, 1, { PARAM_INT, PARAM_INT, PARAM_INT }, cTextureTest },
- { "undoexcept", 0, 1, { PARAM_INT, PARAM_NONE }, cUndoExcept },
- #endif
- // @TODO: undo, undolist, redo, redolist, undoclear, redoclear
- // @TODO: fileexcept (debug only)
- // @TODO: exit, editor, frontend
- // @TODO: history
- { NULL, 0, 0, { PARAM_NONE }, NULL },
- };
- // Currently selected world, required for many functions
- WorldEdit* selectedWorld = NULL;
- WorldEdit* verifySelectedWorld() { start_func
- if (selectedWorld) {
- if (WorldEdit::verifyWorld(selectedWorld)) return selectedWorld;
- selectedWorld = NULL;
- debugWrite("(previously active world no longer available)");
- }
- if (WorldEdit::countWorlds() == 0) {
- debugWrite("ERROR: No worlds currently open.");
- return NULL;
- }
- if (WorldEdit::countWorlds() == 1) {
- selectedWorld = WorldEdit::listWorlds(0);
- debugWrite("(selecting world \"%s\" as active)", selectedWorld->getTitle().c_str());
- return selectedWorld;
- }
- debugWrite("ERROR: No active world- use 'world' to select an active world.");
- return NULL;
- }
- // Command functions
- void cCompile(ConsoleParam* params) { start_func
- WorldEdit* world = verifySelectedWorld();
- if (world) {
- toLower(params[0].valueS);
- ScriptEdit* script = dynamic_cast<ScriptEdit*>(world->findScriptCode(params[0].valueS));
- if (script == NULL) script = dynamic_cast<ScriptEdit*>(world->findScriptLib(params[0].valueS));
- if (script == NULL) {
- debugWrite("ERROR: No script '%s' found in active world", params[0].valueS.c_str());
- }
- else {
- // @TODO: throw_File; does this properly store the compiled form?
- script->markLock();
- script->compile();
- script->markUnlock();
- }
- }
- }
- // @TODO: Currently doesn't work (and disabled) during gameplay mode
- void cDecompile(ConsoleParam* params) { start_func
- WorldEdit* world = verifySelectedWorld();
- if (world) {
- toLower(params[0].valueS);
- ScriptEdit* script = dynamic_cast<ScriptEdit*>(world->findScriptCode(params[0].valueS));
- if (script == NULL) script = dynamic_cast<ScriptEdit*>(world->findScriptLib(params[0].valueS));
- if (script == NULL) {
- debugWrite("ERROR: No script '%s' found in active world", params[0].valueS.c_str());
- }
- else {
- // @TODO: throw_File; does this properly store the compiled form?
- script->markLock();
- script->decompile();
- script->markUnlock();
- }
- }
- }
- void cOpenGLTest(ConsoleParam* params) { start_func
- int maxSize = config->readNum(OGL_MAX_SIZE);
- int minSize = config->readNum(OGL_MIN_SIZE);
-
- selectVideoMode(-1, -1, -1, -1, 0, 1);
- debugWrite("OpenGL tests-");
-
- // For simplicity- ensure test size is a power of 2, max 512
- int testSize = 1;
- while ((testSize <= maxSize) && (testSize < 1024)) {
- testSize *= 2;
- }
- testSize /= 2;
-
- // Now test every size from 512 down to 16, limited by minsize
- if (minSize < 16) minSize = 16;
- int textureCount = 1000;
- while (testSize >= minSize) {
- textureCount = oglTestPossibleTextures(testSize, testSize, 1, textureCount);
- // abort if no limit detected
- if (textureCount < 0) break;
- testSize /= 2;
- textureCount *= 4;
- }
-
- initDefaultVideo();
- }
- void cClear(ConsoleParam* params) { start_func
- debugClear();
- }
- void cWorldQuery(ConsoleParam* params) { start_func
- if (WorldEdit::countWorlds() == 0) {
- debugWrite("No worlds currently open.");
- }
- else {
- debugWrite("%d world(s) currently open:", WorldEdit::countWorlds());
- int pos = 0;
- while (WorldEdit* nextWorld = WorldEdit::listWorlds(pos++)) {
- if (nextWorld == selectedWorld) debugWrite("%d: %s (active)", pos, nextWorld->getTitle().c_str());
- else debugWrite("%d: %s", pos, nextWorld->getTitle().c_str());
- }
- }
- }
- void cWorldSet(ConsoleParam* params) { start_func
- WorldEdit* nextWorld = WorldEdit::listWorlds(params[0].valueI - 1);
-
- if (nextWorld == NULL) debugWrite("ERROR: No world %d open- use 'world' to list open worlds.", params[0].valueI);
- else {
- selectedWorld = nextWorld;
- debugWrite("Selecting world \"%s\" as active.", selectedWorld->getTitle().c_str());
- }
- }
- void cDebugLevelSet(ConsoleParam* params) { start_func
- if ((params[0].valueI >= 0) && (params[0].valueI <= DEBUG_MAX)) {
- debugWrite("Debuglevel changed to %d.", debugLevel(params[0].valueI));
- }
- else {
- debugWrite("ERROR: Invalid debuglevel- Debuglevel ranges from 0 to %d.", DEBUG_MAX);
- }
- }
- void cDebugLevelQuery(ConsoleParam* params) { start_func
- debugWrite("Current debuglevel is %d.", debugLevel());
- }
- void cUndoBufferSet(ConsoleParam* params) { start_func
- WorldEdit* world = verifySelectedWorld();
- if (world) {
- if ((params[0].valueI >= 0) && (params[0].valueI <= UndoBuffer::UNDO_MAX_BUFFER)) {
- world->undo.bufferSize(params[0].valueI);
- if (params[0].valueI) debugWrite("Undo buffer resized to %dK.", params[0].valueI);
- else debugWrite("Undo buffer has been disabled.");
- }
- else debugWrite("ERROR: Undo buffer must be between 0K and %dK.", UndoBuffer::UNDO_MAX_BUFFER);
- }
- }
- void cUndoBufferQuery(ConsoleParam* params) { start_func
- WorldEdit* world = verifySelectedWorld();
- if (world) {
- if (world->undo.bufferSize()) debugWrite("Undo buffer is currently %dK.", world->undo.bufferSize());
- else debugWrite("Undo buffer is currently disabled.");
- }
- }
- #define MAX_CONFIG_HELP 5
- struct configLabel {
- const char* cmd;
- int isString;
- int code;
- const char* help;
- };
- configLabel configNames[] = {
- // @TODO: output help using a word-wrapping function
- { "front_alpha", 0, FRONTEND_ACTIVE_ALPHA,
- "Translucency (alpha) for front-end menus/windows when activated during gameplay. Ranges from 0 to 256. (recommended- 192 to 256)",
- },
- { "front_bkalpha", 0, FRONTEND_ACTIVE_BKALPHA,
- "Translucency (alpha) for front-end background/desktop when activated during gameplay. Ranges from 0 to 256. (recommended- 0 to 128)",
- },
- { "front_overlay", 0, FRONTEND_INACTIVE_ALPHA,
- "Translucency (alpha) for front-end menus/windows when overlaid during gameplay, while game is still active. Ranges from 0 to 256. (recommended- 128 to 192)",
- },
- { "front_overlaybk", 0, FRONTEND_INACTIVE_BKALPHA,
- "Translucency (alpha) for front-end background/desktop when overlaid during gameplay, while game is still active. Ranges from 0 to 256. (recommended- 0)",
- },
- { "texture_max", 0, OGL_MAX_SIZE,
- "Maximum height/width for OpenGL textures. This value is auto-detected and, if changed, may prevent graphics from displaying properly.",
- },
- { "texture_megagroup", 0, OGL_PREFER_GROUPING,
- "Group as many OpenGL textures as possible, even at the expense of texture memory. If off, textures are only grouped in an attempt to conserve memory. (0 = off, 1 = on)",
- },
- { "texture_min", 0, OGL_MIN_SIZE,
- "Minimum height/width for OpenGL textures. This value is auto-detected and, if changed, may prevent graphics from displaying properly.",
- },
- { "texture_powertwo", 0, OGL_POWER_OF_TWO,
- "OpenGL textures must be power-of-two sizes. This value is auto-detected and, if changed, may prevent graphics from displaying properly. (0 = off, 1 = on)",
- },
- { "texture_single", 0, OGL_FORCE_SINGLE,
- "Never group OpenGL textures together- always store single textures. If on, textures are never grouped- even when doing so would conserve texture memory. This setting overrides 'texture_megagroup'. (0 = off, 1 = on)",
- },
- { "linked_retain", 0, LINKED_RETAIN,
- "Retain linked version of bytecode in memory during gameplay. Increases memory usage while reducing scene-transition and script-loading times for scenes and scripts previously used. (0 = off, 1 = on)",
- },
- { "linked_pregen", 0, LINKED_PREGENERATE,
- "Pre-generate and retain linked version of bytecode for all scripts before gameplay. Increases game start time and memory usage while reducing all future scene-transition and script-loading times. This setting obsoletes 'linked_retain'. (0 = off, 1 = on)",
- },
- { NULL, 0, 0, NULL },
- };
- void cConfigList(ConsoleParam* params) { start_func
- for (int pos = 0; configNames[pos].cmd; ++pos) {
- if (configNames[pos].isString)
- debugWrite("%s: %s", configNames[pos].cmd, config->readStr(configNames[pos].code).c_str());
- else
- debugWrite("%s: %d", configNames[pos].cmd, config->readNum(configNames[pos].code));
- }
- }
- void cConfigQuery(ConsoleParam* params) { start_func
- for (int pos = 0; configNames[pos].cmd; ++pos) {
- if (myStricmp(params[0].valueS.c_str(), configNames[pos].cmd) == 0) {
- if (configNames[pos].isString)
- debugWrite("%s: %s", configNames[pos].cmd, config->readStr(configNames[pos].code).c_str());
- else
- debugWrite("%s: %d", configNames[pos].cmd, config->readNum(configNames[pos].code));
- debugWrite(" %s", configNames[pos].help);
- return;
- }
- }
- debugWrite("No configuration setting '%s' found. Type 'config' for a list.", params[0].valueS.c_str());
- }
- // @TODO: apply change for some settings (ex: front_*)
- void cConfigSet(ConsoleParam* params) { start_func
- for (int pos = 0; configNames[pos].cmd; ++pos) {
- if (myStricmp(params[0].valueS.c_str(), configNames[pos].cmd) == 0) {
- if (configNames[pos].isString) {
- debugWrite("%s: Previous setting: %s", configNames[pos].cmd, config->readStr(configNames[pos].code).c_str());
- config->write(configNames[pos].code, params[1].valueS);
- debugWrite("%s: New setting: %d", configNames[pos].cmd, config->readStr(configNames[pos].code).c_str());
- }
- else {
- debugWrite("%s: Previous setting: %d", configNames[pos].cmd, config->readNum(configNames[pos].code));
- config->write(configNames[pos].code, params[1].valueI);
- debugWrite("%s: New setting: %d", configNames[pos].cmd, config->readNum(configNames[pos].code));
- }
- return;
- }
- }
- debugWrite("No configuration setting '%s' found. Type 'config' for a list.", params[0].valueS.c_str());
- }
- #ifdef MEMDEBUG
- void cMemExcept(ConsoleParam* params) { start_func
- if (params[0].valueI >= 0) {
- // Turn off to debug write
- setMemThreshold(0);
- if (params[0].valueI) debugWrite("Memory fail threshold set to %d bytes.", params[0].valueI);
- else debugWrite("Memory fail threshold disabled.");
- setMemThreshold(params[0].valueI);
- }
- else debugWrite("ERROR: Memory fail threshold must be a positive value or zero.");
- }
- #endif
- #ifndef NDEBUG
- void cUndoExcept(ConsoleParam* params) { start_func
- if (params[0].valueI >= 0) {
- UndoBuffer::setUndoThreshold(params[0].valueI);
- if (params[0].valueI) debugWrite("Undo fail threshold set to %d item(s).", params[0].valueI);
- else debugWrite("Undo fail threshold disabled.");
- }
- else debugWrite("ERROR: Undo fail threshold must be a positive value or zero.");
- }
- void cTextureTest(ConsoleParam* params) { start_func
- int w = params[0].valueI;
- int h = params[1].valueI;
- int count = params[2].valueI;
- int max = config->readNum(OGL_MAX_SIZE);
-
- if ((w <= 0) || (h <= 0) || (count <= 0))
- debugWrite("ERROR: All parameters must be greater than zero.");
- else if ((w > max) || (h > max))
- debugWrite("ERROR: Size is larger than maximum texture size.");
- else {
- debugWrite("Storing %d graphics (%d x %d)", count, w, h);
- vector<TextureMap::tGroup> sizes;
- TextureMap::groupTextures(count, w, h, sizes);
- for (vector<TextureMap::tGroup>::iterator pos = sizes.begin(); pos != sizes.end(); ++pos)
- debugWrite(" %d of %d x %d textures", (*pos).qty, (*pos).texW, (*pos).texH);
- }
- }
- #endif
- const char* helpText[] = {
- "debuglevel",
- "Sets or views current debugging level. Each level outputs various details"
- "on current activities to the console window. Multiple levels may be added"
- "together. Available levels:",
- " 0 - No debugging output",
- " 1 - Undo",
- " 2 - Compilation",
- " 4 - Tokenization",
- " 8 - Bytecode",
- #ifdef NDEBUG
- #ifdef MEMDEBUG
- " 16- Memory (outputs to stdout.txt only)",
- " 32- Trace (outputs to stdout.txt only)",
- #endif
- #else
- #ifdef MEMDEBUG
- " 16- Interpreter",
- " 32- Memory (outputs to stdout.txt only)",
- " 64- Trace (outputs to stdout.txt only)",
- #else
- " 16- Interpreter",
- #endif
- #endif
- NULL,
- "clear",
- "Clears the console buffer.",
- NULL,
- "compile",
- "Recompiles the named script, displaying all warnings and errors to the "
- "console window.",
- NULL,
- "config",
- "Views or sets configuration settings. Type 'config' alone to list all "
- "possible settings, and their current values. Type 'config' followed by "
- "a setting name to view a single current setting. Type 'config' followed "
- "by a setting and a new value to change a setting.",
- NULL,
- "decompile",
- "Disassemble a script's bytecode and output to the console window.",
- NULL,
- "help",
- "Retrieves help on a specific command. Type 'help' alone to list all "
- "available commands. Type 'help' followed by a command name to get help "
- "on that specific command.",
- NULL,
- "opengltest",
- "Runs various OpenGL tests and reports on the results. "
- "(WARNING: GCSx MAY STOP RESPONDING FOR UP TO A MINUTE)",
- NULL,
- "undobuffer",
- "Sets or views the size of the undo buffer for the active world, in K. An "
- "undo buffer of 0K will disable undo functionality. Changing the buffer "
- "size clears all undo/redo for that world.",
- NULL,
- "world",
- "Sets or views active world. Many commands only operate on a single, open "
- "world. Type 'world' alone to list all available worlds and the currently "
- "active world. Type 'world' followed by a number to select the active world "
- "to use for commands.",
- NULL,
- #ifdef MEMDEBUG
- "memexcept",
- "Sets a level above which all memory allocations will fail, for testing "
- "purposes. Specify a number in bytes, or 0 to disable this feature. NOTE: "
- "most failed memory allocations will result in GCSx shutting down.",
- NULL,
- #endif
- #ifndef NDEBUG
- "texturetest",
- "Follow with a width and height in pixels, and a count. This will attempt "
- "to arrange the given number of graphics, of the given size, and return "
- "how many textures of what size will be used, based on current settings. "
- "Intented solely for debugging texture allocation algorithms.",
- NULL,
- "undoexcept",
- "Sets a number of actions at which all undo storage attempts will fail, "
- "for testing purposes. For example, 2 actions will cause an undo warning "
- "when the second action is attempted. Specify a number of actions, or 0 "
- "to disable this feature. NOTE: Some operations cause multiple undo "
- "actions.",
- NULL,
- #endif
- NULL,
- };
- vector<string>* allCommandsList = NULL;
- #define HELP_COLUMNS 4
- void cHelpAll(ConsoleParam* params) { start_func
- debugWrite("Available commands:");
-
- if (!allCommandsList) {
- set<string> allCommands;
- unsigned int maxCommandLength = 0;
-
- allCommandsList = new vector<string>;
- // Sort, count, and size all commands
- for (int cmdnum = 0; commands[cmdnum].cmd; ++cmdnum) {
- if (strlen(commands[cmdnum].cmd) > maxCommandLength) {
- maxCommandLength = strlen(commands[cmdnum].cmd);
- }
- allCommands.insert(commands[cmdnum].cmd);
- }
-
- // Number of rows?
- int rows = allCommands.size() / HELP_COLUMNS + ((allCommands.size() % HELP_COLUMNS) ? 1 : 0);
- allCommandsList->reserve(rows);
- // Generate columns (not particularly efficient, but who cares?)
- int spot = 0;
- int firstTrip = 1;
- for (set<string>::iterator pos = allCommands.begin(); pos != allCommands.end(); ++pos) {
- if (firstTrip) allCommandsList->push_back(*pos);
- else (*allCommandsList)[spot] += *pos;
- unsigned int pad = (*pos).length();
- while (pad++ <= maxCommandLength) {
- (*allCommandsList)[spot] += " ";
- }
- if (++spot >= rows) {
- firstTrip = 0;
- spot = 0;
- }
- }
- }
-
- for (vector<string>::iterator pos = allCommandsList->begin(); pos != allCommandsList->end(); ++pos) {
- debugWrite(" %s", (*pos).c_str());
- }
-
- debugWrite("Type 'help <command>' for details");
- }
- void cHelpCommand(ConsoleParam* params) { start_func
- // Lowercase
- toLower(params[0].valueS);
-
- for (int pos = 0; helpText[pos]; ++pos) {
- if (!strcmp(helpText[pos], params[0].valueS.c_str())) {
- for (++pos; helpText[pos]; ++pos) {
- debugWrite(helpText[pos]);
- }
- return;
- }
- for (++pos; helpText[pos]; ++pos) ;
- }
-
- debugWrite("No help available for '%s', type 'help' for a list of commands.", params[0].valueS.c_str());
- }
- // Console parser
- void consoleParse(const string& cmd) { start_func
- // Skip any leading spaces
- string::size_type pos = 0;
- pos = cmd.find_first_not_of(' ', pos);
- // (only spaces present)
- if (pos == string::npos) return;
-
- // Grab command- text up to next space or end of line
- string::size_type paramstart = cmd.find_first_of(' ', pos);
- string command = cmd.substr(pos, paramstart == string::npos ? string::npos : paramstart - pos);
- // (find start of parameters too)
- paramstart = cmd.find_first_not_of(' ', paramstart);
- // Lowercase
- toLower(command);
-
- // Find command (may be more than one match)
- int found = 0;
- ConsoleParam params[MAX_PARAM];
- for (int cmdnum = 0; commands[cmdnum].cmd; ++cmdnum) {
- if (!strcmp(command.c_str(), commands[cmdnum].cmd)) {
- found = 1;
-
- // Check parameters
- string::size_type parampos = paramstart;
- int invalid = 0;
- for (int paramnum = 0; paramnum < MAX_PARAM; ++paramnum) {
- if (commands[cmdnum].param[paramnum] == PARAM_NONE) {
- if (parampos != string::npos) invalid = 1;
- // (no more params)
- break;
- }
- else if (parampos == string::npos) {
- invalid = 1;
- }
- else {
- string::size_type paramend = cmd.find_first_of(' ', parampos);
- if (commands[cmdnum].param[paramnum] == PARAM_LINE) paramend = string::npos;
- params[paramnum].valueS = cmd.substr(parampos, paramend == string::npos ? string::npos : paramend - parampos);
- parampos = cmd.find_first_not_of(' ', paramend);
- params[paramnum].valueI = 0;
-
- // More specific types?
- if (commands[cmdnum].param[paramnum] == PARAM_INT) {
- try {
- params[paramnum].valueI = strToIntErr(params[paramnum].valueS);
- }
- catch (int) {
- invalid = 1;
- }
- }
- }
- }
-
- if (!invalid) {
- // Found match!
- if ((!commands[cmdnum].editorMode) && (getProgramMode() == MODE_EDITOR)) {
- debugWrite("Sorry, '%s' is only available in gameplay mode.", command.c_str());
- }
- else if ((!commands[cmdnum].gameMode) && (getProgramMode() != MODE_EDITOR)) {
- debugWrite("Sorry, '%s' is only available in editor mode.", command.c_str());
- }
- else {
- commands[cmdnum].function(params);
- }
- return;
- }
- }
- }
-
- // Not found or invalid parameters
- if (found) {
- // Invalid
- for (int cmdnum = 0; commands[cmdnum].cmd; ++cmdnum) {
- if (!strcmp(command.c_str(), commands[cmdnum].cmd)) {
- string usage;
- for (int paramnum = 0; paramnum < MAX_PARAM; ++paramnum) {
- switch (commands[cmdnum].param[paramnum]) {
- case PARAM_NONE:
- paramnum = MAX_PARAM;
- break;
-
- case PARAM_STRING:
- usage += " <string>";
- break;
- case PARAM_INT:
- usage += " <integer>";
- break;
- case PARAM_LINE:
- usage += " <string...>";
- break;
- }
- }
- debugWrite("Usage: %s%s", command.c_str(), usage.c_str());
- }
- }
- debugWrite("Type 'help %s' for details", command.c_str());
- }
- else {
- debugWrite("Unrecognized command '%s', type 'help' for help", command.c_str());
- }
- }
- // Cleanup
- void destroyConsoleGlobals() { start_func
- if (allCommandsList) {
- delete allCommandsList;
- allCommandsList = NULL;
- }
- }
|