#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "build.h"
#define CMD_FILE DATA_DIR "commands.dat"
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
#define SKEY( string, field ) \
if ( !str_cmp( word, string ) ) \
{ \
free_string( field ); \
field = fread_string( fp ); \
fMatch = TRUE; \
break; \
}
void load_commands( void );
void save_commands( void );
struct cmd_list_type
{
char *name;
DO_FUN *function;
};
extern bool fBootDb;
int MAX_CMD;
struct cmd_type *cmd_table;
void clear_table_commands args( ( void ) );
#if defined(COMMAND)
#undef COMMAND
#endif
#define COMMAND(cmd) { #cmd, cmd },
const struct cmd_list_type cmd_list [] =
{
#include "commands.h"
{ NULL, NULL }
};
#undef COMMAND
#define COMMAND(cmd) DECLARE_DO_FUN(cmd);
const struct olc_cmd_type cmdedit_table[] =
{
{ "name", cmdedit_name },
{ "function", cmdedit_function },
{ "level", cmdedit_level },
{ "position", cmdedit_position },
{ "log", cmdedit_log },
{ "new", cmdedit_new },
{ "delete", cmdedit_delete },
{ "list", cmdedit_list },
{ "show", cmdedit_show },
{ "commands", show_commands },
{ "?", show_help },
{ "", 0 }
};
char * cmd_func_name( DO_FUN *command )
{
int cmd;
for ( cmd = 0; cmd_list[cmd].name; cmd++ )
if ( cmd_list[cmd].function == command )
return cmd_list[cmd].name;
return "";
}
DO_FUN * cmd_func_lookup( char *arg )
{
int cmd;
for ( cmd = 0; cmd_list[cmd].name; cmd++ )
if ( !str_cmp(cmd_list[cmd].name, arg) )
return cmd_list[cmd].function;
if ( fBootDb )
{
bugf( "Cmd_func_lookup : funcion %s non-exhistant.", arg );
return do_nothing;
}
return NULL;
}
/*
* Returns FALSE if not used in the cmd_table[cmd].function
*/
bool fun_lookup( DO_FUN *do_fun )
{
int cmd;
for( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
if( cmd_table[cmd].do_fun == do_fun )
return TRUE;
return FALSE;
}
int cmd_lookup( char *arg )
{
int cmd;
for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
if ( LOWER(arg[0]) == LOWER(cmd_table[cmd].name[0])
&& !str_prefix( arg, cmd_table[cmd].name ) )
return cmd;
return -1;
}
void cmdedit( CHAR_DATA *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
char command[MAX_INPUT_LENGTH];
struct cmd_type *pCmd;
int cmd;
EDIT_CMD( ch, pCmd );
smash_tilde(argument);
strcpy(arg, argument);
argument = one_argument( argument, command);
if( get_trust(ch) < LEVEL_JUDGE )
{
send_to_char("Insufficiant trust to edit commands.\n\r", ch);
edit_done(ch);
return;
}
if (command[0] == '\0')
{
cmdedit_show(ch, argument);
return;
}
if (!str_cmp(command, "done") )
{
edit_done(ch);
return;
}
if (!str_cmp(command, "save") )
{
send_to_char("Saving commands...", ch);
save_commands();
send_to_char("Done.\n\r", ch);
return;
}
/* Search Table and Dispatch Command. */
for ( cmd = 0; *cmdedit_table[cmd].name; cmd++ )
{
if ( !str_prefix( command, cmdedit_table[cmd].name ) )
{
if ( (*cmdedit_table[cmd].olc_fun) ( ch, argument ) )
{
logf( NULL, "%s editing %s function.",
ch->name, pCmd->name );
save_commands();
}
return;
}
}
if( ( cmd = flag_value( show_flags, arg ) ) != NO_FLAG )
{
TOGGLE_BIT( pCmd->show, cmd );
send_to_char( "Done.\n\r", ch );
save_commands();
return;
}
interpret(ch, arg);
return;
}
void do_cmdedit(CHAR_DATA *ch, char *argument)
{
struct cmd_type *pCmd;
char command[MSL];
int comando;
if ( IS_NPC(ch) )
return;
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Syntax : CMDEdit [command]\n\r", ch );
return;
}
argument = one_argument( argument, command );
if ( !str_cmp( command, "new" ) )
{
if ( cmdedit_new(ch, argument) )
save_commands();
return;
}
if ( !str_cmp( command, "delete" ) )
{
if ( cmdedit_delete(ch, argument) )
save_commands();
return;
}
if( !str_cmp( command, "save_commands" ) )
{
save_commands();
stc( "Done.\n\r", ch );
return;
}
if ( (comando = cmd_lookup(command)) == -1 )
{
send_to_char( "CMDEdit : Command non-exhistant.\n\r", ch );
return;
}
pCmd = &cmd_table[comando];
set_editor( ch->desc, ED_CMD, pCmd );
return;
}
CMDEDIT( cmdedit_show )
{
struct cmd_type *pCmd;
char buf[MIL];
EDIT_CMD( ch, pCmd );
sprintf( buf, "{cName {B: {n%s\n\r", pCmd->name );
send_to_char( buf, ch );
sprintf( buf, "{cFunction {B: {n%s\n\r",
cmd_func_name(pCmd->do_fun) );
send_to_char( buf, ch );
sprintf( buf, "{cLevel {B: {C[{n%d{C]\n\r",
pCmd->level );
send_to_char( buf, ch );
sprintf( buf, "{cPosition {B: {C[{n%d{C]\n\r",
pCmd->position );
send_to_char( buf, ch );
sprintf( buf, "{cLog {B: {n%s\n\r",
flag_string( log_flags, pCmd->log ) );
send_to_char( buf, ch );
sprintf( buf, "{cShowTo {B: {n%s\n\r",
flag_string( show_flags, pCmd->show ) );
send_to_char( buf, ch );
if( pCmd->disabled_by[0] != '\0' )
{
sprintf( buf, "{cDisabled {B: {C%d {n%s\n\r",
pCmd->disable_level, pCmd->disabled_by );
send_to_char( buf, ch );
send_to_char( "{cReason \n\r{n",ch );
if( pCmd->reason )
sprintf( buf, "%s\n\r", pCmd->reason );
else
sprintf( buf, "(None given)\n\r" );
send_to_char( buf, ch );
}
return FALSE;
}
void list_functions( CHAR_DATA *ch )
{
int i;
char buf[MSL];
sprintf( buf, "Num %-13.13s Num %-13.13s Num %-13.13s Num %-13.13s\n\r",
"Func", "Func", "Func", "Func" );
send_to_char(buf,ch);
for ( i = 0; cmd_list[i].name; i++ )
{
sprintf( buf, "%3d %-13.13s", i, cmd_list[i].name );
if ( i % 4 == 3 )
strcat( buf, "\n\r" );
else
strcat( buf, " " );
send_to_char( buf, ch );
}
if ( i % 4 != 0 )
send_to_char( "\n\r", ch);
}
void used_functions( CHAR_DATA *ch )
{
int i;
char buf [ MAX_STRING_LENGTH ];
bool found;
sprintf( buf, "Num %-13.13s Num %-13.13s Num %-13.13s Num %-13.13s\n\r",
"Func", "Func", "Func", "Func" );
send_to_char(buf,ch);
found = FALSE;
for ( i = 0; cmd_list[i].name; i++ )
{
if( !fun_lookup( cmd_list[i].function ) )
{
found = TRUE;
sprintf( buf, "%3d %-13.13s", i, cmd_list[i].name );
if ( i % 4 == 3 )
strcat( buf, "\n\r" );
else
strcat( buf, " " );
send_to_char( buf, ch );
}
}
if( !found )
send_to_char( "There are no used functions in commands.h\n\r", ch );
else if ( i % 4 != 0 )
send_to_char( "\n\r", ch);
return;
}
void list_commands(CHAR_DATA *ch, int minlev, int maxlev)
{
char buf[MSL];
int i, cnt = 0;
sprintf( buf, "Lvl %-12.12s %-13.13s Pos Log Lvl %-12.12s %-13.13s Pos Log\n\r",
"Name", "Function", "Name", "Function" );
send_to_char( buf, ch );
for ( i = 0; i < MAX_CMD; ++i )
{
if ( cmd_table[i].level < minlev || cmd_table[i].level > maxlev )
continue;
sprintf( buf, "%2d %-12.12s %-13.13s %-3.3s %-3.3s",
cmd_table[i].level,
cmd_table[i].name,
cmd_func_name(cmd_table[i].do_fun),
flag_string( position_flags, cmd_table[i].position ),
flag_string( log_flags,cmd_table[i].log));
if ( cnt % 2 == 1 )
strcat(buf,"\n\r");
else
strcat(buf," ");
send_to_char( buf, ch );
cnt++;
}
if ( cnt % 2 != 0 )
stc("\n\r",ch);
return;
}
CMDEDIT( cmdedit_list )
{
char arg[MIL], arg2[MIL];
int minlev, maxlev;
argument = one_argument( argument, arg );
if ( arg[0] == '\0' || !is_name(arg, "commands functions unused") )
{
send_to_char( "Syntax : list commands [level min] [level max]\n\r", ch );
send_to_char( " list functions\n\r", ch );
send_to_char( " list unused\n\r", ch );
return FALSE;
}
minlev = 0;
maxlev = MAX_LEVEL;
if ( argument[0] != '\0' )
{
argument = one_argument( argument, arg2 );
if ( !is_number( arg2 ) )
{
send_to_char( "CMDEdit : Argument must be a number.\n\r", ch );
return FALSE;
}
minlev = atoi( arg2 );
if ( argument[0] == '\0' )
maxlev = atoi( argument );
else
maxlev = 0;
if ( maxlev < 1 || maxlev > MAX_LEVEL )
maxlev = minlev;
}
if ( !str_prefix(arg,"commands") )
list_commands(ch,minlev,maxlev);
else if ( !str_prefix(arg,"functions") )
list_functions(ch);
else if ( !str_prefix(arg,"unused" ) )
used_functions(ch);
else
send_to_char("Invalid.\n\r",ch);
return FALSE;
}
void do_nothing( CHAR_DATA *ch, char *argument )
{
return;
}
CMDEDIT( cmdedit_name )
{
struct cmd_type *pCmd;
int cmd;
EDIT_CMD(ch,pCmd);
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Sintaxis : name [name]\n\r", ch );
return FALSE;
}
if ( cmd_lookup(argument) != -1 )
{
send_to_char( "CMDEdit : Command already exhists.\n\r", ch );
return FALSE;
}
free_string(pCmd->name);
pCmd->name = str_dup( argument );
clear_table_commands();
cmd = cmd_lookup(argument);
if ( cmd != -1 )
ch->desc->pEdit = &cmd_table[cmd];
else
bugf( "Cmdedit_name : cmd_lookup returns -1 at %s!", argument );
send_to_char( "Ok.\n\r", ch );
return TRUE;
}
CMDEDIT( cmdedit_new )
{
DESCRIPTOR_DATA *d;
CHAR_DATA *tch;
struct cmd_type *new_table;
int cmd;
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Syntax : new [number of command]\n\r", ch );
return FALSE;
}
cmd = cmd_lookup( argument );
if (cmd != -1)
{
send_to_char ("CMDEdit : Command non-exhistant.\n\r",ch);
return FALSE;
}
for ( d = descriptor_list; d; d = d->next )
{
if ( d->connected != CON_PLAYING
|| (tch = CH(d)) == NULL || tch->desc == NULL )
continue;
if ( tch->desc->editor == ED_CMD )
edit_done(tch);
}
MAX_CMD++;
new_table = realloc (cmd_table, sizeof(struct cmd_type) * (MAX_CMD + 1));
if (!new_table) /* realloc failed */
{
send_to_char ("Failure to reallocate table. Prepare for the worse.\n\r",ch);
return FALSE;
}
cmd_table = new_table;
cmd_table[MAX_CMD-1].name = str_dup (argument);
cmd_table[MAX_CMD-1].do_fun = do_nothing;
cmd_table[MAX_CMD-1].position = POS_STANDING;
cmd_table[MAX_CMD-1].level = ch->level;
cmd_table[MAX_CMD-1].log = LOG_ALWAYS;
cmd_table[MAX_CMD-1].show = CSHOW_NEVER;
cmd_table[MAX_CMD-1].disabled_by = str_dup( "" );
cmd_table[MAX_CMD-1].reason = str_dup( "" );
cmd_table[MAX_CMD-1].disable_level = 12;
cmd_table[MAX_CMD].name = str_dup( "" );
clear_table_commands();
cmd = cmd_lookup(argument);
if ( cmd != -1 )
ch->desc->pEdit = &cmd_table[cmd];
else
bugf( "Cmdedit_new : cmd_lookup returned -1 with %s!", argument );
ch->desc->editor = ED_CMD;
send_to_char ("Command created.\n\r",ch);
return TRUE;
}
CMDEDIT( cmdedit_delete )
{
DESCRIPTOR_DATA *d;
CHAR_DATA *tch;
int i,j,iCmd;
struct cmd_type *new_table;
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Syntax : delete [number or command]\n\r", ch );
return FALSE;
}
iCmd = cmd_lookup(argument);
if (iCmd == -1)
{
send_to_char( "CMDEdit : Command non-exhistant.\n\r", ch );
return FALSE;
}
for ( d = descriptor_list; d; d = d->next )
{
if ( d->connected != CON_PLAYING || (tch = CH(d)) == NULL || tch->desc == NULL )
continue;
if ( tch->desc->editor == ED_CMD )
edit_done(tch);
}
new_table = malloc (sizeof(struct cmd_type) * MAX_CMD);
if (!new_table)
{
send_to_char ("Memory allocation failed. Brace for impact...\n\r",ch);
return FALSE;
}
for (i = 0, j = 0; i < MAX_CMD+1; i++)
if (i != iCmd) /* copy, increase only if copied */
{
new_table[j] = cmd_table[i];
j++;
}
free (cmd_table);
cmd_table = new_table;
MAX_CMD--; /* Important :() */
clear_table_commands();
send_to_char ("Command deleted\n\r",ch);
return TRUE;
}
CMDEDIT( cmdedit_function )
{
struct cmd_type *pCmd;
DO_FUN *funcion;
EDIT_CMD(ch,pCmd);
if ( !argument || argument[0] == '\0' )
{
send_to_char( "Syntax : function [name-function]\n\r", ch );
return FALSE;
}
if ( (funcion = cmd_func_lookup(argument)) == NULL )
{
send_to_char( "CMDEdit : Function inexistente.\n\r", ch );
return FALSE;
}
pCmd->do_fun = funcion;
send_to_char( "Ok.\n\r", ch );
return TRUE;
}
CMDEDIT( cmdedit_level )
{
struct cmd_type *pCmd;
int niv;
EDIT_CMD(ch,pCmd);
if ( !argument || argument[0] == '\0')
{
ch_printf( ch, "Syntax : level [level]\n\r" );
return FALSE;
}
if( is_number( argument ) )
niv = atoi( argument );
else
if ( (niv = flag_value(level_flags, argument)) == NO_FLAG )
{
send_to_char( "CMDEdit : Level out of range.\n\r", ch );
return FALSE;
}
if ( pCmd->level > ch->level )
{
send_to_char( "CMDEdit : Cannot create command higher then you.\n\r", ch );
return FALSE;
}
pCmd->level = niv;
send_to_char( "Ok.\n\r", ch );
return TRUE;
}
CMDEDIT( cmdedit_log )
{
struct cmd_type *pCmd;
int value;
EDIT_CMD(ch,pCmd);
if ( !argument || argument[0] == '\0' )
{
ch_printf( ch, "Syntax : log [type/number]\n\r" );
return FALSE;
}
if( is_number( argument ) )
value = atoi( argument );
else
value = flag_value( log_flags, argument );
if( value < 0 || value > 2 )
{
ch_printf( ch, "CMDEdit: Log %d is to large.\n\r", value );
return FALSE;
}
pCmd->log = value;
stc("Log toggled.\n\r", ch);
return TRUE;
}
CMDEDIT( cmdedit_position )
{
struct cmd_type *pCmd;
int value;
EDIT_CMD(ch,pCmd);
if ( !argument || argument[0] == '\0' )
{
ch_printf( ch, "Syntax : log [type/number]\n\r" );
return FALSE;
}
if( is_number( argument ) )
value = atoi( argument );
else
value = flag_value( position_flags, argument );
if( value < 0 || value > 9 )
{
ch_printf( ch, "CMDEdit: Position %d is invalid.\n\r", value );
return FALSE;
}
pCmd->position = value;
stc("Position set.\n\r", ch);
return TRUE;
}
void fread_cmd( FILE *fp, struct cmd_type * pCmd )
{
char buf[MAX_STRING_LENGTH];
char *word;
bool fMatch;
pCmd->disabled_by = str_dup( "" );
pCmd->reason = str_dup( "" );
pCmd->disable_level = MAX_LEVEL;
for ( ;; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER(word[0]) )
{
case '*':
case '#':
fMatch = TRUE;
fread_to_eol( fp );
break;
case 'D':
if( !str_cmp( word, "D" ) )
{
fMatch = TRUE;
pCmd->disable_level = fread_number( fp );
free_string( pCmd->disabled_by );
pCmd->disabled_by = fread_string( fp );
break;
}
break;
case 'C':
if( !str_cmp( word, "C" ) )
{
char * p;
fMatch = TRUE;
p = fread_string ( fp );
pCmd->do_fun = cmd_func_lookup( p );
free_string( p );
break;
}
break;
case 'E':
if ( !str_cmp( word, "End" ) )
{
if( pCmd->do_fun == do_nothing )
SET_BIT( pCmd->show, CSHOW_NEVER );
return;
}
break;
case 'L':
KEY( "Lv", pCmd->level, fread_number(fp) );
KEY( "Lg", pCmd->log, fread_number(fp) );
break;
case 'N':
if( !str_cmp( word, "N" ) )
{
free_string( pCmd->name );
pCmd->name = fread_string( fp );
fMatch = TRUE;
break;
}
break;
case 'P':
KEY( "P", pCmd->position, fread_number(fp) );
break;
case 'R':
SKEY( "R", pCmd->reason );
case 'S':
KEY( "S", pCmd->show, fread_number(fp) );
break;
}
if ( !fMatch )
{
sprintf( buf, "Fread_command: no match: %s", word );
bug( buf, 0 );
}
}
}
void load_commands( void )
{
FILE * fp;
extern struct cmd_type * cmd_table;
extern int MAX_CMD;
int i = 0, large;
fp = fopen( CMD_FILE, "r" );
if ( !fp )
{
perror( "load_table_commands ");
exit(1);
}
large = fread_number(fp);
MAX_CMD = large;
logf( NULL, "Creating cmd_table: large %d, size: %d", large + 1,
sizeof(struct cmd_type) * (large + 1) );
cmd_table = calloc( sizeof(struct cmd_type), large + 1);
for( i = 0; i < MAX_CMD; i++ )
fread_cmd( fp, &cmd_table[i] );
logf( NULL, "Table of commands loaded." );
fclose(fp);
cmd_table[MAX_CMD].name = str_dup( "" ); /* Backwards compat */
return;
}
void save_commands( void )
{
FILE * fp;
struct cmd_type * temp;
extern struct cmd_type * cmd_table;
int cnt = 0;
fp = fopen( CMD_FILE, "w" );
if ( !fp )
{
perror( "save_table_commands" );
return;
}
for ( MAX_CMD = 0; cmd_table[MAX_CMD].name[0]; MAX_CMD++ )
;
fprintf( fp, "%d\n\n", MAX_CMD );
for( cnt = 0; cnt < MAX_CMD; cnt++ )
{
temp = &cmd_table[cnt];
fprintf( fp, "#COMAND\n" );
fprintf( fp, "N %s~\n", temp->name );
fprintf( fp, "C %s~\n", cmd_func_name(temp->do_fun) );
fprintf( fp, "Lv %d\n", temp->level );
fprintf( fp, "P %d\n", temp->position );
fprintf( fp, "Lg %d\n", temp->log );
fprintf( fp, "S %d\n", temp->show );
if( temp->disabled_by[0] != '\0' )
{
fprintf( fp, "D %d %s~\n",
temp->disable_level,
temp->disabled_by );
fprintf( fp, "R %s~\n", strip_cr(temp->reason) );
}
fprintf( fp, "End\n\n" );
}
fclose(fp);
}