(svn r2243) -Fix: Rework of console. Use 'help command|variable' to get help about it. You can assign variables with =, ++, --, or just new value. Console parser is now lenient towards typed spaces, and more robust in general (at least readable). Removed the 'set' command, instead implemented all such variables as 'variables'.

- Some variables are really special and cannot be assigned normally, use their callback procedure for assignment/querying. This commit also obsoletes "[1172804] Console set command cleanup"
pull/155/head
Darkvater 19 years ago
parent b299f5aa5a
commit 22a375ba73

File diff suppressed because it is too large Load Diff

@ -1,108 +1,118 @@
#ifndef CONSOLE_H
#define CONSOLE_H
// ** console parser ** //
// maximum length of a typed in command
#define ICON_CMDLN_SIZE 255
// maximum length of a totally expanded command
#define ICON_MAX_STREAMSIZE 1024
typedef enum _iconsole_var_types {
ICONSOLE_VAR_NONE,
typedef enum IConsoleVarTypes {
ICONSOLE_VAR_BOOLEAN,
ICONSOLE_VAR_BYTE,
ICONSOLE_VAR_UINT8,
ICONSOLE_VAR_UINT16,
ICONSOLE_VAR_UINT32,
ICONSOLE_VAR_INT16,
ICONSOLE_VAR_INT32,
ICONSOLE_VAR_STRING,
ICONSOLE_VAR_POINTER,
ICONSOLE_VAR_REFERENCE,
ICONSOLE_VAR_UNKNOWN
} _iconsole_var_types;
ICONSOLE_VAR_STRING
} IConsoleVarTypes;
typedef enum {
typedef enum IConsoleModes {
ICONSOLE_FULL,
ICONSOLE_OPENED,
ICONSOLE_CLOSED
} _iconsole_modes;
} IConsoleModes;
typedef enum _iconsole_hook_types {
typedef enum IConsoleHookTypes {
ICONSOLE_HOOK_ACCESS,
ICONSOLE_HOOK_BEFORE_CHANGE,
ICONSOLE_HOOK_BEFORE_EXEC,
ICONSOLE_HOOK_AFTER_CHANGE,
ICONSOLE_HOOK_AFTER_EXEC
} _iconsole_hook_types;
struct _iconsole_var;
typedef bool (*iconsole_var_hook)(struct _iconsole_var* hook_var);
typedef struct _iconsole_var {
// --------------- //
union {
void* addr;
bool* bool_;
byte* byte_;
uint16* uint16_;
uint32* uint32_;
int16* int16_;
int32* int32_;
char* string_;
struct _iconsole_var* reference_;
} data;
char* name;
_iconsole_var_types type;
// -------------- //
iconsole_var_hook hook_access;
iconsole_var_hook hook_before_change;
iconsole_var_hook hook_after_change;
// -------------- //
struct _iconsole_var* _next;
bool _malloc;
} _iconsole_var;
struct _iconsole_cmd;
typedef bool (*iconsole_cmd_hook)(struct _iconsole_cmd* hook_cmd);
typedef _iconsole_var* (*_iconsole_cmd_addr)(byte argc, char* argv[], byte argt[]);
typedef struct _iconsole_cmd {
// -------------- //
_iconsole_cmd_addr addr;
char* name;
// -------------- //
iconsole_cmd_hook hook_access;
iconsole_cmd_hook hook_before_exec;
iconsole_cmd_hook hook_after_exec;
// -------------- //
void* _next;
} _iconsole_cmd;
void IConsoleAliasRegister(const char* name, const char* cmdline);
typedef struct _iconsole_alias {
// -------------- //
char * cmdline;
char* name;
void* _next;
} _iconsole_alias;
_iconsole_alias* IConsoleAliasGet(const char* name);
ICONSOLE_HOOK_PRE_ACTION,
ICONSOLE_HOOK_POST_ACTION
} IConsoleHookTypes;
/** --Hooks--
* Hooks are certain triggers get get accessed/executed on either
* access, before execution/change or after execution/change. This allows
* for general flow of permissions or special action needed in some cases
*/
typedef bool IConsoleHook(void);
typedef struct IConsoleHooks{
IConsoleHook *access; // trigger when accessing the variable/command
IConsoleHook *pre; // trigger before the variable/command is changed/executed
IConsoleHook *post; // trigger after the variable/command is changed/executed
} IConsoleHooks;
/** --Commands--
* Commands are commands, or functions. They get executed once and any
* effect they produce are carried out. The arguments to the commands
* are given to them, each input word seperated by a double-quote (") is an argument
* If you want to handle multiple words as one, enclose them in double-quotes
* eg. 'say "hello sexy boy"'
*/
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
struct IConsoleCmd;
typedef struct IConsoleCmd {
char *name; // name of command
struct IConsoleCmd *next; // next command in list
IConsoleCmdProc *proc; // process executed when command is typed
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleCmd;
/** --Variables--
* Variables are pointers to real ingame variables which allow for
* changing while ingame. After changing they keep their new value
* and can be used for debugging, gameplay, etc. It accepts:
* - no arguments; just print out current value
* - '= <new value>' to assign a new value to the variable
* - '++' to increase value by one
* - '--' to decrease value by one
*/
struct IConsoleVar;
typedef struct IConsoleVar {
char *name; // name of the variable
struct IConsoleVar *next; // next variable in list
void *addr; // the address where the variable is pointing at
uint32 size; // size of the variable, used for strings
char *help; // the optional help string shown when requesting information
IConsoleVarTypes type; // type of variable (for correct assignment/output)
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleVar;
/** --Aliases--
* Aliases are like shortcuts for complex functions, variable assignments,
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
* 'list_vars' for example), or concatenate more commands into one
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
* given to them in the command line.
* - "%A - %Z" substitute arguments 1 t/m 26
* - "%+" lists all parameters keeping them seperated
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
* - ";" allows for combining commands (see example 'ng')
*/
struct IConsoleAlias;
typedef struct IConsoleAlias {
char *name; // name of the alias
struct IConsoleAlias *next; // next alias in list
char *cmdline; // command(s) that is/are being aliased
} IConsoleAlias;
// ** console parser ** //
IConsoleCmd *_iconsole_cmds; // list of registred commands
IConsoleVar *_iconsole_vars; // list of registred vars
IConsoleAlias *_iconsole_aliases; // list of registred aliases
_iconsole_cmd* _iconsole_cmds; // list of registred commands
_iconsole_var* _iconsole_vars; // list of registred vars
_iconsole_alias* _iconsole_aliases; // list of registred aliases
// ** console colors ** //
// ** console colors/modes ** //
VARDEF byte _iconsole_color_default;
VARDEF byte _iconsole_color_error;
VARDEF byte _iconsole_color_warning;
VARDEF byte _iconsole_color_debug;
VARDEF byte _iconsole_color_commands;
VARDEF _iconsole_modes _iconsole_mode;
VARDEF IConsoleModes _iconsole_mode;
// ** console functions ** //
void IConsoleInit(void);
void IConsoleClear(void);
void IConsoleFree(void);
@ -112,44 +122,42 @@ void IConsoleClose(void);
void IConsoleOpen(void);
// ** console cmd buffer ** //
void IConsoleCmdBufferAdd(const char* cmd);
void IConsoleCmdBufferNavigate(signed char direction);
void IConsoleHistoryAdd(const char *cmd);
void IConsoleHistoryNavigate(signed char direction);
// ** console output ** //
void IConsolePrint(uint16 color_code, const char* string);
void CDECL IConsolePrintF(uint16 color_code, const char* s, ...);
void IConsoleDebug(const char* string);
void IConsoleError(const char* string);
void IConsoleWarning(const char* string);
void IConsolePrint(uint16 color_code, const char *string);
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
void IConsoleDebug(const char *string);
void IConsoleWarning(const char *string);
void IConsoleError(const char *string);
// *** Commands *** //
void IConsoleCmdRegister(const char* name, _iconsole_cmd_addr addr);
_iconsole_cmd* IConsoleCmdGet(const char* name);
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
void IConsoleAliasRegister(const char *name, const char *cmd);
IConsoleCmd *IConsoleCmdGet(const char *name);
IConsoleAlias *IConsoleAliasGet(const char *name);
// *** Variables *** //
void IConsoleVarRegister(const char* name, void* addr, _iconsole_var_types type);
void IConsoleVarMemRegister(const char* name, _iconsole_var_types type);
void IConsoleVarInsert(_iconsole_var* item_new, const char* name);
_iconsole_var* IConsoleVarGet(const char* name);
_iconsole_var* IConsoleVarAlloc(_iconsole_var_types type);
void IConsoleVarFree(_iconsole_var* var);
void IConsoleVarSetString(_iconsole_var* var, const char* string);
void IConsoleVarSetValue(_iconsole_var* var, int value);
void IConsoleVarDump(const _iconsole_var* var, const char* dump_desc);
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
IConsoleVar* IConsoleVarGet(const char *name);
void IConsoleVarPrintGetValue(const IConsoleVar *var);
void IConsoleVarPrintSetValue(const IConsoleVar *var);
// *** Parser *** //
void IConsoleCmdExec(const char *cmdstr);
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
void IConsoleCmdExec(const char* cmdstr);
// ** console std lib ** //
// ** console std lib (register ingame commands/aliases/variables) ** //
void IConsoleStdLibRegister(void);
// ** hook code ** //
void IConsoleVarHook(const char* name, _iconsole_hook_types type, iconsole_var_hook proc);
void IConsoleCmdHook(const char* name, _iconsole_hook_types type, iconsole_cmd_hook proc);
bool IConsoleVarHookHandle(_iconsole_var* hook_var, _iconsole_hook_types type);
bool IConsoleCmdHookHandle(_iconsole_cmd* hook_cmd, _iconsole_hook_types type);
// ** Hooking code ** //
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
// ** Supporting functions **//
bool GetArgumentInteger(uint32 *value, const char *arg);
#endif /* CONSOLE_H */

File diff suppressed because it is too large Load Diff

@ -1370,21 +1370,6 @@ void NetworkShutDown(void)
}
#endif
}
void NetworkChangeCompanyPassword(const char *str)
{
if (strncmp(str, "*", sizeof(_network_player_info[_local_player].password)) == 0) {
_network_player_info[_local_player].password[0] = '\0';
IConsolePrint(_iconsole_color_warning, "Company password protection removed.");
} else {
ttd_strlcpy(_network_player_info[_local_player].password, str, sizeof(_network_player_info[_local_player].password));
IConsolePrintF(_iconsole_color_warning, "Company protected with password '%s'.", _network_player_info[_local_player].password);
}
if (!_network_server)
SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
}
#else
void ParseConnectionString(const char **player, const char **port, char *connection_string) {}

@ -217,6 +217,6 @@ void ParseConnectionString(const char **player, const char **port, char *connect
void NetworkUpdateClientInfo(uint16 client_index);
void NetworkAddServer(const char *b);
void NetworkRebuildHostList(void);
void NetworkChangeCompanyPassword(const char *str);
bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
#endif /* NETWORK_H */

@ -656,7 +656,7 @@ static void PlayerCompanyWndProc(Window *w, WindowEvent *e)
#ifdef ENABLE_NETWORK
case 2: /* Change company password */
if (*b == 0) *b = '*'; // empty password is a '*' because of console argument
NetworkChangeCompanyPassword(b);
NetworkChangeCompanyPassword(1, &b);
#endif
}
} break;

@ -42,4 +42,7 @@ typedef struct SettingDesc {
const void *b;
} SettingDesc;
void IConsoleSetPatchSetting(const char *name, const char *value);
void IConsoleGetPatchSetting(const char *name);
#endif /* SETTINGS_H */

@ -1033,17 +1033,22 @@ static void PatchesSelectionWndProc(Window *w, WindowEvent *e)
}
}
/**
* Network-safe changing of patch-settings.
* @param p1 bytes 0 - 7: the patches type (page) that is being changed (construction, network, ai)
* @param p1 bytes 8 - ..: the actual patch (entry) being set inside the category
* @param p2 the new value for the patch
*/
int32 CmdChangePatchSetting(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
const PatchPage *page;
const PatchEntry *pe;
byte pcat = p1 & 0xFF;
byte pel = (p1 >> 8) & 0xFF;
if (flags & DC_EXEC) {
page = &_patches_page[(byte)p1];
if (page == NULL) return 0;
pe = &page->entries[(byte)(p1 >> 8)];
if (pe == NULL) return 0;
if (pcat >= lengthof(_patches_page)) return 0;
if (pel >= _patches_page[pcat].num) return 0;
if (flags & DC_EXEC) {
const PatchEntry *pe = &_patches_page[pcat].entries[pel];
WritePE(pe, (int32)p2);
InvalidateWindow(WC_GAME_OPTIONS, 0);
@ -1052,116 +1057,79 @@ int32 CmdChangePatchSetting(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
static const PatchEntry *IConsoleGetPatch(const char *name, uint *page, uint *entry)
{
const PatchPage *pp;
const PatchEntry *pe;
for (*page = 0; *page < lengthof(_patches_page); (*page)++) {
pp = &_patches_page[*page];
for (*entry = 0; *entry < pp->num; (*entry)++) {
pe = &pp->entries[*entry];
if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0)
return pe;
}
}
return NULL;
}
/* Those 2 functions need to be here, else we have to make some stuff non-static
and besides, it is also better to keep stuff like this at the same place */
void ConsoleSetPatchSetting(char *name, char *value)
void IConsoleSetPatchSetting(char *name, const char *value)
{
const PatchPage *page;
const PatchEntry *pe = NULL;
bool found = false;
uint i;
unsigned int j;
const PatchEntry *pe;
uint page, entry;
int val;
/* Search for the name in the patch-settings */
for (i = 0; i < lengthof(_patches_page); i++) {
page = &_patches_page[i];
for (j = 0; j < page->num; j++) {
pe = &page->entries[j];
if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0) {
/* We found the name */
found = true;
break;
}
}
if (found)
break;
}
pe = IConsoleGetPatch(name, &page, &entry);
/* We did not found the patch setting */
if (!found || pe == NULL) {
IConsolePrintF(_iconsole_color_warning, "'%s' is an unkown patch setting", name);
if (pe == NULL) {
IConsolePrintF(_iconsole_color_warning, "'%s' is an unknown patch setting.", name);
return;
}
val = atoi(value);
sscanf(value, "%d", &val);
if (pe->type == PE_CURRENCY) {
if (pe->type == PE_CURRENCY) // currency can be different on each client
val /= GetCurrentCurrencyRate();
}
// If an item is playerbased, we do not send it over the network (if any)
if (pe->flags & PF_PLAYERBASED) {
WritePE(pe, val);
} else {
// Else we do
DoCommandP(0, i + (j << 8), val, NULL, CMD_CHANGE_PATCH_SETTING);
}
} else // Else we do
DoCommandP(0, page + (entry << 8), val, NULL, CMD_CHANGE_PATCH_SETTING);
{
char tval[20];
const char *tval2 = value;
if (pe->type == PE_BOOL) {
snprintf(tval, sizeof(tval), (val == 1) ? "on" : "off");
tval2 = tval;
}
switch(pe->type) {
case PE_BOOL:
if (val == 1)
snprintf(value, sizeof(value), "enabled");
else
snprintf(value, sizeof(value), "disabled");
break;
default:
break;
IConsolePrintF(_iconsole_color_warning, "'%s' changed to: %s", name, tval2);
}
IConsolePrintF(_iconsole_color_warning, "'%s' changed in:", name);
IConsolePrintF(_iconsole_color_warning, " '%s'", value);
}
void ConsoleGetPatchSetting(char *name)
void IConsoleGetPatchSetting(const char *name)
{
const PatchPage *page;
const PatchEntry *pe = NULL;
char value[50];
bool found = false;
uint i;
unsigned int j;
/* Search for the name in the patch-settings */
for (i = 0; i < lengthof(_patches_page); i++) {
page = &_patches_page[i];
for (j = 0; j < page->num; j++) {
pe = &page->entries[j];
if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0) {
/* We found the name */
found = true;
break;
}
}
if (found)
break;
}
char value[20];
uint page, entry;
const PatchEntry *pe = IConsoleGetPatch(name, &page, &entry);
/* We did not found the patch setting */
if (!found || pe == NULL) {
IConsolePrintF(_iconsole_color_warning, "'%s' is an unkown patch setting", name);
/* We did not find the patch setting */
if (pe == NULL) {
IConsolePrintF(_iconsole_color_warning, "'%s' is an unknown patch setting.", name);
return;
}
/* 'pe' is now the correct patch setting */
switch(pe->type) {
case PE_BOOL:
if (ReadPE(pe) == 1)
snprintf(value, sizeof(value), "enabled");
else
snprintf(value, sizeof(value), "disabled");
break;
case PE_UINT8:
case PE_INT16:
case PE_UINT16:
case PE_INT32:
case PE_CURRENCY:
snprintf(value, sizeof(value), "%d", ReadPE(pe));
break;
}
if (pe->type == PE_BOOL) {
snprintf(value, sizeof(value), (ReadPE(pe) == 1) ? "on" : "off");
} else
snprintf(value, sizeof(value), "%d", ReadPE(pe));
IConsolePrintF(_iconsole_color_warning, "Current value for '%s' is:", name);
IConsolePrintF(_iconsole_color_warning, " '%s'", value);
IConsolePrintF(_iconsole_color_warning, "Current value for '%s' is: '%s'", name, value);
}
static const Widget _patches_selection_widgets[] = {

Loading…
Cancel
Save