2006-10-06 17:05:27 +00:00
|
|
|
|
/*! \file command.cpp
|
2007-01-03 03:11:53 +00:00
|
|
|
|
* \brief Command parser and support routines.
|
2006-10-06 17:05:27 +00:00
|
|
|
|
*
|
|
|
|
|
|
* The functions here crack command lists into commands, decode switches, and
|
|
|
|
|
|
* match commands to built-in and softcoded commands. This is one of the
|
|
|
|
|
|
* three parsers in the server. The other two parsers are for functions
|
2006-10-07 01:41:02 +00:00
|
|
|
|
* (see eval.cpp) and locks (boolexp.cpp).
|
2006-10-06 17:05:27 +00:00
|
|
|
|
*/
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
#include "copyright.h"
|
|
|
|
|
|
#include "autoconf.h"
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
#include "externs.h"
|
2026-03-09 19:40:40 -06:00
|
|
|
|
#include "ganl_stub.h"
|
2026-03-29 08:54:51 -06:00
|
|
|
|
#include "walk.h"
|
2026-07-28 11:31:23 -06:00
|
|
|
|
#include "mux_table.h"
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2025-03-25 13:54:19 -06:00
|
|
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
|
|
|
|
#include <pcre2.h>
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Switch tables for the various commands.
|
|
|
|
|
|
//
|
|
|
|
|
|
static NAMETAB attrib_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("access"), 1, CA_GOD, ATTRIB_ACCESS},
|
|
|
|
|
|
{T("delete"), 1, CA_GOD, ATTRIB_DELETE},
|
|
|
|
|
|
{T("rename"), 1, CA_GOD, ATTRIB_RENAME},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB boot_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("port"), 1, CA_WIZARD, BOOT_PORT|SW_MULTIPLE},
|
|
|
|
|
|
{T("quiet"), 1, CA_WIZARD, BOOT_QUIET|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2012-07-10 09:48:56 -07:00
|
|
|
|
static NAMETAB break_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("inline"), 1, CA_WIZARD, BREAK_INLINE},
|
|
|
|
|
|
{T("queued"), 1, CA_WIZARD, BREAK_QUEUED},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2012-07-10 09:48:56 -07:00
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB cboot_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, CBOOT_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB comtitle_sw[] =
|
|
|
|
|
|
{
|
2026-03-04 13:53:25 -07:00
|
|
|
|
{T("gag"), 1, CA_PUBLIC, COMTITLE_GAG},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("off"), 2, CA_PUBLIC, COMTITLE_OFF},
|
|
|
|
|
|
{T("on"), 2, CA_PUBLIC, COMTITLE_ON},
|
2026-03-04 13:53:25 -07:00
|
|
|
|
{T("ungag"), 1, CA_PUBLIC, COMTITLE_UNGAG},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB cemit_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("noheader"), 1, CA_PUBLIC, CEMIT_NOHEADER},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-15 22:44:58 +00:00
|
|
|
|
static NAMETAB chown_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("nostrip"), 1, CA_PUBLIC, CHOWN_NOSTRIP},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-15 22:44:58 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB clone_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("cost"), 1, CA_PUBLIC, CLONE_SET_COST},
|
|
|
|
|
|
{T("inherit"), 3, CA_PUBLIC, CLONE_INHERIT|SW_MULTIPLE},
|
|
|
|
|
|
{T("inventory"), 3, CA_PUBLIC, CLONE_INVENTORY},
|
|
|
|
|
|
{T("location"), 1, CA_PUBLIC, CLONE_LOCATION},
|
|
|
|
|
|
{T("nostrip"), 2, CA_WIZARD, CLONE_NOSTRIP|SW_MULTIPLE},
|
|
|
|
|
|
{T("parent"), 2, CA_PUBLIC, CLONE_FROM_PARENT|SW_MULTIPLE},
|
|
|
|
|
|
{T("preserve"), 2, CA_WIZARD, CLONE_PRESERVE|SW_MULTIPLE},
|
2026-03-03 19:38:14 -07:00
|
|
|
|
{ nullptr, 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB clist_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("full"), 0, CA_PUBLIC, CLIST_FULL},
|
|
|
|
|
|
{T("headers"), 0, CA_PUBLIC, CLIST_HEADERS},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB cset_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("anon"), 1, CA_PUBLIC, CSET_SPOOF},
|
|
|
|
|
|
{T("header"), 1, CA_PUBLIC, CSET_HEADER},
|
|
|
|
|
|
{T("list"), 2, CA_PUBLIC, CSET_LIST},
|
|
|
|
|
|
{T("log") , 3, CA_PUBLIC, CSET_LOG},
|
|
|
|
|
|
{T("loud"), 3, CA_PUBLIC, CSET_LOUD},
|
|
|
|
|
|
{T("mute"), 1, CA_PUBLIC, CSET_QUIET},
|
|
|
|
|
|
{T("nospoof"), 1, CA_PUBLIC, CSET_NOSPOOF},
|
|
|
|
|
|
{T("object"), 1, CA_PUBLIC, CSET_OBJECT},
|
|
|
|
|
|
{T("private"), 2, CA_PUBLIC, CSET_PRIVATE},
|
|
|
|
|
|
{T("public"), 2, CA_PUBLIC, CSET_PUBLIC},
|
|
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, CSET_QUIET},
|
|
|
|
|
|
{T("spoof"), 1, CA_PUBLIC, CSET_SPOOF},
|
2007-08-05 20:45:35 +00:00
|
|
|
|
{T("timestamp_logs"), 1, CA_PUBLIC, CSET_LOG_TIME},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB dbck_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("full"), 1, CA_WIZARD, DBCK_FULL},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB decomp_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("dbref"), 1, CA_PUBLIC, DECOMP_DBREF},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB destroy_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("instant"), 4, CA_PUBLIC, DEST_INSTANT|SW_MULTIPLE},
|
|
|
|
|
|
{T("override"), 8, CA_PUBLIC, DEST_OVERRIDE|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB dig_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("teleport"), 1, CA_PUBLIC, DIG_TELEPORT},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB doing_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("header"), 1, CA_PUBLIC, DOING_HEADER},
|
|
|
|
|
|
{T("message"), 1, CA_PUBLIC, DOING_MESSAGE},
|
|
|
|
|
|
{T("poll"), 1, CA_PUBLIC, DOING_POLL},
|
|
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, DOING_QUIET|SW_MULTIPLE},
|
|
|
|
|
|
{T("unique"), 1, CA_PUBLIC, DOING_UNIQUE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB dolist_sw[] =
|
|
|
|
|
|
{
|
2026-06-10 09:00:21 -06:00
|
|
|
|
{T("break"), 1, CA_PUBLIC, DOLIST_BREAK|SW_MULTIPLE},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("delimit"), 1, CA_PUBLIC, DOLIST_DELIMIT},
|
|
|
|
|
|
{T("notify"), 1, CA_PUBLIC, DOLIST_NOTIFY|SW_MULTIPLE},
|
2026-03-04 14:46:56 -07:00
|
|
|
|
{T("now"), 1, CA_WIZARD, DOLIST_NOW|SW_MULTIPLE},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("space"), 1, CA_PUBLIC, DOLIST_SPACE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB query_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("sql"), 1, CA_PUBLIC, QUERY_SQL},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB drop_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, DROP_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB dump_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("flatfile"), 1, CA_WIZARD, DUMP_FLATFILE|SW_MULTIPLE},
|
|
|
|
|
|
{T("structure"), 1, CA_WIZARD, DUMP_STRUCT|SW_MULTIPLE},
|
|
|
|
|
|
{T("text"), 1, CA_WIZARD, DUMP_TEXT|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB emit_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("here"), 2, CA_PUBLIC, SAY_HERE|SW_MULTIPLE},
|
|
|
|
|
|
{T("html"), 2, CA_PUBLIC, SAY_HTML|SW_MULTIPLE},
|
|
|
|
|
|
{T("room"), 1, CA_PUBLIC, SAY_ROOM|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB enter_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, MOVE_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB examine_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("brief"), 1, CA_PUBLIC, EXAM_BRIEF},
|
|
|
|
|
|
{T("debug"), 1, CA_WIZARD, EXAM_DEBUG},
|
|
|
|
|
|
{T("full"), 1, CA_PUBLIC, EXAM_LONG},
|
|
|
|
|
|
{T("parent"), 1, CA_PUBLIC, EXAM_PARENT},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB femit_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("here"), 1, CA_PUBLIC, PEMIT_HERE|SW_MULTIPLE},
|
|
|
|
|
|
{T("room"), 1, CA_PUBLIC, PEMIT_ROOM|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB fixdb_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("contents"), 1, CA_GOD, FIXDB_CON},
|
|
|
|
|
|
{T("exits"), 1, CA_GOD, FIXDB_EXITS},
|
|
|
|
|
|
{T("location"), 1, CA_GOD, FIXDB_LOC},
|
|
|
|
|
|
{T("next"), 1, CA_GOD, FIXDB_NEXT},
|
|
|
|
|
|
{T("owner"), 1, CA_GOD, FIXDB_OWNER},
|
|
|
|
|
|
{T("pennies"), 1, CA_GOD, FIXDB_PENNIES},
|
|
|
|
|
|
{T("rename"), 1, CA_GOD, FIXDB_NAME},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB flag_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("remove"), 1, CA_GOD, FLAG_REMOVE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2007-08-21 00:12:29 +00:00
|
|
|
|
static NAMETAB folder_sw[] =
|
|
|
|
|
|
{
|
2007-12-21 17:46:20 -08:00
|
|
|
|
{T("file"), 1, CA_PUBLIC, FOLDER_FILE},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, FOLDER_LIST},
|
|
|
|
|
|
{T("read"), 1, CA_PUBLIC, FOLDER_READ},
|
|
|
|
|
|
{T("set"), 1, CA_PUBLIC, FOLDER_SET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2007-08-21 00:12:29 +00:00
|
|
|
|
};
|
2026-03-04 14:46:56 -07:00
|
|
|
|
static NAMETAB force_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("now"), 1, CA_WIZARD, FORCE_NOW},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB fpose_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("default"), 1, CA_PUBLIC, 0},
|
|
|
|
|
|
{T("nospace"), 1, CA_PUBLIC, SAY_NOSPACE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB function_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("delete"), 1, CA_WIZARD, FN_DELETE},
|
|
|
|
|
|
{T("list"), 1, CA_WIZARD, FN_LIST},
|
|
|
|
|
|
{T("preserve"), 3, CA_WIZARD, FN_PRES|SW_MULTIPLE},
|
|
|
|
|
|
{T("privileged"), 3, CA_WIZARD, FN_PRIV|SW_MULTIPLE},
|
2026-03-04 10:55:57 -07:00
|
|
|
|
{T("restrict"), 1, CA_WIZARD, FN_RESTRICT|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB get_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, GET_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB give_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_WIZARD, GIVE_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB goto_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, MOVE_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB halt_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_PUBLIC, HALT_ALL},
|
2026-03-04 16:50:02 -07:00
|
|
|
|
{T("pid"), 1, CA_PUBLIC, HALT_PID},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB hook_sw[] =
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
{T("after"), 3, CA_GOD, CEF_HOOK_AFTER},
|
|
|
|
|
|
{T("before"), 3, CA_GOD, CEF_HOOK_BEFORE},
|
|
|
|
|
|
{T("clear"), 3, CA_GOD, CEF_HOOK_CLEAR|SW_MULTIPLE},
|
|
|
|
|
|
{T("fail"), 1, CA_GOD, CEF_HOOK_AFAIL},
|
|
|
|
|
|
{T("ignore"), 3, CA_GOD, CEF_HOOK_IGNORE},
|
|
|
|
|
|
{T("igswitch"), 3, CA_GOD, CEF_HOOK_IGSWITCH},
|
|
|
|
|
|
{T("list"), 3, CA_GOD, CEF_HOOK_LIST},
|
|
|
|
|
|
{T("permit"), 3, CA_GOD, CEF_HOOK_PERMIT},
|
|
|
|
|
|
{T("args"), 3, CA_GOD, CEF_HOOK_ARGS},
|
2026-03-03 19:38:14 -07:00
|
|
|
|
{nullptr, 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB icmd_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("check"), 2, CA_GOD, ICMD_CHECK},
|
|
|
|
|
|
{T("clear"), 2, CA_GOD, ICMD_CLEAR},
|
|
|
|
|
|
{T("croom"), 2, CA_GOD, ICMD_CROOM},
|
|
|
|
|
|
{T("disable"), 1, CA_GOD, ICMD_DISABLE},
|
|
|
|
|
|
{T("droom"), 2, CA_GOD, ICMD_DROOM},
|
|
|
|
|
|
{T("ignore"), 1, CA_GOD, ICMD_IGNORE},
|
|
|
|
|
|
{T("iroom"), 2, CA_GOD, ICMD_IROOM},
|
|
|
|
|
|
{T("lroom"), 2, CA_GOD, ICMD_LROOM},
|
|
|
|
|
|
{T("lallroom"), 2, CA_GOD, ICMD_LALLROOM},
|
|
|
|
|
|
{T("off"), 2, CA_GOD, ICMD_OFF},
|
|
|
|
|
|
{T("on"), 2, CA_GOD, ICMD_ON},
|
2026-03-03 19:38:14 -07:00
|
|
|
|
{nullptr, 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB leave_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, MOVE_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB listmotd_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("brief"), 1, CA_WIZARD, MOTD_BRIEF},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
NAMETAB lock_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("defaultlock"), 1, CA_PUBLIC, A_LOCK},
|
|
|
|
|
|
{T("droplock"), 1, CA_PUBLIC, A_LDROP},
|
|
|
|
|
|
{T("enterlock"), 1, CA_PUBLIC, A_LENTER},
|
|
|
|
|
|
{T("getfromlock"), 1, CA_PUBLIC, A_LGET},
|
|
|
|
|
|
{T("givelock"), 1, CA_PUBLIC, A_LGIVE},
|
|
|
|
|
|
{T("leavelock"), 2, CA_PUBLIC, A_LLEAVE},
|
|
|
|
|
|
{T("linklock"), 2, CA_PUBLIC, A_LLINK},
|
|
|
|
|
|
{T("maillock"), 1, CA_PUBLIC, A_LMAIL},
|
|
|
|
|
|
{T("openlock"), 1, CA_PUBLIC, A_LOPEN},
|
|
|
|
|
|
{T("pagelock"), 3, CA_PUBLIC, A_LPAGE},
|
|
|
|
|
|
{T("parentlock"), 3, CA_PUBLIC, A_LPARENT},
|
|
|
|
|
|
{T("receivelock"), 1, CA_PUBLIC, A_LRECEIVE},
|
|
|
|
|
|
{T("speechlock"), 1, CA_PUBLIC, A_LSPEECH},
|
|
|
|
|
|
{T("teloutlock"), 2, CA_PUBLIC, A_LTELOUT},
|
|
|
|
|
|
{T("tportlock"), 2, CA_PUBLIC, A_LTPORT},
|
|
|
|
|
|
{T("uselock"), 1, CA_PUBLIC, A_LUSE},
|
|
|
|
|
|
{T("userlock"), 4, CA_PUBLIC, A_LUSER},
|
2009-03-04 13:59:34 -08:00
|
|
|
|
{T("visiblelock"), 1, CA_PUBLIC, A_LVISIBLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB look_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("outside"), 1, CA_PUBLIC, LOOK_OUTSIDE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB mail_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("abort"), 2, CA_PUBLIC, MAIL_ABORT},
|
|
|
|
|
|
{T("alias"), 4, CA_PUBLIC, MAIL_ALIAS},
|
|
|
|
|
|
{T("alist"), 4, CA_PUBLIC, MAIL_ALIST},
|
|
|
|
|
|
{T("bcc"), 1, CA_PUBLIC, MAIL_BCC},
|
|
|
|
|
|
{T("cc"), 2, CA_PUBLIC, MAIL_CC},
|
|
|
|
|
|
{T("clear"), 2, CA_PUBLIC, MAIL_CLEAR},
|
|
|
|
|
|
{T("debug"), 2, CA_PUBLIC, MAIL_DEBUG},
|
|
|
|
|
|
{T("dstats"), 2, CA_PUBLIC, MAIL_DSTATS},
|
|
|
|
|
|
{T("edit"), 1, CA_PUBLIC, MAIL_EDIT},
|
|
|
|
|
|
{T("file"), 2, CA_PUBLIC, MAIL_FILE},
|
|
|
|
|
|
{T("folder"), 3, CA_PUBLIC, MAIL_FOLDER},
|
|
|
|
|
|
{T("forward"), 3, CA_PUBLIC, MAIL_FORWARD},
|
|
|
|
|
|
{T("fstats"), 2, CA_PUBLIC, MAIL_FSTATS},
|
|
|
|
|
|
{T("fwd"), 2, CA_PUBLIC, MAIL_FORWARD},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, MAIL_LIST},
|
2026-03-04 12:07:22 -07:00
|
|
|
|
{T("next"), 3, CA_PUBLIC, MAIL_NEXT},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("nuke"), 1, CA_PUBLIC, MAIL_NUKE},
|
|
|
|
|
|
{T("proof"), 2, CA_PUBLIC, MAIL_PROOF},
|
|
|
|
|
|
{T("purge"), 2, CA_PUBLIC, MAIL_PURGE},
|
|
|
|
|
|
{T("quick"), 3, CA_PUBLIC, MAIL_QUICK},
|
|
|
|
|
|
{T("quote"), 3, CA_PUBLIC, MAIL_QUOTE|SW_MULTIPLE},
|
|
|
|
|
|
{T("read"), 3, CA_PUBLIC, MAIL_READ},
|
|
|
|
|
|
{T("reply"), 3, CA_PUBLIC, MAIL_REPLY},
|
|
|
|
|
|
{T("replyall"), 6, CA_PUBLIC, MAIL_REPLYALL},
|
|
|
|
|
|
{T("retract"), 3, CA_PUBLIC, MAIL_RETRACT},
|
|
|
|
|
|
{T("review"), 3, CA_PUBLIC, MAIL_REVIEW},
|
|
|
|
|
|
{T("safe"), 2, CA_PUBLIC, MAIL_SAFE},
|
|
|
|
|
|
{T("send"), 2, CA_PUBLIC, MAIL_SEND},
|
|
|
|
|
|
{T("stats"), 2, CA_PUBLIC, MAIL_STATS},
|
|
|
|
|
|
{T("tag"), 1, CA_PUBLIC, MAIL_TAG},
|
|
|
|
|
|
{T("unclear"), 3, CA_PUBLIC, MAIL_UNCLEAR},
|
2026-03-18 12:56:16 -06:00
|
|
|
|
{T("unsafe"), 3, CA_PUBLIC, MAIL_UNSAFE},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("untag"), 3, CA_PUBLIC, MAIL_UNTAG},
|
|
|
|
|
|
{T("urgent"), 2, CA_PUBLIC, MAIL_URGENT},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB malias_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("add"), 1, CA_PUBLIC, MALIAS_ADD},
|
|
|
|
|
|
{T("chown"), 1, CA_PUBLIC, MALIAS_CHOWN},
|
|
|
|
|
|
{T("desc"), 1, CA_PUBLIC, MALIAS_DESC},
|
|
|
|
|
|
{T("delete"), 1, CA_PUBLIC, MALIAS_DELETE},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, MALIAS_LIST},
|
|
|
|
|
|
{T("remove"), 1, CA_PUBLIC, MALIAS_REMOVE},
|
|
|
|
|
|
{T("rename"), 1, CA_PUBLIC, MALIAS_RENAME},
|
|
|
|
|
|
{T("status"), 1, CA_PUBLIC, MALIAS_STATUS},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB mark_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("clear"), 1, CA_PUBLIC, MARK_CLEAR},
|
|
|
|
|
|
{T("set"), 1, CA_PUBLIC, MARK_SET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB markall_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("clear"), 1, CA_PUBLIC, MARK_CLEAR},
|
|
|
|
|
|
{T("set"), 1, CA_PUBLIC, MARK_SET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB motd_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("brief"), 1, CA_WIZARD, MOTD_BRIEF|SW_MULTIPLE},
|
|
|
|
|
|
{T("connect"), 1, CA_WIZARD, MOTD_ALL},
|
|
|
|
|
|
{T("down"), 1, CA_WIZARD, MOTD_DOWN},
|
|
|
|
|
|
{T("full"), 1, CA_WIZARD, MOTD_FULL},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, MOTD_LIST},
|
|
|
|
|
|
{T("wizard"), 1, CA_WIZARD, MOTD_WIZ},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB notify_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_PUBLIC, NFY_NFYALL},
|
|
|
|
|
|
{T("first"), 1, CA_PUBLIC, NFY_NFY},
|
2007-11-26 22:23:34 -08:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, NFY_QUIET|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB open_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("inventory"), 1, CA_PUBLIC, OPEN_INVENTORY},
|
|
|
|
|
|
{T("location"), 1, CA_PUBLIC, OPEN_LOCATION},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB page_sw[] =
|
|
|
|
|
|
{
|
2026-03-04 12:03:45 -07:00
|
|
|
|
{T("blind"), 1, CA_PUBLIC, PAGE_BLIND|SW_MULTIPLE},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("noeval"), 1, CA_PUBLIC, SW_NOEVAL|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-04 12:14:01 -07:00
|
|
|
|
static NAMETAB addcommand_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("noeval"), 1, CA_GOD, ADDCMD_NOEVAL|SW_MULTIPLE},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-04 13:47:30 -07:00
|
|
|
|
static NAMETAB oemit_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, PEMIT_LIST|SW_MULTIPLE},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB pemit_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("contents"), 1, CA_PUBLIC, PEMIT_CONTENTS|SW_MULTIPLE},
|
|
|
|
|
|
{T("html"), 1, CA_PUBLIC, PEMIT_HTML|SW_MULTIPLE},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, PEMIT_LIST|SW_MULTIPLE},
|
|
|
|
|
|
{T("noeval"), 1, CA_PUBLIC, SW_NOEVAL|SW_MULTIPLE},
|
|
|
|
|
|
{T("object"), 1, CA_PUBLIC, 0},
|
|
|
|
|
|
{T("silent"), 1, CA_PUBLIC, 0},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB pose_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("default"), 1, CA_PUBLIC, 0},
|
|
|
|
|
|
{T("noeval"), 3, CA_PUBLIC, SW_NOEVAL|SW_MULTIPLE},
|
|
|
|
|
|
{T("nospace"), 3, CA_PUBLIC, SAY_NOSPACE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB ps_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_PUBLIC, PS_ALL|SW_MULTIPLE},
|
|
|
|
|
|
{T("brief"), 1, CA_PUBLIC, PS_BRIEF},
|
|
|
|
|
|
{T("long"), 1, CA_PUBLIC, PS_LONG},
|
|
|
|
|
|
{T("summary"), 1, CA_PUBLIC, PS_SUMM},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB quota_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_GOD, QUOTA_ALL|SW_MULTIPLE},
|
|
|
|
|
|
{T("fix"), 1, CA_WIZARD, QUOTA_FIX},
|
|
|
|
|
|
{T("remaining"), 1, CA_WIZARD, QUOTA_REM|SW_MULTIPLE},
|
|
|
|
|
|
{T("set"), 1, CA_WIZARD, QUOTA_SET},
|
|
|
|
|
|
{T("total"), 1, CA_WIZARD, QUOTA_TOT|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
static NAMETAB protect_sw[] =
|
|
|
|
|
|
{
|
2026-03-17 00:51:29 -06:00
|
|
|
|
{T("add"), 2, CA_PUBLIC, PROTECT_ADD},
|
|
|
|
|
|
{T("alias"), 2, CA_PUBLIC, PROTECT_ALIAS},
|
|
|
|
|
|
{T("all"), 3, CA_WIZARD, PROTECT_ALL},
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
{T("del"), 1, CA_PUBLIC, PROTECT_DEL},
|
|
|
|
|
|
{T("list"), 1, CA_PUBLIC, PROTECT_LIST},
|
2026-03-17 00:51:29 -06:00
|
|
|
|
{T("unalias"), 1, CA_PUBLIC, PROTECT_UNALIAS},
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2007-09-17 23:56:51 +00:00
|
|
|
|
static NAMETAB reference_sw[] =
|
|
|
|
|
|
{
|
2007-12-21 17:46:20 -08:00
|
|
|
|
{T("list"), 1, CA_PUBLIC, REFERENCE_LIST},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2007-09-17 23:56:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB say_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("noeval"), 1, CA_PUBLIC, SAY_NOEVAL|SW_NOEVAL|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB set_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, SET_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB stats_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_PUBLIC, STAT_ALL},
|
|
|
|
|
|
{T("me"), 1, CA_PUBLIC, STAT_ME},
|
|
|
|
|
|
{T("player"), 1, CA_PUBLIC, STAT_PLAYER},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-04 14:02:21 -07:00
|
|
|
|
static NAMETAB scan_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("globals"), 1, CA_PUBLIC, SCAN_GLOBALS|SW_MULTIPLE},
|
|
|
|
|
|
{T("room"), 1, CA_PUBLIC, SCAN_ROOM|SW_MULTIPLE},
|
|
|
|
|
|
{T("self"), 1, CA_PUBLIC, SCAN_SELF|SW_MULTIPLE},
|
|
|
|
|
|
{T("zone"), 1, CA_PUBLIC, SCAN_ZONE|SW_MULTIPLE},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB sweep_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("commands"), 3, CA_PUBLIC, SWEEP_COMMANDS|SW_MULTIPLE},
|
|
|
|
|
|
{T("connected"), 3, CA_PUBLIC, SWEEP_CONNECT|SW_MULTIPLE},
|
|
|
|
|
|
{T("exits"), 1, CA_PUBLIC, SWEEP_EXITS|SW_MULTIPLE},
|
|
|
|
|
|
{T("here"), 1, CA_PUBLIC, SWEEP_HERE|SW_MULTIPLE},
|
|
|
|
|
|
{T("inventory"), 1, CA_PUBLIC, SWEEP_ME|SW_MULTIPLE},
|
|
|
|
|
|
{T("listeners"), 1, CA_PUBLIC, SWEEP_LISTEN|SW_MULTIPLE},
|
|
|
|
|
|
{T("players"), 1, CA_PUBLIC, SWEEP_PLAYER|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB switch_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("all"), 1, CA_PUBLIC, SWITCH_ANY},
|
|
|
|
|
|
{T("default"), 1, CA_PUBLIC, SWITCH_DEFAULT},
|
|
|
|
|
|
{T("first"), 1, CA_PUBLIC, SWITCH_ONE},
|
|
|
|
|
|
{T("notify"), 1, CA_PUBLIC, SWITCH_NOTIFY|SW_MULTIPLE},
|
2026-03-04 14:46:56 -07:00
|
|
|
|
{T("now"), 1, CA_WIZARD, SWITCH_NOW|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB teleport_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("list"), 1, CA_PUBLIC, TELEPORT_LIST|SW_MULTIPLE},
|
|
|
|
|
|
{T("loud"), 1, CA_PUBLIC, TELEPORT_DEFAULT},
|
|
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, TELEPORT_QUIET},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB timecheck_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("log"), 1, CA_WIZARD, TIMECHK_LOG | SW_MULTIPLE},
|
|
|
|
|
|
{T("reset"), 1, CA_WIZARD, TIMECHK_RESET | SW_MULTIPLE},
|
|
|
|
|
|
{T("screen"), 1, CA_WIZARD, TIMECHK_SCREEN | SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB toad_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("no_chown"), 1, CA_WIZARD, TOAD_NO_CHOWN|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-29 08:54:51 -06:00
|
|
|
|
static NAMETAB walk_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("stop"), 1, CA_PUBLIC, WALK_STOP},
|
|
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, WALK_QUIET|SW_MULTIPLE},
|
|
|
|
|
|
{T("locked"), 1, CA_PUBLIC, WALK_LOCKED|SW_MULTIPLE},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
Add PennMUSH and RhostMUSH feature adoption
PennMUSH: #lambda/#apply anonymous inline attributes, @include with
/nobreak /localize /clearregs, channel mogrifiers (MOGRIFY`BLOCK,
MESSAGE, FORMAT, OVERRIDE, NOBUFFER), cmogrifier().
RhostMUSH: between(), delextract(), garble(), caplist(), moon(),
soundex(), soundlike(), while(), crc32obj(), subnetmatch(),
wrapcolumns(), sandbox() with AST fallback for JIT compatibility.
21 new features/functions, 15 new smoke test files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:08:08 -06:00
|
|
|
|
static NAMETAB include_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("nobreak"), 1, CA_PUBLIC, INCLUDE_NOBREAK},
|
|
|
|
|
|
{T("localize"), 1, CA_PUBLIC, INCLUDE_LOCALIZE|SW_MULTIPLE},
|
|
|
|
|
|
{T("clearregs"), 1, CA_PUBLIC, INCLUDE_CLEARREGS|SW_MULTIPLE},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
static NAMETAB trig_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("quiet"), 1, CA_PUBLIC, TRIG_QUIET},
|
|
|
|
|
|
{T("notify"), 1, CA_PUBLIC, TRIG_NOTIFY|SW_MULTIPLE},
|
2026-03-04 14:46:56 -07:00
|
|
|
|
{T("now"), 1, CA_WIZARD, TRIG_NOW|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB wait_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("until"), 1, CA_PUBLIC, WAIT_UNTIL},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-11-27 05:25:42 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB verb_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("no_name"), 3, CA_PUBLIC, VERB_NONAME},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB wall_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("admin"), 1, CA_ADMIN, SHOUT_ADMIN|SW_MULTIPLE},
|
|
|
|
|
|
{T("emit"), 1, CA_ANNOUNCE, SHOUT_EMIT|SW_MULTIPLE},
|
|
|
|
|
|
{T("no_prefix"), 1, CA_ANNOUNCE, SHOUT_NOTAG|SW_MULTIPLE},
|
|
|
|
|
|
{T("pose"), 1, CA_ANNOUNCE, SHOUT_POSE|SW_MULTIPLE},
|
|
|
|
|
|
{T("wizard"), 1, CA_ANNOUNCE, SHOUT_WIZARD|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static NAMETAB warp_sw[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("check"), 1, CA_WIZARD, TWARP_CLEAN|SW_MULTIPLE},
|
|
|
|
|
|
{T("dump"), 1, CA_WIZARD, TWARP_DUMP|SW_MULTIPLE},
|
|
|
|
|
|
{T("events"), 1, CA_WIZARD, TWARP_EVENTS|SW_MULTIPLE},
|
|
|
|
|
|
{T("idle"), 1, CA_WIZARD, TWARP_IDLE|SW_MULTIPLE},
|
|
|
|
|
|
{T("queue"), 1, CA_WIZARD, TWARP_QUEUE|SW_MULTIPLE},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-18 08:38:44 -06:00
|
|
|
|
static NAMETAB lua_sw[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{T("inline"), 1, CA_WIZARD, LUA_INLINE},
|
|
|
|
|
|
{T("stats"), 1, CA_PUBLIC, LUA_STATS},
|
|
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// @lua handler — execute Lua scripts or show stats.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void do_lua(dbref executor, dbref caller, dbref enactor, int eval,
|
|
|
|
|
|
int key, UTF8 *arg1, const UTF8 *cargs[], int ncargs)
|
|
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(eval);
|
|
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
|
|
|
|
|
|
|
|
|
|
|
if (nullptr == mudstate.pILuaControl)
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Lua module is not loaded."));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (LUA_STATS == key)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t nCalls, nErrors, nInsnHits, nMemHits, nBytes;
|
2026-03-18 09:14:01 -06:00
|
|
|
|
size_t nCacheHits, nCacheMisses, nCacheEntries;
|
2026-03-18 08:38:44 -06:00
|
|
|
|
mudstate.pILuaControl->GetStats(&nCalls, &nErrors,
|
2026-03-18 09:14:01 -06:00
|
|
|
|
&nInsnHits, &nMemHits, &nBytes,
|
|
|
|
|
|
&nCacheHits, &nCacheMisses, &nCacheEntries);
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
notify(executor, tprintf(M_("Lua stats: %zu calls, %zu errors, "
|
2026-03-18 08:38:44 -06:00
|
|
|
|
"%zu insn-limit hits, %zu mem-limit hits, %zu bytes used"),
|
|
|
|
|
|
nCalls, nErrors, nInsnHits, nMemHits, nBytes));
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
notify(executor, tprintf(M_("Cache: %zu entries, %zu hits, %zu misses"),
|
2026-03-18 09:14:01 -06:00
|
|
|
|
nCacheEntries, nCacheHits, nCacheMisses));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (LUA_INLINE == key)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Wizard(executor))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Permission denied."));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
UTF8 result[8000];
|
|
|
|
|
|
size_t nResult = 0;
|
|
|
|
|
|
mudstate.pILuaControl->Eval(executor, caller, enactor,
|
|
|
|
|
|
arg1, strlen(reinterpret_cast<const char *>(arg1)),
|
|
|
|
|
|
result, sizeof(result), &nResult);
|
|
|
|
|
|
notify(executor, result);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Default: @lua obj/attr — execute a Lua script on an object.
|
|
|
|
|
|
//
|
|
|
|
|
|
UTF8 *pSlash = reinterpret_cast<UTF8 *>(
|
|
|
|
|
|
const_cast<char *>(strchr(reinterpret_cast<const char *>(arg1), '/')));
|
|
|
|
|
|
if (nullptr == pSlash)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(executor, M_("Usage: @lua <object>/<attribute>"));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
*pSlash = '\0';
|
|
|
|
|
|
UTF8 *pAttrName = pSlash + 1;
|
|
|
|
|
|
|
|
|
|
|
|
dbref obj = lookup_player(executor, arg1, true);
|
|
|
|
|
|
if (NOTHING == obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
init_match(executor, arg1, NOTYPE);
|
|
|
|
|
|
match_everything(MAT_EXIT_PARENTS);
|
|
|
|
|
|
obj = match_result();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Good_obj(obj))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("No such object."));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UTF8 result[8000];
|
|
|
|
|
|
size_t nResult = 0;
|
|
|
|
|
|
mudstate.pILuaControl->CallAttr(executor, caller, enactor,
|
|
|
|
|
|
obj, pAttrName, nullptr, 0,
|
|
|
|
|
|
result, sizeof(result), &nResult);
|
|
|
|
|
|
notify(executor, result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
|
|
* Command table: Definitions for builtin commands, used to build the command
|
|
|
|
|
|
* hash table.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Format: Name Switches Permissions Needed
|
|
|
|
|
|
* Key (if any) Calling Seq Handler
|
|
|
|
|
|
*/
|
|
|
|
|
|
static CMDENT_NO_ARG command_table_no_arg[] =
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@@"), nullptr, CA_PUBLIC, 0, CS_NO_ARGS, 0, do_comment},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@dbck"), dbck_sw, CA_WIZARD, 0, CS_NO_ARGS, 0, do_dbck},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@dbclean"), nullptr, CA_GOD, 0, CS_NO_ARGS, 0, do_dbclean},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@dump"), dump_sw, CA_WIZARD, 0, CS_NO_ARGS, 0, do_dump},
|
2026-03-04 12:28:38 -07:00
|
|
|
|
{T("@logrotate"), nullptr, CA_WIZARD, 0, CS_NO_ARGS, 0, do_logrotate},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@mark_all"), markall_sw, CA_WIZARD, MARK_SET, CS_NO_ARGS, 0, do_markall},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@readcache"), nullptr, CA_WIZARD, 0, CS_NO_ARGS, 0, do_readcache},
|
|
|
|
|
|
{T("@restart"), nullptr, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_NO_ARGS, 0, do_restart},
|
2026-03-03 11:43:59 -07:00
|
|
|
|
{T("@startslave"), nullptr, CA_WIZARD, 0, CS_NO_ARGS, 0, do_startslave},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@timecheck"), timecheck_sw, CA_WIZARD, 0, CS_NO_ARGS, 0, do_timecheck},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("clearcom"), nullptr, CA_NO_SLAVE, 0, CS_NO_ARGS, 0, do_clearcom},
|
2026-03-04 14:34:21 -07:00
|
|
|
|
{T("help"), nullptr, CA_PUBLIC, CMD_HELP, CS_NO_ARGS, 0, logged_out0},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("info"), nullptr, CA_PUBLIC, CMD_INFO, CS_NO_ARGS, 0, logged_out0},
|
|
|
|
|
|
{T("inventory"), nullptr, CA_PUBLIC, 0, CS_NO_ARGS, 0, do_inventory},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("leave"), leave_sw, CA_LOCATION, 0, CS_NO_ARGS, 0, do_leave},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("logout"), nullptr, CA_PUBLIC, CMD_LOGOUT, CS_NO_ARGS, 0, logged_out0},
|
|
|
|
|
|
{T("quit"), nullptr, CA_PUBLIC, CMD_QUIT, CS_NO_ARGS, 0, logged_out0},
|
|
|
|
|
|
{T("report"), nullptr, CA_PUBLIC, 0, CS_NO_ARGS, 0, do_report},
|
|
|
|
|
|
{T("score"), nullptr, CA_PUBLIC, 0, CS_NO_ARGS, 0, do_score},
|
|
|
|
|
|
{T("version"), nullptr, CA_PUBLIC, 0, CS_NO_ARGS, 0, do_version},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), nullptr, 0, 0, 0, 0, nullptr}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static CMDENT_ONE_ARG command_table_one_arg[] =
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@apply_marked"), nullptr, CA_WIZARD|CA_GBL_INTERP, 0, CS_ONE_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_apply_marked},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@boot"), boot_sw, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, 0, do_boot},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@ccreate"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG, 0, do_createchannel},
|
|
|
|
|
|
{T("@cdestroy"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG, 0, do_destroychannel},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@clist"), clist_sw, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_chanlist},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@cut"), nullptr, CA_WIZARD|CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, 0, do_cut},
|
|
|
|
|
|
{T("@cwho"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_channelwho},
|
2026-03-10 01:34:06 -06:00
|
|
|
|
{T("@crondel"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_crondel},
|
|
|
|
|
|
{T("@crontab"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_crontab},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@destroy"), destroy_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, DEST_ONE, CS_ONE_ARG|CS_INTERP, 0, do_destroy},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@disable"), nullptr, CA_WIZARD, GLOB_DISABLE, CS_ONE_ARG, 0, do_global},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@doing"), doing_sw, CA_PUBLIC, 0, CS_ONE_ARG, 0, do_doing},
|
|
|
|
|
|
{T("@emit"), emit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, SAY_EMIT, CS_ONE_ARG|CS_INTERP, 0, do_say},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@enable"), nullptr, CA_WIZARD, GLOB_ENABLE, CS_ONE_ARG, 0, do_global},
|
|
|
|
|
|
{T("@entrances"), nullptr, CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_entrances},
|
|
|
|
|
|
{T("@eval"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, 0, do_eval},
|
|
|
|
|
|
{T("@find"), nullptr, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_find},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@halt"), halt_sw, CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, 0, do_halt},
|
2026-03-04 14:56:46 -07:00
|
|
|
|
{T("@hook"), hook_sw, CA_GOD, 0, CS_ONE_ARG|CS_NOINTERP, 0, do_hook},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@kick"), nullptr, CA_WIZARD, QUEUE_KICK, CS_ONE_ARG|CS_INTERP, 0, do_queue},
|
|
|
|
|
|
{T("@last"), nullptr, CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_last},
|
|
|
|
|
|
{T("@list"), nullptr, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_list},
|
2026-03-18 08:38:44 -06:00
|
|
|
|
{T("@lua"), lua_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_lua},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@list_file"), nullptr, CA_WIZARD, 0, CS_ONE_ARG|CS_INTERP, 0, do_list_file},
|
|
|
|
|
|
{T("@listcommands"), nullptr, CA_GOD, 0, CS_ONE_ARG, 0, do_listcommands},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@listmotd"), listmotd_sw,CA_PUBLIC, MOTD_LIST, CS_ONE_ARG, 0, do_motd},
|
|
|
|
|
|
{T("@mark"), mark_sw, CA_WIZARD, SRCH_MARK, CS_ONE_ARG|CS_NOINTERP, 0, do_search},
|
|
|
|
|
|
{T("@motd"), motd_sw, CA_WIZARD, 0, CS_ONE_ARG, 0, do_motd},
|
|
|
|
|
|
{T("@nemit"), emit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, SAY_EMIT, CS_ONE_ARG|CS_UNPARSE|CS_NOSQUISH, 0, do_say},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@poor"), nullptr, CA_GOD, 0, CS_ONE_ARG|CS_INTERP, 0, do_poor},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@ps"), ps_sw, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_ps},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@quitprogram"), nullptr, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_quitprog},
|
2026-03-04 14:02:21 -07:00
|
|
|
|
{T("@scan"), scan_sw, CA_PUBLIC, 0, CS_ONE_ARG|CS_NOINTERP, 0, do_scan},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@search"), nullptr, CA_PUBLIC, SRCH_SEARCH, CS_ONE_ARG|CS_NOINTERP, 0, do_search},
|
|
|
|
|
|
{T("@shutdown"), nullptr, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_shutdown},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@stats"), stats_sw, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_stats},
|
|
|
|
|
|
{T("@sweep"), sweep_sw, CA_PUBLIC, 0, CS_ONE_ARG, 0, do_sweep},
|
|
|
|
|
|
{T("@timewarp"), warp_sw, CA_WIZARD, 0, CS_ONE_ARG|CS_INTERP, 0, do_timewarp},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@unlink"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD, 0, CS_ONE_ARG|CS_INTERP, 0, do_unlink},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@unlock"), lock_sw, CA_NO_SLAVE, 0, CS_ONE_ARG|CS_INTERP, 0, do_unlock},
|
|
|
|
|
|
{T("@wall"), wall_sw, CA_ANNOUNCE, SHOUT_DEFAULT, CS_ONE_ARG|CS_INTERP, 0, do_shout},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@wipe"), nullptr, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_ONE_ARG|CS_INTERP, 0, do_wipe},
|
|
|
|
|
|
{T("allcom"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_allcom},
|
|
|
|
|
|
{T("comlist"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_comlist},
|
|
|
|
|
|
{T("delcom"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_delcom},
|
|
|
|
|
|
{T("doing"), nullptr, CA_PUBLIC, CMD_DOING, CS_ONE_ARG, 0, logged_out1},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("drop"), drop_sw, CA_NO_SLAVE|CA_CONTENTS|CA_LOCATION|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_drop},
|
|
|
|
|
|
{T("enter"), enter_sw, CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, 0, do_enter},
|
|
|
|
|
|
{T("examine"), examine_sw, CA_PUBLIC, 0, CS_ONE_ARG|CS_INTERP, 0, do_examine},
|
|
|
|
|
|
{T("get"), get_sw, CA_LOCATION|CA_NO_GUEST, 0, CS_ONE_ARG|CS_INTERP, 0, do_get},
|
|
|
|
|
|
{T("goto"), goto_sw, CA_LOCATION, 0, CS_ONE_ARG|CS_INTERP, 0, do_move},
|
|
|
|
|
|
{T("look"), look_sw, CA_LOCATION, LOOK_LOOK, CS_ONE_ARG|CS_INTERP, 0, do_look},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("outputprefix"), nullptr, CA_PUBLIC, CMD_PREFIX, CS_ONE_ARG, 0, logged_out1},
|
|
|
|
|
|
{T("outputsuffix"), nullptr, CA_PUBLIC, CMD_SUFFIX, CS_ONE_ARG, 0, logged_out1},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("pose"), pose_sw, CA_LOCATION|CA_NO_SLAVE, SAY_POSE, CS_ONE_ARG|CS_INTERP, 0, do_say},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("puebloclient"), nullptr, CA_PUBLIC, CMD_PUEBLOCLIENT, CS_ONE_ARG, 0, logged_out1},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("say"), say_sw, CA_LOCATION|CA_NO_SLAVE, SAY_SAY, CS_ONE_ARG|CS_INTERP, 0, do_say},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("session"), nullptr, CA_PUBLIC, CMD_SESSION, CS_ONE_ARG, 0, logged_out1},
|
|
|
|
|
|
{T("think"), nullptr, CA_NO_SLAVE, 0, CS_ONE_ARG, 0, do_think},
|
|
|
|
|
|
{T("train"), nullptr, CA_PUBLIC, 0, CS_ONE_ARG, 0, do_train},
|
|
|
|
|
|
{T("use"), nullptr, CA_NO_SLAVE|CA_GBL_INTERP, 0, CS_ONE_ARG|CS_INTERP, 0, do_use},
|
|
|
|
|
|
{T("who"), nullptr, CA_PUBLIC, CMD_WHO, CS_ONE_ARG, 0, logged_out1},
|
|
|
|
|
|
{T("\\"), nullptr, CA_NO_GUEST|CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, 0, do_say},
|
|
|
|
|
|
{T(":"), nullptr, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, 0, do_say},
|
|
|
|
|
|
{T(";"), nullptr, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, 0, do_say},
|
|
|
|
|
|
{T("\""), nullptr, CA_LOCATION|CF_DARK|CA_NO_SLAVE, SAY_PREFIX, CS_ONE_ARG|CS_INTERP|CS_LEADIN, 0, do_say},
|
|
|
|
|
|
{T("-"), nullptr, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_ONE_ARG|CS_LEADIN, 0, do_postpend},
|
|
|
|
|
|
{T("~"), nullptr, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_ONE_ARG|CS_LEADIN, 0, do_prepend},
|
|
|
|
|
|
{T("#"), nullptr, CA_NO_SLAVE|CA_GBL_INTERP|CF_DARK, 0, CS_ONE_ARG|CS_INTERP|CS_CMDARG, 0, do_force_prefixed},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), nullptr, 0, 0, 0, 0, nullptr}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static CMDENT_TWO_ARG command_table_two_arg[] =
|
|
|
|
|
|
{
|
2026-03-04 12:14:01 -07:00
|
|
|
|
{T("@addcommand"), addcommand_sw, CA_GOD, 0, CS_TWO_ARG, 0, do_addcommand},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@admin"), nullptr, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, 0, do_admin},
|
|
|
|
|
|
{T("@alias"), nullptr, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_TWO_ARG, 0, do_alias},
|
2012-07-10 09:48:56 -07:00
|
|
|
|
{T("@assert"), break_sw, CA_PUBLIC, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_assert},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@attribute"), attrib_sw, CA_GOD, 0, CS_TWO_ARG|CS_INTERP, 0, do_attribute},
|
2012-07-10 09:48:56 -07:00
|
|
|
|
{T("@break"), break_sw, CA_PUBLIC, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_break},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@cboot"), cboot_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_chboot},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@ccharge"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, EDIT_CHANNEL_CCHARGE, CS_TWO_ARG, 0, do_editchannel},
|
|
|
|
|
|
{T("@cchown"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, EDIT_CHANNEL_CCHOWN, CS_TWO_ARG, 0, do_editchannel},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@cemit"), cemit_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_cemit},
|
|
|
|
|
|
{T("@chown"), chown_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, CHOWN_ONE, CS_TWO_ARG|CS_INTERP, 0, do_chown},
|
|
|
|
|
|
{T("@chownall"), chown_sw, CA_WIZARD|CA_GBL_BUILD, CHOWN_ALL, CS_TWO_ARG|CS_INTERP, 0, do_chownall},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@chzone"), nullptr, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_INTERP, 0, do_chzone},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@clone"), clone_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_clone},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@coflags"), nullptr, CA_NO_SLAVE, EDIT_CHANNEL_COFLAGS, CS_TWO_ARG, 0, do_editchannel},
|
|
|
|
|
|
{T("@cpflags"), nullptr, CA_NO_SLAVE, EDIT_CHANNEL_CPFLAGS, CS_TWO_ARG, 0, do_editchannel},
|
|
|
|
|
|
{T("@create"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_create},
|
2026-03-10 01:34:06 -06:00
|
|
|
|
{T("@cron"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_cron},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@cset"), cset_sw, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, 0, do_chopen},
|
|
|
|
|
|
{T("@decompile"), decomp_sw, CA_PUBLIC, 0, CS_TWO_ARG|CS_INTERP, 0, do_decomp},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@delcommand"), nullptr, CA_GOD, 0, CS_TWO_ARG, 0, do_delcommand},
|
2007-09-02 21:44:11 -07:00
|
|
|
|
{T("@dolist"), dolist_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_dolist},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@drain"), nullptr, CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST, NFY_DRAIN, CS_TWO_ARG, 0, do_notify},
|
|
|
|
|
|
{T("@email"), nullptr, CA_WIZARD, 0, CS_TWO_ARG, 0, do_plusemail},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@femit"), femit_sw, CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE, PEMIT_FEMIT, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
|
|
|
|
|
{T("@fixdb"), fixdb_sw, CA_GOD, 0, CS_TWO_ARG|CS_INTERP, 0, do_fixdb},
|
|
|
|
|
|
{T("@flag"), flag_sw, CA_GOD, 0, CS_TWO_ARG, 0, do_flag},
|
2007-09-03 17:57:33 -07:00
|
|
|
|
{T("@folder"), folder_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_folder},
|
2026-03-04 14:46:56 -07:00
|
|
|
|
{T("@force"), force_sw, CA_NO_SLAVE|CA_GBL_INTERP|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP|CS_CMDARG, 0, do_force},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@forwardlist"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_forwardlist},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@fpose"), fpose_sw, CA_LOCATION|CA_NO_SLAVE, PEMIT_FPOSE, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@fsay"), nullptr, CA_LOCATION|CA_NO_SLAVE, PEMIT_FSAY, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@function"), function_sw,CA_GOD, 0, CS_TWO_ARG|CS_INTERP, 0, do_function},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@link"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_link},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@lock"), lock_sw, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, 0, do_lock},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@log"), nullptr, CA_WIZARD, 0, CS_TWO_ARG, 0, do_log},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@mail"), mail_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_mail},
|
|
|
|
|
|
{T("@malias"), malias_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_malias},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@moniker"), nullptr, CA_NO_GUEST|CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, 0, do_moniker},
|
|
|
|
|
|
{T("@name"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_name},
|
|
|
|
|
|
{T("@newpassword"), nullptr, CA_WIZARD, 0, CS_TWO_ARG, 0, do_newpassword},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@notify"), notify_sw, CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_notify},
|
|
|
|
|
|
{T("@npemit"), pemit_sw, CA_NO_GUEST|CA_NO_SLAVE, PEMIT_PEMIT, CS_TWO_ARG|CS_UNPARSE|CS_NOSQUISH, 0, do_pemit},
|
2026-03-04 13:47:30 -07:00
|
|
|
|
{T("@oemit"), oemit_sw, CA_NO_GUEST|CA_NO_SLAVE, PEMIT_OEMIT, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@parent"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_parent},
|
|
|
|
|
|
{T("@password"), nullptr, CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_password},
|
|
|
|
|
|
{T("@pcreate"), nullptr, CA_WIZARD|CA_GBL_BUILD, PCRE_PLAYER, CS_TWO_ARG, 0, do_pcreate},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@pemit"), pemit_sw, CA_NO_GUEST|CA_NO_SLAVE, PEMIT_PEMIT, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@power"), nullptr, CA_PUBLIC, 0, CS_TWO_ARG, 0, do_power},
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
{T("@protect"), protect_sw, CA_NO_GUEST|CA_NO_SLAVE, PROTECT_ADD, CS_TWO_ARG|CS_INTERP, 0, do_protect},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@program"), nullptr, CA_PUBLIC, 0, CS_TWO_ARG|CS_INTERP, 0, do_prog},
|
2007-09-02 21:44:11 -07:00
|
|
|
|
{T("@query"), query_sw, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP|CS_CMDARG, 0, do_query},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@quota"), quota_sw, CA_PUBLIC, 0, CS_TWO_ARG|CS_INTERP, 0, do_quota},
|
2007-09-26 12:04:34 -07:00
|
|
|
|
{T("@reference"), reference_sw, CA_PUBLIC, 0, CS_TWO_ARG|CS_INTERP, 0, do_reference},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@robot"), nullptr, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST|CA_PLAYER, PCRE_ROBOT, CS_TWO_ARG, 0, do_pcreate},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef REALITY_LVLS
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@rxlevel"), nullptr, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, 0, do_rxlevel},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#endif
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@set"), set_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG, 0, do_set},
|
|
|
|
|
|
{T("@teleport"), teleport_sw,CA_NO_GUEST, TELEPORT_DEFAULT, CS_TWO_ARG|CS_INTERP, 0, do_teleport},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef REALITY_LVLS
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@txlevel"), nullptr, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, 0, do_txlevel},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#endif
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@toad"), toad_sw, CA_WIZARD, 0, CS_TWO_ARG|CS_INTERP, 0, do_toad},
|
2026-03-29 08:54:51 -06:00
|
|
|
|
{T("@walk"), walk_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_walk},
|
|
|
|
|
|
{T("@patrol"), walk_sw, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_patrol},
|
2007-09-02 21:44:11 -07:00
|
|
|
|
{T("@wait"), wait_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_wait},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("addcom"), nullptr, CA_NO_SLAVE, 0, CS_TWO_ARG, 0, do_addcom},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("comtitle"), comtitle_sw,CA_NO_SLAVE, 0, CS_TWO_ARG, 0, do_comtitle},
|
|
|
|
|
|
{T("give"), give_sw, CA_LOCATION|CA_NO_GUEST, 0, CS_TWO_ARG|CS_INTERP, 0, do_give},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("kill"), nullptr, CA_NO_GUEST|CA_NO_SLAVE, KILL_KILL, CS_TWO_ARG|CS_INTERP, 0, do_kill},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("page"), page_sw, CA_NO_SLAVE, 0, CS_TWO_ARG|CS_INTERP, 0, do_page},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("slay"), nullptr, CA_WIZARD, KILL_SLAY, CS_TWO_ARG|CS_INTERP, 0, do_kill},
|
|
|
|
|
|
{T("whisper"), nullptr, CA_LOCATION|CA_NO_SLAVE, PEMIT_WHISPER, CS_TWO_ARG|CS_INTERP, 0, do_pemit},
|
|
|
|
|
|
{T("&"), nullptr, CA_NO_GUEST|CA_NO_SLAVE|CF_DARK, 0, CS_TWO_ARG|CS_LEADIN, 0, do_setvattr},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), nullptr, 0, 0, 0, 0, nullptr}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static CMDENT_TWO_ARG_ARGV command_table_two_arg_argv[] =
|
|
|
|
|
|
{
|
2026-03-03 19:52:20 -07:00
|
|
|
|
{T("@cpattr"), nullptr, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, 0, do_cpattr},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@dig"), dig_sw, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, 0, do_dig},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@edit"), nullptr, CA_NO_SLAVE|CA_NO_GUEST, 0, CS_TWO_ARG|CS_ARGV|CS_STRIP_AROUND, 0, do_edit},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@icmd"), icmd_sw, CA_GOD, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, 0, do_icmd},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@if"), nullptr, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_if},
|
Add PennMUSH and RhostMUSH feature adoption
PennMUSH: #lambda/#apply anonymous inline attributes, @include with
/nobreak /localize /clearregs, channel mogrifiers (MOGRIFY`BLOCK,
MESSAGE, FORMAT, OVERRIDE, NOBUFFER), cmogrifier().
RhostMUSH: between(), delextract(), garble(), caplist(), moon(),
soundex(), soundlike(), while(), crc32obj(), subnetmatch(),
wrapcolumns(), sandbox() with AST fallback for JIT compatibility.
21 new features/functions, 15 new smoke test files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:08:08 -06:00
|
|
|
|
{T("@include"), include_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV, 0, do_include},
|
2018-10-03 17:54:51 +00:00
|
|
|
|
{T("@mvattr"), nullptr, CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD, 0, CS_TWO_ARG|CS_ARGV, 0, do_mvattr},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@open"), open_sw, CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP, 0, do_open},
|
2007-09-02 22:02:33 -07:00
|
|
|
|
{T("@switch"), switch_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND, 0, do_switch},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("@trigger"), trig_sw, CA_GBL_INTERP, 0, CS_TWO_ARG|CS_ARGV, 0, do_trigger},
|
|
|
|
|
|
{T("@verb"), verb_sw, CA_GBL_INTERP|CA_NO_SLAVE, 0, CS_TWO_ARG|CS_ARGV|CS_INTERP|CS_STRIP_AROUND, 0, do_verb},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), nullptr, 0, 0, 0, 0, nullptr}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static CMDENT *goto_cmdp;
|
|
|
|
|
|
|
|
|
|
|
|
void commands_no_arg_add(CMDENT_NO_ARG cmdent[])
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
for (CMDENT_NO_ARG* cp0a = cmdent; cp0a->cmdname; cp0a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nLen = strlen(reinterpret_cast<const char*>(cp0a->cmdname));
|
|
|
|
|
|
auto it = mudstate.command_htab.find(std::vector<UTF8>(cp0a->cmdname, cp0a->cmdname + nLen));
|
|
|
|
|
|
if (it == mudstate.command_htab.end())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.emplace(std::vector<UTF8>(cp0a->cmdname, cp0a->cmdname + nLen), cp0a);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void commands_one_arg_add(CMDENT_ONE_ARG cmdent[])
|
|
|
|
|
|
{
|
|
|
|
|
|
CMDENT_ONE_ARG *cp1a;
|
|
|
|
|
|
for (cp1a = cmdent; cp1a->cmdname; cp1a++)
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nLen = strlen(reinterpret_cast<const char*>(cp1a->cmdname));
|
|
|
|
|
|
auto it = mudstate.command_htab.find(std::vector<UTF8>(cp1a->cmdname, cp1a->cmdname + nLen));
|
|
|
|
|
|
if (it == mudstate.command_htab.end())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.emplace(std::vector<UTF8>(cp1a->cmdname, cp1a->cmdname + nLen), cp1a);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void commands_two_arg_add(CMDENT_TWO_ARG cmdent[])
|
|
|
|
|
|
{
|
|
|
|
|
|
CMDENT_TWO_ARG *cp2a;
|
|
|
|
|
|
for (cp2a = cmdent; cp2a->cmdname; cp2a++)
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nLen = strlen(reinterpret_cast<const char*>(cp2a->cmdname));
|
|
|
|
|
|
auto it = mudstate.command_htab.find(std::vector<UTF8>(cp2a->cmdname, cp2a->cmdname + nLen));
|
|
|
|
|
|
if (it == mudstate.command_htab.end())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.emplace(std::vector<UTF8>(cp2a->cmdname, cp2a->cmdname + nLen), cp2a);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void commands_two_arg_argv_add(CMDENT_TWO_ARG_ARGV cmdent[])
|
|
|
|
|
|
{
|
|
|
|
|
|
CMDENT_TWO_ARG_ARGV *cp2aa;
|
|
|
|
|
|
for (cp2aa = cmdent; cp2aa->cmdname; cp2aa++)
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nLen = strlen(reinterpret_cast<const char*>(cp2aa->cmdname));
|
|
|
|
|
|
auto it = mudstate.command_htab.find(std::vector<UTF8>(cp2aa->cmdname, cp2aa->cmdname + nLen));
|
|
|
|
|
|
if (it == mudstate.command_htab.end())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.emplace(std::vector<UTF8>(cp2aa->cmdname, cp2aa->cmdname + nLen), cp2aa);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init_cmdtab(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Load attribute-setting commands.
|
|
|
|
|
|
//
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (ATTR* ap = AttrTable; ap->name; ap++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (ap->flags & AF_NOCMD)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t nBuffer;
|
|
|
|
|
|
bool bValid;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
const UTF8 *cbuff = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
CMDENT_TWO_ARG *cp2a = nullptr;
|
2006-09-29 18:29:18 +00:00
|
|
|
|
try
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2006-09-29 18:29:18 +00:00
|
|
|
|
cp2a = new CMDENT_TWO_ARG;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (...)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != cp2a)
|
2006-09-29 18:29:18 +00:00
|
|
|
|
{
|
2007-03-14 00:55:08 +00:00
|
|
|
|
cp2a->cmdname = StringClone(cbuff);
|
2006-09-29 18:29:18 +00:00
|
|
|
|
cp2a->perms = CA_NO_GUEST | CA_NO_SLAVE;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
cp2a->switches = nullptr;
|
2006-09-29 18:29:18 +00:00
|
|
|
|
if (ap->flags & (AF_WIZARD | AF_MDARK))
|
|
|
|
|
|
{
|
|
|
|
|
|
cp2a->perms |= CA_WIZARD;
|
|
|
|
|
|
}
|
|
|
|
|
|
cp2a->extra = ap->number;
|
|
|
|
|
|
cp2a->callseq = CS_TWO_ARG;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
cp2a->flags = CEF_ALLOC;
|
2006-09-29 18:29:18 +00:00
|
|
|
|
cp2a->handler = do_setattr;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.emplace(std::vector<UTF8>(cp2a->cmdname, cp2a->cmdname + nBuffer), cp2a);
|
2006-09-29 18:29:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
Remove ISOUTOFMEMORY macro; add per-site OOM recovery and fix g_dump_child_pid
Eliminate the ISOUTOFMEMORY macro that unconditionally aborted on allocation
failure. Each of the 23 call sites now handles OOM appropriately:
- Fatal sites (buffer pools, db array, anum table): mux_assert or OutOfMemory
- Recoverable sites (queue, mail, commands, guests, vattrs, config, restart,
forward lists): log the failure and return gracefully
Also fix g_dump_child_pid portability: volatile pid_t -> volatile sig_atomic_t
with explicit casts in ganl_adapter.cpp.
Close integer overflow issue as false alarm (getstring_noalloc uses a bounded
static buffer, so nBuffer+1 cannot wrap).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:31:20 -06:00
|
|
|
|
STARTLOG(LOG_PROBLEMS, "CMD", "MEM");
|
|
|
|
|
|
log_printf(T("init_cmdtab: out of memory adding @set-attr command."));
|
|
|
|
|
|
ENDLOG;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Load the builtin commands
|
|
|
|
|
|
//
|
|
|
|
|
|
commands_no_arg_add(command_table_no_arg);
|
|
|
|
|
|
commands_one_arg_add(command_table_one_arg);
|
|
|
|
|
|
commands_two_arg_add(command_table_two_arg);
|
|
|
|
|
|
commands_two_arg_argv_add(command_table_two_arg_argv);
|
|
|
|
|
|
|
2007-12-09 00:53:07 +00:00
|
|
|
|
cache_prefix_cmds();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
const UTF8 *tmp = reinterpret_cast<const UTF8*>("goto");
|
|
|
|
|
|
auto it = mudstate.command_htab.find(std::vector<UTF8>(tmp, tmp + 4));
|
|
|
|
|
|
goto_cmdp = (it != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-09 00:53:07 +00:00
|
|
|
|
static CMDENT *g_prefix_cmds[256];
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
void clear_prefix_cmds()
|
|
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (auto& g_prefix_cmd : g_prefix_cmds)
|
2012-03-15 08:20:40 -07:00
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
g_prefix_cmd = nullptr;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 14:04:30 -07:00
|
|
|
|
#ifdef SELFCHECK
|
2012-03-15 08:20:40 -07:00
|
|
|
|
void finish_cmdtab()
|
|
|
|
|
|
{
|
|
|
|
|
|
clear_prefix_cmds();
|
2018-10-03 17:54:51 +00:00
|
|
|
|
goto_cmdp = nullptr;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|
|
|
|
|
|
// First pass is to get rid of aliases.
|
|
|
|
|
|
//
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
StringPtrMap ht;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
CMDENT *cmdp;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
for (auto &[key, val] : mudstate.command_htab)
|
2012-03-15 08:20:40 -07:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
cmdp = static_cast<CMDENT*>(val);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (0 == (cmdp->flags & CEF_VISITED))
|
|
|
|
|
|
{
|
|
|
|
|
|
cmdp->flags |= CEF_VISITED;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nLen = strlen(reinterpret_cast<char*>(cmdp->cmdname));
|
|
|
|
|
|
ht.emplace(std::vector<UTF8>(cmdp->cmdname, cmdp->cmdname + nLen), cmdp);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
mudstate.command_htab.clear();
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|
|
|
|
|
|
// Second pass is to free unique CMDENTs and related things.
|
|
|
|
|
|
//
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
for (auto &[htkey, htval] : ht)
|
2012-03-15 08:20:40 -07:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
cmdp = static_cast<CMDENT*>(htval);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (cmdp->callseq & CS_ADDED)
|
|
|
|
|
|
{
|
2026-03-19 08:48:37 -06:00
|
|
|
|
delete cmdp->addent;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
cmdp->addent = nullptr;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cmdp->flags & CEF_ALLOC)
|
|
|
|
|
|
{
|
|
|
|
|
|
MEMFREE(cmdp->cmdname);
|
2018-10-03 17:54:51 +00:00
|
|
|
|
cmdp->cmdname = nullptr;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
delete cmdp;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
cmdp = nullptr;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-03-15 14:04:30 -07:00
|
|
|
|
#endif
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
/*! \brief Fills in the table of single-character prefix commands.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Command entries for known prefix commands (<code>" : ; \ # & - ~</code>)
|
|
|
|
|
|
* are copied from the regular command table. Entries for all other starting
|
2018-10-03 17:54:51 +00:00
|
|
|
|
* characters are set to nullptr.
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*
|
|
|
|
|
|
* \return None.
|
|
|
|
|
|
*/
|
2007-12-09 00:53:07 +00:00
|
|
|
|
void cache_prefix_cmds(void)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
clear_prefix_cmds();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
#define SET_PREFIX_CMD(s) \
|
|
|
|
|
|
do { \
|
|
|
|
|
|
const UTF8 *_tmp = reinterpret_cast<const UTF8*>(s); \
|
|
|
|
|
|
auto _it = mudstate.command_htab.find(std::vector<UTF8>(_tmp, _tmp + 1)); \
|
2026-03-03 18:39:35 -07:00
|
|
|
|
g_prefix_cmds[static_cast<unsigned char>((s)[0])] = \
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
(_it != mudstate.command_htab.end()) ? static_cast<CMDENT*>(_it->second) : nullptr; \
|
|
|
|
|
|
} while (0)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
SET_PREFIX_CMD("\"");
|
|
|
|
|
|
SET_PREFIX_CMD(":");
|
|
|
|
|
|
SET_PREFIX_CMD(";");
|
|
|
|
|
|
SET_PREFIX_CMD("\\");
|
|
|
|
|
|
SET_PREFIX_CMD("#");
|
|
|
|
|
|
SET_PREFIX_CMD("&");
|
|
|
|
|
|
SET_PREFIX_CMD("-");
|
|
|
|
|
|
SET_PREFIX_CMD("~");
|
|
|
|
|
|
#undef SET_PREFIX_CMD
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-12-23 23:00:58 -08:00
|
|
|
|
inline bool is_prefix_cmd(const UTF8 *pCommand, size_t *pnPrefix, CMDENT **ppcmd)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2009-11-12 21:42:05 -08:00
|
|
|
|
bool fReturn = false;
|
|
|
|
|
|
size_t nPrefix = 0;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
CMDENT *pcmd = nullptr;
|
2009-11-12 21:42:05 -08:00
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != pCommand)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2026-03-03 18:39:35 -07:00
|
|
|
|
pcmd = g_prefix_cmds[static_cast<unsigned char>(pCommand[0])];
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != pcmd)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2009-11-12 21:42:05 -08:00
|
|
|
|
nPrefix = 1;
|
|
|
|
|
|
fReturn = true;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if ( 0xE2 == pCommand[0]
|
|
|
|
|
|
&& 0x80 == pCommand[1]
|
|
|
|
|
|
&& 0x9C == pCommand[2])
|
|
|
|
|
|
{
|
|
|
|
|
|
// U+201C is a Unicode quote typically sent instead of ASCII double quote.
|
|
|
|
|
|
//
|
2026-03-03 18:39:35 -07:00
|
|
|
|
pcmd = g_prefix_cmds[static_cast<unsigned char>('"')];
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != pcmd)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2009-11-12 21:42:05 -08:00
|
|
|
|
nPrefix = 3;
|
|
|
|
|
|
fReturn = true;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2009-11-12 21:42:05 -08:00
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != pnPrefix)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2009-11-12 21:42:05 -08:00
|
|
|
|
*pnPrefix = nPrefix;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
}
|
2009-11-12 21:42:05 -08:00
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != ppcmd)
|
2007-12-09 00:53:07 +00:00
|
|
|
|
{
|
2009-11-12 21:42:05 -08:00
|
|
|
|
*ppcmd = pcmd;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
}
|
2009-11-12 21:42:05 -08:00
|
|
|
|
return fReturn;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// check_access: Check if player has access to function.
|
|
|
|
|
|
//
|
|
|
|
|
|
bool check_access(dbref player, int mask)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mask & (CA_DISABLED|CA_STATIC))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( God(player)
|
|
|
|
|
|
|| mudstate.bReadingConfiguration)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & CA_MUSTBE_MASK)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Since CA_GOD by itself is a frequent case, for the sake of
|
|
|
|
|
|
// performance, we test CA_GOD specifically. If CA_GOD were ever
|
|
|
|
|
|
// combined with anything, it would be passed through to the general
|
|
|
|
|
|
// case.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ((mask & CA_MUSTBE_MASK) == CA_GOD)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Since God(player) is always false here, CA_GOD is still handled by
|
|
|
|
|
|
// the following code even though it doesn't appear in any of the
|
|
|
|
|
|
// cases explicitly. CA_WIZARD by itself is also a common case, but
|
|
|
|
|
|
// since we have have a bit (mask & CA_MUSTBE_MASK), and since that
|
|
|
|
|
|
// bit is not a lone CA_GOD bit (handled above), and since CA_WIZARD
|
|
|
|
|
|
// it tested first below, it doesn't make sense to test CA_WIZARD
|
|
|
|
|
|
// as a special case.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!( ((mask & CA_WIZARD) && Wizard(player))
|
|
|
|
|
|
|| ((mask & CA_ADMIN) && WizRoy(player))
|
|
|
|
|
|
|| ((mask & CA_BUILDER) && Builder(player))
|
|
|
|
|
|
|| ((mask & CA_STAFF) && Staff(player))
|
|
|
|
|
|
|| ((mask & CA_HEAD) && Head(player))
|
|
|
|
|
|
|| ((mask & CA_ANNOUNCE) && Announce(player))
|
|
|
|
|
|
|| ((mask & CA_IMMORTAL) && Immortal(player))
|
|
|
|
|
|
|| ((mask & CA_UNINS) && Uninspected(player))
|
|
|
|
|
|
|| ((mask & CA_ROBOT) && Robot(player))))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for forbidden flags.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( (mask & CA_CANTBE_MASK)
|
|
|
|
|
|
&& !Wizard(player))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( ((mask & CA_NO_HAVEN) && Player_haven(player))
|
|
|
|
|
|
|| ((mask & CA_NO_ROBOT) && Robot(player))
|
|
|
|
|
|
|| ((mask & CA_NO_SLAVE) && Slave(player))
|
|
|
|
|
|
|| ((mask & CA_NO_SUSPECT) && Suspect(player))
|
|
|
|
|
|
|| ((mask & CA_NO_GUEST) && Guest(player))
|
|
|
|
|
|
|| ((mask & CA_NO_UNINS) && Uninspected(player)))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
|
|
* Process the various hook calls.
|
|
|
|
|
|
* Idea taken from TinyMUSH3, code from RhostMUSH, ported by Jake Nelson.
|
|
|
|
|
|
* Hooks processed: before, after, ignore, permit, fail
|
|
|
|
|
|
*****************************************************************************/
|
2007-03-14 22:33:04 +00:00
|
|
|
|
static UTF8 *hook_name(const UTF8 *pCommand, int key)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-09-15 08:59:39 -07:00
|
|
|
|
const char *keylet;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
switch (key)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_AFAIL:
|
2006-09-01 22:59:23 +00:00
|
|
|
|
keylet = "AF";
|
|
|
|
|
|
break;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_AFTER:
|
2006-09-01 22:59:23 +00:00
|
|
|
|
keylet = "A";
|
|
|
|
|
|
break;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_BEFORE:
|
2006-09-01 22:59:23 +00:00
|
|
|
|
keylet = "B";
|
|
|
|
|
|
break;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_IGNORE:
|
2006-09-01 22:59:23 +00:00
|
|
|
|
keylet = "I";
|
|
|
|
|
|
break;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_PERMIT:
|
2006-09-01 22:59:23 +00:00
|
|
|
|
keylet = "P";
|
|
|
|
|
|
break;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
case CEF_HOOK_ARGS:
|
2007-11-03 21:34:30 -07:00
|
|
|
|
keylet = "R";
|
|
|
|
|
|
break;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
default:
|
2018-10-03 17:54:51 +00:00
|
|
|
|
return nullptr;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
|
const UTF8 *cmdName = pCommand;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( pCommand[0]
|
|
|
|
|
|
&& !pCommand[1])
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (pCommand[0])
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
case '"' : cmdName = T("say"); break;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
case ':' :
|
2007-03-14 22:33:04 +00:00
|
|
|
|
case ';' : cmdName = T("pose"); break;
|
|
|
|
|
|
case '\\': cmdName = T("@emit"); break;
|
|
|
|
|
|
case '#' : cmdName = T("@force"); break;
|
|
|
|
|
|
case '&' : cmdName = T("@set"); break;
|
|
|
|
|
|
case '-' : cmdName = T("@mail"); break;
|
|
|
|
|
|
case '~' : cmdName = T("@mail"); break;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
return tprintf(T("%s_%s"), keylet, cmdName);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
static bool process_hook(dbref executor, CMDENT *cmdp, int key, bool save_flg)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool retval = true;
|
|
|
|
|
|
ATTR *hk_attr = atr_str(hook_name(cmdp->cmdname, key));
|
|
|
|
|
|
if (hk_attr)
|
|
|
|
|
|
{
|
|
|
|
|
|
dbref aowner;
|
|
|
|
|
|
int aflags;
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atext = LBuf_Adopt(atr_get("process_hook.1060", mudconf.hook_obj,
|
|
|
|
|
|
hk_attr->number, &aowner, &aflags));
|
2007-04-10 07:03:12 +00:00
|
|
|
|
if (atext[0] && !(aflags & AF_NOPROG))
|
|
|
|
|
|
{
|
Implement NOEVAL object flag and attribute flag (#11).
Add NOEVAL object flag (FLAG_WORD3) and AF_NOEVAL attribute flag so that
attribute contents can be stored as literal data without evaluation.
When either flag is set, u(), ulocal(), get_eval(), @trigger, did_it()
messages/actions, @function, modSpeech, check_filter, make_prefix,
process_hook, sortby comparison, eval_boolexp, and format attributes
(EXITFORMAT/CONFORMAT/NAMEFORMAT/DESCFORMAT) all return raw text with
no function calls, %-substitutions, or escape processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:04:14 -07:00
|
|
|
|
if ((aflags & AF_NOEVAL) || NoEval(mudconf.hook_obj))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
fix(command): NOEVAL boolean hooks must read their content (#1280)
process_hook() returns a bool: true means "proceed", false means a PERMIT
hook denies or an IGNORE hook swallows the command. Under AF_NOEVAL -- or
a NOEVAL hook_obj -- it discarded the attribute's content outright and
returned true, so a NOEVAL permit hook allowed every command. A
permission control silently disabled, and indistinguishable from having no
hook configured at all.
Call sites confirm the polarity: command.cpp:2163-2170 (and the four
copies at 2350, 2513, 2680, 2775) set hval on `!process_hook(...)`, so
true is "allow". The default `retval = true` is correct for "no hook
attribute" -- it is only the NOEVAL branch that wrongly joins it.
Fixed by deriving the boolean from the unevaluated text. That is the
semantic the rest of the NOEVAL work already uses rather than a preference
of mine: 4cb904fcc introduced AF_NOEVAL as "return raw text with no
function calls" across a list of sites, and eval_boolexp -- the only other
*boolean* consumer in that list -- compares the raw text
(`bCheck = !string_compare(buff, b->sub1)`) instead of short-circuiting.
process_hook was the outlier. A literal "0" or "#-1 ..." hook now blocks
as written, and a literal "1" still permits.
Adds tests/scenario/hook_noeval.py. Not in the smoke corpus: @admin
hook_obj / hook_cmd are CA_GOD for both read and write, and smoke test
cases run as the test object rather than #1. The ufunction_fn.mux
@startup-on-#1 pattern does not carry over, because that publishes a
global any object can then call, whereas this needs the config pointed at
an object and the hook attribute mutated at run time.
The test validates against the unfixed build -- and the first draft did
not. It used `@set obj/attr=NOEVAL`, but the attribute flag is NO_EVAL
(`noeval` is an unrelated command switch), so it set nothing, the hook was
evaluated normally, and all three cases passed against the *broken* build.
Corrected, and it now asserts the flag is really present (flags() must
report 'E') so it cannot silently degrade that way again:
ok 1 - permit hook attribute is actually marked NO_EVAL
not ok 2 - NOEVAL permit hook denying '0' blocks the command
(lastcreate before='#17' after='#20')
ok 3 - NOEVAL permit hook allowing '1' still permits
Case 3 passing in both builds is deliberate: it stops the fix from being
"deny all NOEVAL hooks", which would have been fail-closed but wrong.
Verified: build clean; smoke 1427/1427, 0 crashes, 305/305 dispatched;
scenario 7/7 drivers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 22:18:40 -06:00
|
|
|
|
// NOEVAL means "use this attribute's text literally", not
|
|
|
|
|
|
// "this attribute has no opinion". Returning true here
|
|
|
|
|
|
// discarded the content outright, so a NOEVAL permit or
|
|
|
|
|
|
// ignore hook allowed every command -- a permission control
|
|
|
|
|
|
// silently disabled, and indistinguishable from having no
|
|
|
|
|
|
// hook configured at all (#1280).
|
|
|
|
|
|
//
|
|
|
|
|
|
// Derive the boolean from the unevaluated text instead. That
|
|
|
|
|
|
// is what the rest of the NOEVAL work does: eval_boolexp,
|
|
|
|
|
|
// added in the same commit (4cb904fcc) and the only other
|
|
|
|
|
|
// boolean consumer in its list, compares the raw text rather
|
|
|
|
|
|
// than short-circuiting. A literal "0" or "#-1 ..." hook now
|
|
|
|
|
|
// blocks as written.
|
|
|
|
|
|
//
|
|
|
|
|
|
retval = xlate(atext);
|
2007-04-10 07:03:12 +00:00
|
|
|
|
}
|
Implement NOEVAL object flag and attribute flag (#11).
Add NOEVAL object flag (FLAG_WORD3) and AF_NOEVAL attribute flag so that
attribute contents can be stored as literal data without evaluation.
When either flag is set, u(), ulocal(), get_eval(), @trigger, did_it()
messages/actions, @function, modSpeech, check_filter, make_prefix,
process_hook, sortby comparison, eval_boolexp, and format attributes
(EXITFORMAT/CONFORMAT/NAMEFORMAT/DESCFORMAT) all return raw text with
no function calls, %-substitutions, or escape processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:04:14 -07:00
|
|
|
|
else
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
Implement NOEVAL object flag and attribute flag (#11).
Add NOEVAL object flag (FLAG_WORD3) and AF_NOEVAL attribute flag so that
attribute contents can be stored as literal data without evaluation.
When either flag is set, u(), ulocal(), get_eval(), @trigger, did_it()
messages/actions, @function, modSpeech, check_filter, make_prefix,
process_hook, sortby comparison, eval_boolexp, and format attributes
(EXITFORMAT/CONFORMAT/NAMEFORMAT/DESCFORMAT) all return raw text with
no function calls, %-substitutions, or escape processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:04:14 -07:00
|
|
|
|
reg_ref **preserve = nullptr;
|
|
|
|
|
|
if (save_flg)
|
|
|
|
|
|
{
|
|
|
|
|
|
preserve = PushRegisters(MAX_GLOBAL_REGS);
|
|
|
|
|
|
save_global_regs(preserve);
|
|
|
|
|
|
}
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
UTF8 *bufc;
|
|
|
|
|
|
LBuf buff = LBuf_Src("process_hook");
|
|
|
|
|
|
bufc = buff;
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(atext, LBUF_SIZE-1, buff, &bufc, mudconf.hook_obj, executor,
|
Implement NOEVAL object flag and attribute flag (#11).
Add NOEVAL object flag (FLAG_WORD3) and AF_NOEVAL attribute flag so that
attribute contents can be stored as literal data without evaluation.
When either flag is set, u(), ulocal(), get_eval(), @trigger, did_it()
messages/actions, @function, modSpeech, check_filter, make_prefix,
process_hook, sortby comparison, eval_boolexp, and format attributes
(EXITFORMAT/CONFORMAT/NAMEFORMAT/DESCFORMAT) all return raw text with
no function calls, %-substitutions, or escape processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:04:14 -07:00
|
|
|
|
executor, AttrTrace(aflags, EV_FCHECK|EV_EVAL), nullptr, 0);
|
|
|
|
|
|
*bufc = '\0';
|
|
|
|
|
|
if (save_flg)
|
|
|
|
|
|
{
|
|
|
|
|
|
restore_global_regs(preserve);
|
|
|
|
|
|
PopRegisters(preserve, MAX_GLOBAL_REGS);
|
|
|
|
|
|
}
|
|
|
|
|
|
retval = xlate(buff);
|
2007-04-10 07:03:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return retval;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-03 21:34:30 -07:00
|
|
|
|
void process_hook_args(dbref executor, CMDENT *cmdp, UTF8* arg1, UTF8* arg2, UTF8* args[], int nargs, UTF8* sw)
|
2007-10-26 22:27:32 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
ATTR *hk_attr = atr_str(hook_name(cmdp->cmdname, CEF_HOOK_ARGS));
|
2007-10-26 22:27:32 +00:00
|
|
|
|
if (hk_attr)
|
|
|
|
|
|
{
|
|
|
|
|
|
dbref aowner;
|
|
|
|
|
|
int aflags;
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atext = LBuf_Adopt(atr_get("process_hook_args.1093", mudconf.hook_obj,
|
|
|
|
|
|
hk_attr->number, &aowner, &aflags));
|
2007-10-26 22:27:32 +00:00
|
|
|
|
if (atext[0] && !(aflags & AF_NOPROG))
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
reg_ref **preserve = nullptr;
|
2007-10-26 22:27:32 +00:00
|
|
|
|
preserve = PushRegisters(MAX_GLOBAL_REGS);
|
|
|
|
|
|
save_global_regs(preserve);
|
2018-10-03 17:54:51 +00:00
|
|
|
|
UTF8 *bufc = nullptr;
|
2007-11-03 21:34:30 -07:00
|
|
|
|
UTF8* inargs[5];
|
|
|
|
|
|
if (arg1)
|
|
|
|
|
|
{
|
|
|
|
|
|
inargs[0] = alloc_lbuf("process_hook_args.1103");
|
|
|
|
|
|
mux_strncpy(inargs[0], arg1, LBUF_SIZE-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-03-03 18:39:35 -07:00
|
|
|
|
inargs[0] = const_cast<UTF8 *>(T(""));
|
2007-11-03 21:34:30 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (arg2)
|
|
|
|
|
|
{
|
|
|
|
|
|
inargs[1] = alloc_lbuf("process_hook_args.1110");
|
|
|
|
|
|
mux_strncpy(inargs[1], arg2, LBUF_SIZE-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-03-03 18:39:35 -07:00
|
|
|
|
inargs[1] = const_cast<UTF8 *>(T(""));
|
2007-11-03 21:34:30 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 18:39:35 -07:00
|
|
|
|
inargs[2] = const_cast<UTF8 *>(T(""));
|
2007-11-03 21:34:30 -07:00
|
|
|
|
inargs[4] = sw;
|
|
|
|
|
|
|
|
|
|
|
|
if (arg1)
|
|
|
|
|
|
{
|
|
|
|
|
|
bufc = arg1;
|
2026-03-03 18:39:35 -07:00
|
|
|
|
inargs[3] = const_cast<UTF8 *>(T("0"));
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(atext, LBUF_SIZE-1, arg1, &bufc, mudconf.hook_obj, executor,
|
2007-11-03 21:34:30 -07:00
|
|
|
|
executor, AttrTrace(aflags, EV_FCHECK|EV_EVAL), (const UTF8**)inargs, 5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (arg2)
|
|
|
|
|
|
{
|
|
|
|
|
|
bufc = arg2;
|
2026-03-03 18:39:35 -07:00
|
|
|
|
inargs[3] = const_cast<UTF8 *>(T("1"));
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(atext, LBUF_SIZE-1, arg2, &bufc, mudconf.hook_obj, executor,
|
2007-11-03 21:34:30 -07:00
|
|
|
|
executor, AttrTrace(aflags, EV_FCHECK|EV_EVAL), (const UTF8**)inargs, 5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (nargs)
|
|
|
|
|
|
{
|
|
|
|
|
|
inargs[2] = alloc_lbuf("process_hook_args.1135");
|
|
|
|
|
|
UTF8 qbuff[I64BUF_SIZE];
|
|
|
|
|
|
inargs[3] = qbuff;
|
|
|
|
|
|
for (int i = 0; i < nargs; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
mux_i64toa(i+2, qbuff);
|
|
|
|
|
|
bufc = args[i];
|
|
|
|
|
|
mux_strncpy(inargs[2], args[i], LBUF_SIZE-1);
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(atext, LBUF_SIZE-1, args[i], &bufc, mudconf.hook_obj, executor,
|
2007-11-03 21:34:30 -07:00
|
|
|
|
executor, AttrTrace(aflags, EV_FCHECK|EV_EVAL), (const UTF8**)inargs, 5);
|
|
|
|
|
|
}
|
|
|
|
|
|
free_lbuf(inargs[2]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (arg2) free_lbuf(inargs[1]);
|
|
|
|
|
|
if (arg1) free_lbuf(inargs[0]);
|
2007-10-26 22:27:32 +00:00
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr != bufc)
|
2008-01-22 23:54:34 -08:00
|
|
|
|
{
|
|
|
|
|
|
*bufc = '\0';
|
|
|
|
|
|
}
|
2007-10-26 22:27:32 +00:00
|
|
|
|
restore_global_regs(preserve);
|
|
|
|
|
|
PopRegisters(preserve, MAX_GLOBAL_REGS);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
|
|
* process_cmdent: Perform indicated command with passed args.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
|
static void process_cmdent(CMDENT *cmdp, UTF8 *switchp, dbref executor, dbref caller,
|
|
|
|
|
|
dbref enactor, int eval, bool interactive, UTF8 *arg, UTF8 *unp_command,
|
2007-04-09 23:40:23 +00:00
|
|
|
|
const UTF8 *cargs[], int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
// Perform object type checks.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (Invalid_Objtype(executor))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Command incompatible with executor type."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if we have permission to execute the command.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!check_access(executor, cmdp->perms))
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check global flags
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( !Builder(executor)
|
|
|
|
|
|
&& Protect(CA_GBL_BUILD)
|
|
|
|
|
|
&& !(mudconf.control_flags & CF_BUILD))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Sorry, building is not allowed now."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (Protect(CA_GBL_INTERP) && !(mudconf.control_flags & CF_INTERP))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Sorry, queueing and triggering are not allowed now."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *buf1, *buf2, tchar, *bp, *str, *buff, *j, *new0;
|
|
|
|
|
|
UTF8 *args[MAX_ARG];
|
2007-11-03 21:34:30 -07:00
|
|
|
|
UTF8* sw = switchp;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
int nargs, i, interp, key, xkey, aflags;
|
|
|
|
|
|
dbref aowner;
|
|
|
|
|
|
ADDENT *add;
|
|
|
|
|
|
|
|
|
|
|
|
key = cmdp->extra & ~SW_MULTIPLE;
|
|
|
|
|
|
if (key & SW_GOT_UNIQUE)
|
|
|
|
|
|
{
|
|
|
|
|
|
i = 1;
|
|
|
|
|
|
key = key & ~SW_GOT_UNIQUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check command switches. Note that there may be more than one,
|
|
|
|
|
|
// and that we OR all of them together along with the extra value
|
|
|
|
|
|
// from the command table to produce the key value in the handler
|
|
|
|
|
|
// call.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (switchp && cmdp->switches)
|
|
|
|
|
|
{
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
2026-03-03 18:39:35 -07:00
|
|
|
|
buf1 = reinterpret_cast<UTF8 *>(strchr(reinterpret_cast<char *>(switchp), '/'));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (buf1)
|
|
|
|
|
|
{
|
|
|
|
|
|
*buf1++ = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!search_nametab(executor, cmdp->switches, switchp, &xkey))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (xkey == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Unrecognized switch ‘%s’ for command ‘%s’."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
switchp, cmdp->cmdname));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (xkey == -2)
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!(xkey & SW_MULTIPLE))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i == 1)
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Illegal combination of switches."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
i = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
xkey &= ~SW_MULTIPLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
key |= xkey;
|
|
|
|
|
|
switchp = buf1;
|
|
|
|
|
|
} while (buf1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (switchp && !(cmdp->callseq & CS_ADDED))
|
|
|
|
|
|
{
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
notify(executor, tprintf(M_("Command %s does not take switches."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
cmdp->cmdname));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-03-31 07:04:14 +00:00
|
|
|
|
bool bGoodHookObj = (Good_obj(mudconf.hook_obj) && !Going(mudconf.hook_obj));
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// 'Before' hooks.
|
|
|
|
|
|
// @hook idea from TinyMUSH 3, code from RhostMUSH. Ported by Jake Nelson.
|
|
|
|
|
|
//
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_BEFORE)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_BEFORE, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// We are allowed to run the command. Now, call the handler using
|
|
|
|
|
|
// the appropriate calling sequence and arguments.
|
|
|
|
|
|
//
|
|
|
|
|
|
//if ((cmdp->callseq & CS_INTERP) && (key & SW_NOEVAL))
|
|
|
|
|
|
if (key & SW_NOEVAL)
|
|
|
|
|
|
{
|
|
|
|
|
|
// The user specified /noeval on a @pemit or a @npemit,
|
|
|
|
|
|
// just do EV_STRIP_CURLY and remove the SW_NOEVAL from the
|
|
|
|
|
|
// 'key'.
|
|
|
|
|
|
//
|
2006-12-08 23:38:02 +00:00
|
|
|
|
interp = 0;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
key &= ~SW_NOEVAL;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if ( (cmdp->callseq & CS_INTERP)
|
|
|
|
|
|
|| !( interactive
|
|
|
|
|
|
|| (cmdp->callseq & CS_NOINTERP)))
|
|
|
|
|
|
{
|
|
|
|
|
|
// If the command is interpreted, or we're interactive (and
|
|
|
|
|
|
// the command isn't specified CS_NOINTERP), eval the args.
|
|
|
|
|
|
//
|
|
|
|
|
|
interp = EV_EVAL | EV_STRIP_CURLY;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cmdp->callseq & CS_STRIP)
|
|
|
|
|
|
{
|
|
|
|
|
|
interp = EV_STRIP_CURLY;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cmdp->callseq & CS_STRIP_AROUND)
|
|
|
|
|
|
{
|
|
|
|
|
|
interp = EV_STRIP_AROUND;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
interp = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-04-09 23:40:23 +00:00
|
|
|
|
UTF8 *aargs[NUM_ENV_VARS];
|
2006-09-01 22:59:23 +00:00
|
|
|
|
int nargs2;
|
|
|
|
|
|
switch (cmdp->callseq & CS_NARG_MASK)
|
|
|
|
|
|
{
|
|
|
|
|
|
case CS_NO_ARGS: // <cmd> (no args)
|
2026-03-03 18:39:35 -07:00
|
|
|
|
(*((reinterpret_cast<CMDENT_NO_ARG *>(cmdp))->handler))(executor, caller, enactor, eval, key);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case CS_ONE_ARG: // <cmd> <arg>
|
|
|
|
|
|
|
|
|
|
|
|
// If an unparsed command, just give it to the handler
|
|
|
|
|
|
//
|
|
|
|
|
|
// Interpret if necessary, but not twice for CS_ADDED.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED))
|
|
|
|
|
|
{
|
|
|
|
|
|
buf1 = bp = alloc_lbuf("process_cmdent");
|
|
|
|
|
|
str = arg;
|
2007-10-08 09:42:23 -07:00
|
|
|
|
|
2006-12-27 20:25:19 +00:00
|
|
|
|
// Copy and skip first character for CS_LEADIN, to
|
|
|
|
|
|
// prevent the \ prefix command from escaping part of
|
|
|
|
|
|
// its argument.
|
|
|
|
|
|
//
|
2007-12-09 00:53:07 +00:00
|
|
|
|
if ( (cmdp->callseq & CS_LEADIN)
|
2026-03-03 18:39:35 -07:00
|
|
|
|
&& UTF8_SIZE1 == utf8_FirstByte[static_cast<unsigned char>(str[0])])
|
2006-12-27 20:25:19 +00:00
|
|
|
|
{
|
2007-10-08 09:42:23 -07:00
|
|
|
|
UTF8 ch = *str++;
|
|
|
|
|
|
*bp++ = ch;
|
|
|
|
|
|
|
|
|
|
|
|
if ( mudconf.space_compress
|
2008-01-15 15:18:23 +00:00
|
|
|
|
&& ( ';' == ch
|
|
|
|
|
|
|| ':' == ch)
|
2007-10-08 09:42:23 -07:00
|
|
|
|
&& str[0] == ' ')
|
|
|
|
|
|
{
|
2007-12-09 00:53:07 +00:00
|
|
|
|
// Skip following space to prevent the parser from space
|
|
|
|
|
|
// compressing it.
|
|
|
|
|
|
//
|
2007-10-08 09:42:23 -07:00
|
|
|
|
*bp++ = *str++;
|
|
|
|
|
|
}
|
2006-12-27 20:25:19 +00:00
|
|
|
|
}
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(str, LBUF_SIZE-1, buf1, &bp, executor, caller, enactor,
|
2007-01-28 02:08:08 +00:00
|
|
|
|
eval|interp|EV_FCHECK|EV_TOP, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
buf1 = parse_to(&arg, '\0', interp | EV_TOP);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Call the correct handler.
|
|
|
|
|
|
//
|
2007-09-02 13:48:10 -07:00
|
|
|
|
if (cmdp->callseq & CS_ADDED)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-03-19 08:48:37 -06:00
|
|
|
|
for (auto &addent : *cmdp->addent)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-03-19 08:48:37 -06:00
|
|
|
|
buff = atr_get("process_cmdent.1347", addent.thing, addent.atr, &aowner, &aflags);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2007-03-08 03:53:27 +00:00
|
|
|
|
// Attribute should contain at least two characters and first
|
|
|
|
|
|
// character is '$'.
|
2006-09-01 22:59:23 +00:00
|
|
|
|
//
|
2007-03-08 03:53:27 +00:00
|
|
|
|
if ( AMATCH_CMD != buff[0]
|
|
|
|
|
|
|| '\0' == buff[1])
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(buff);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Skip the '$' character and the next to allow "$::cmd".
|
|
|
|
|
|
//
|
|
|
|
|
|
size_t iBuff;
|
|
|
|
|
|
for (iBuff = 2; '\0' != buff[iBuff]
|
|
|
|
|
|
&& ':' != buff[iBuff]; iBuff++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
2007-03-08 03:53:27 +00:00
|
|
|
|
|
|
|
|
|
|
if ('\0' == buff[iBuff])
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-03-07 03:29:00 +00:00
|
|
|
|
free_lbuf(buff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2007-03-08 03:53:27 +00:00
|
|
|
|
buff[iBuff++] = '\0';
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
if (!(cmdp->callseq & CS_LEADIN))
|
|
|
|
|
|
{
|
2007-03-12 06:58:05 +00:00
|
|
|
|
for (j = unp_command; *j && (*j != ' '); j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-12 06:58:05 +00:00
|
|
|
|
for (j = unp_command; *j; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
new0 = alloc_lbuf("process_cmdent.soft");
|
|
|
|
|
|
bp = new0;
|
|
|
|
|
|
if (!*j)
|
|
|
|
|
|
{
|
|
|
|
|
|
// No args.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!(cmdp->callseq & CS_LEADIN))
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_str(cmdp->cmdname, new0, &bp);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_str(unp_command, new0, &bp);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (switchp)
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_chr('/', new0, &bp);
|
|
|
|
|
|
safe_str(switchp, new0, &bp);
|
|
|
|
|
|
}
|
|
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
j++;
|
|
|
|
|
|
safe_str(cmdp->cmdname, new0, &bp);
|
|
|
|
|
|
if (switchp)
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_chr('/', new0, &bp);
|
|
|
|
|
|
safe_str(switchp, new0, &bp);
|
|
|
|
|
|
}
|
|
|
|
|
|
safe_chr(' ', new0, &bp);
|
|
|
|
|
|
safe_str(j, new0, &bp);
|
|
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( ( (aflags & AF_REGEXP)
|
|
|
|
|
|
&& regexp_match(buff + 1, new0,
|
2025-03-25 13:54:19 -06:00
|
|
|
|
((aflags & AF_CASE) ? PCRE2_CASELESS : 0), aargs,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
NUM_ENV_VARS))
|
|
|
|
|
|
|| ( (aflags & AF_REGEXP) == 0
|
|
|
|
|
|
&& wild(buff + 1, new0, aargs, NUM_ENV_VARS)))
|
|
|
|
|
|
{
|
|
|
|
|
|
CLinearTimeAbsolute lta;
|
2026-03-19 08:48:37 -06:00
|
|
|
|
wait_que(addent.thing, caller, executor,
|
2006-11-05 13:43:16 +00:00
|
|
|
|
AttrTrace(aflags, 0), false, lta, NOTHING, 0,
|
2007-03-08 03:53:27 +00:00
|
|
|
|
buff + iBuff,
|
2007-04-09 23:40:23 +00:00
|
|
|
|
NUM_ENV_VARS, (const UTF8 **)aargs,
|
2006-11-05 13:43:16 +00:00
|
|
|
|
mudstate.global_regs);
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
for (i = 0; i < NUM_ENV_VARS; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (aargs[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(aargs[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
free_lbuf(new0);
|
|
|
|
|
|
free_lbuf(buff);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ((cmdp->flags & CEF_HOOK_ARGS) && bGoodHookObj)
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
process_hook_args(executor, cmdp, buf1, nullptr, nullptr, 0, sw);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
2026-03-03 18:39:35 -07:00
|
|
|
|
(*((reinterpret_cast<CMDENT_ONE_ARG *>(cmdp))->handler))(executor, caller,
|
2007-09-02 13:48:10 -07:00
|
|
|
|
enactor, eval, key, buf1, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Free the buffer if one was allocated.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED))
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(buf1);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case CS_TWO_ARG: // <cmd> <arg1> = <arg2>
|
|
|
|
|
|
|
|
|
|
|
|
// Interpret ARG1
|
|
|
|
|
|
//
|
|
|
|
|
|
buf2 = parse_to(&arg, '=', EV_STRIP_TS);
|
|
|
|
|
|
|
|
|
|
|
|
nargs2 = 0;
|
|
|
|
|
|
if (buf2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
nargs2 = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
nargs2 = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Handle when no '=' was specified.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!arg || (arg && !*arg))
|
|
|
|
|
|
{
|
|
|
|
|
|
arg = &tchar;
|
|
|
|
|
|
*arg = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
buf1 = bp = alloc_lbuf("process_cmdent.2");
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(buf2, LBUF_SIZE-1, buf1, &bp, executor, caller, enactor,
|
2007-01-28 02:08:08 +00:00
|
|
|
|
eval|EV_STRIP_CURLY|EV_FCHECK|EV_EVAL|EV_TOP, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
if (cmdp->callseq & CS_ARGV)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Arg2 is ARGV style. Go get the args.
|
|
|
|
|
|
//
|
2007-04-09 08:36:13 +00:00
|
|
|
|
parse_arglist(executor, caller, enactor, arg,
|
2006-09-06 05:46:01 +00:00
|
|
|
|
eval|interp|EV_STRIP_LS|EV_STRIP_TS, args, MAX_ARG, cargs,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
ncargs, &nargs);
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ((cmdp->flags & CEF_HOOK_ARGS) && bGoodHookObj)
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
process_hook_args(executor, cmdp, buf1, nullptr, args, nargs, sw);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
2026-03-03 18:39:35 -07:00
|
|
|
|
(*((reinterpret_cast<CMDENT_TWO_ARG_ARGV *>(cmdp))->handler))(executor, caller,
|
2007-09-02 22:02:33 -07:00
|
|
|
|
enactor, eval, key, buf1, args, nargs, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Free the argument buffers.
|
|
|
|
|
|
//
|
|
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(args[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Arg2 is normal style. Interpret if needed.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (interp & EV_EVAL)
|
|
|
|
|
|
{
|
|
|
|
|
|
buf2 = bp = alloc_lbuf("process_cmdent.3");
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(arg, LBUF_SIZE-1, buf2, &bp, executor, caller, enactor,
|
2007-01-28 02:08:08 +00:00
|
|
|
|
eval|interp|EV_FCHECK|EV_TOP, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cmdp->callseq & CS_UNPARSE)
|
|
|
|
|
|
{
|
2006-09-06 05:46:01 +00:00
|
|
|
|
buf2 = parse_to(&arg, '\0', eval|interp|EV_TOP|EV_NO_COMPRESS);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2006-09-06 05:46:01 +00:00
|
|
|
|
buf2 = parse_to(&arg, '\0', eval|interp|EV_STRIP_LS|EV_STRIP_TS|EV_TOP);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ((cmdp->flags & CEF_HOOK_ARGS) && bGoodHookObj)
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
process_hook_args(executor, cmdp, nargs2>=1?buf1:nullptr, nargs2>=2?buf2:nullptr, nullptr, 0, sw);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
}
|
2026-03-03 18:39:35 -07:00
|
|
|
|
(*((reinterpret_cast<CMDENT_TWO_ARG *>(cmdp))->handler))(executor, caller,
|
2007-09-02 21:44:11 -07:00
|
|
|
|
enactor, eval, key, nargs2, buf1, buf2, cargs, ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Free the buffer, if needed.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (interp & EV_EVAL)
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(buf2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Free the buffer obtained by evaluating Arg1.
|
|
|
|
|
|
//
|
|
|
|
|
|
free_lbuf(buf1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 'After' hooks.
|
|
|
|
|
|
// @hook idea from TinyMUSH 3, code from RhostMUSH. Ported by Jake Nelson.
|
|
|
|
|
|
//
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFTER)
|
|
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFTER, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-03-14 22:33:04 +00:00
|
|
|
|
static int cmdtest(dbref player, const UTF8 *cmd)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
dbref aowner;
|
2022-03-11 15:10:26 -07:00
|
|
|
|
int aflags;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2022-03-11 15:10:26 -07:00
|
|
|
|
int rval = 0;
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf buff1 = LBuf_Adopt(atr_get("cmdtest.1573", player, A_CMDCHECK, &aowner, &aflags));
|
|
|
|
|
|
if (nullptr == buff1.get()) return 0;
|
2022-03-11 15:10:26 -07:00
|
|
|
|
const UTF8* pt1 = buff1;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
while (pt1 && *pt1)
|
|
|
|
|
|
{
|
2022-03-11 15:10:26 -07:00
|
|
|
|
const auto pt2 = reinterpret_cast<const UTF8*>(strchr(reinterpret_cast<const char*>(pt1), ':'));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!pt2 || (pt2 == pt1))
|
|
|
|
|
|
break;
|
2022-03-11 15:10:26 -07:00
|
|
|
|
if (!strncmp(reinterpret_cast<const char*>(pt2)+1, reinterpret_cast<const char*>(cmd), strlen(reinterpret_cast<const char*>(cmd))))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (*(pt2-1) == '1')
|
|
|
|
|
|
rval = 1;
|
|
|
|
|
|
else
|
|
|
|
|
|
rval = 2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2022-03-11 15:10:26 -07:00
|
|
|
|
pt1 = reinterpret_cast<const UTF8*>(strchr(reinterpret_cast<const char*>(pt2) + 1, ' '));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (pt1 && *pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (mux_isspace(*pt1))
|
|
|
|
|
|
{
|
|
|
|
|
|
pt1++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return rval;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-03-14 22:33:04 +00:00
|
|
|
|
static int zonecmdtest(dbref player, const UTF8 *cmd)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (!Good_obj(player) || God(player))
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
dbref loc = Location(player);
|
|
|
|
|
|
|
|
|
|
|
|
int i_ret = 0;
|
|
|
|
|
|
if (Good_obj(loc))
|
|
|
|
|
|
{
|
|
|
|
|
|
i_ret = cmdtest(loc, cmd);
|
|
|
|
|
|
if (i_ret == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
dbref zone = Zone(loc);
|
|
|
|
|
|
if ( Good_obj(zone)
|
|
|
|
|
|
&& ( isRoom(zone)
|
|
|
|
|
|
|| isThing(zone)))
|
|
|
|
|
|
{
|
|
|
|
|
|
i_ret = cmdtest(zone, cmd);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return i_ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// handle_gmcp: Process an inbound GMCP message.
|
|
|
|
|
|
//
|
|
|
|
|
|
// The payload is "package[.sub] [json]". We fire the A_GMCP attribute
|
|
|
|
|
|
// on the player with %0 = package, %1 = json data.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void handle_gmcp(dbref player, const UTF8 *payload)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Good_obj(player) || !isPlayer(player))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Split payload into package and JSON at the first space.
|
|
|
|
|
|
//
|
|
|
|
|
|
const UTF8 *pSpace = payload;
|
|
|
|
|
|
while (*pSpace && *pSpace != ' ')
|
|
|
|
|
|
{
|
|
|
|
|
|
pSpace++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UTF8 pkg[SBUF_SIZE];
|
|
|
|
|
|
size_t nPkg = static_cast<size_t>(pSpace - payload);
|
|
|
|
|
|
if (nPkg >= SBUF_SIZE) nPkg = SBUF_SIZE - 1;
|
|
|
|
|
|
memcpy(pkg, payload, nPkg);
|
|
|
|
|
|
pkg[nPkg] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
const UTF8 *json = (*pSpace == ' ') ? pSpace + 1 : T("");
|
|
|
|
|
|
|
|
|
|
|
|
dbref aowner;
|
|
|
|
|
|
int aflags;
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf pGmcpAttr = LBuf_Adopt(atr_pget(player, A_GMCP, &aowner, &aflags));
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
if (pGmcpAttr[0] != '\0')
|
|
|
|
|
|
{
|
|
|
|
|
|
const UTF8 *gmcp_args[2];
|
|
|
|
|
|
gmcp_args[0] = pkg;
|
|
|
|
|
|
gmcp_args[1] = json;
|
|
|
|
|
|
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf lbuf = LBuf_Src("handle_gmcp");
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
UTF8 *lp = lbuf;
|
2026-04-05 18:34:51 -06:00
|
|
|
|
mux_exec(pGmcpAttr, strlen(reinterpret_cast<const char *>(pGmcpAttr.get())),
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
lbuf, &lp, player, player, player,
|
|
|
|
|
|
EV_FCHECK | EV_EVAL | EV_TOP,
|
|
|
|
|
|
gmcp_args, 2);
|
|
|
|
|
|
*lp = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// process_command: Execute a command.
|
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *process_command
|
2006-09-01 22:59:23 +00:00
|
|
|
|
(
|
|
|
|
|
|
dbref executor,
|
|
|
|
|
|
dbref caller,
|
|
|
|
|
|
dbref enactor,
|
2006-09-06 05:46:01 +00:00
|
|
|
|
int eval,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
bool interactive,
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *arg_command,
|
2007-04-09 23:40:23 +00:00
|
|
|
|
const UTF8 *args[],
|
2006-09-01 22:59:23 +00:00
|
|
|
|
int nargs
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
Convert all static scratch buffers to thread_local
43 static scratch-buffer arrays across 21 files (5 in mux/src, 38 in
mux/modules/) changed from `static` to `thread_local`. Under the
current single-threaded evaluator this is a zero-behavior-change swap
— `thread_local` storage has the same lifetime and zero-allocation
properties as `static` — but each thread gets its own copy, which
makes these functions safe for a future multi-threaded evaluator
without any locking.
Read-only constant tables (`aRadix64`, `aRadixPenn36`,
`aRadixPenn64`, `Empty`) left as `static` because they are immutable
shared data.
Affected areas:
net.cpp — queue_string co_buf, trimmed_site, dump_users NameField
signals.cpp — signal_desc
stubslave.cpp — Stub_PipePump
attrcache.cpp — sqlite_attr_buf
boolexp.cpp — parsestore
command.cpp — preserve_cmd, SpaceCompressCommand, LowerCaseCommand
comsys.cpp — NewTitle, Buffer, temp
db.cpp — tbuff, Buffer (x2)
flags.cpp — buff
funceval.cpp — textbuff
functions.cpp — TimeBuffer64, TimeBuffer80, Buffer
help.cpp — Line, Buffer
mail.cpp — aFolders, Buffer, res, szFittedMailAliasDesc
match.cpp — buffer
player.cpp — szSalt, buf (x2), buff
plusemail.cpp — buf
predicates.cpp — Buf (x2), pName
session.cpp — szFittedDoing
set.cpp — pRestrictedKeyText
unparse.cpp — buf, boolexp_buf
mail_mod.cpp — result, res, buf
All 21 files verified with g++ -std=c++17 -fsyntax-only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:21:14 -06:00
|
|
|
|
thread_local UTF8 preserve_cmd[LBUF_SIZE];
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *pOriginalCommand = arg_command;
|
Convert all static scratch buffers to thread_local
43 static scratch-buffer arrays across 21 files (5 in mux/src, 38 in
mux/modules/) changed from `static` to `thread_local`. Under the
current single-threaded evaluator this is a zero-behavior-change swap
— `thread_local` storage has the same lifetime and zero-allocation
properties as `static` — but each thread gets its own copy, which
makes these functions safe for a future multi-threaded evaluator
without any locking.
Read-only constant tables (`aRadix64`, `aRadixPenn36`,
`aRadixPenn64`, `Empty`) left as `static` because they are immutable
shared data.
Affected areas:
net.cpp — queue_string co_buf, trimmed_site, dump_users NameField
signals.cpp — signal_desc
stubslave.cpp — Stub_PipePump
attrcache.cpp — sqlite_attr_buf
boolexp.cpp — parsestore
command.cpp — preserve_cmd, SpaceCompressCommand, LowerCaseCommand
comsys.cpp — NewTitle, Buffer, temp
db.cpp — tbuff, Buffer (x2)
flags.cpp — buff
funceval.cpp — textbuff
functions.cpp — TimeBuffer64, TimeBuffer80, Buffer
help.cpp — Line, Buffer
mail.cpp — aFolders, Buffer, res, szFittedMailAliasDesc
match.cpp — buffer
player.cpp — szSalt, buf (x2), buff
plusemail.cpp — buf
predicates.cpp — Buf (x2), pName
session.cpp — szFittedDoing
set.cpp — pRestrictedKeyText
unparse.cpp — buf, boolexp_buf
mail_mod.cpp — result, res, buf
All 21 files verified with g++ -std=c++17 -fsyntax-only.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:21:14 -06:00
|
|
|
|
thread_local UTF8 SpaceCompressCommand[LBUF_SIZE];
|
|
|
|
|
|
thread_local UTF8 LowerCaseCommand[LBUF_SIZE];
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Robustify player.
|
|
|
|
|
|
//
|
2026-03-09 15:12:06 -06:00
|
|
|
|
const UTF8 *cmdsave = g_debug_cmd;
|
|
|
|
|
|
g_debug_cmd = T("< process_command >");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.nStackNest = 0;
|
|
|
|
|
|
mudstate.bStackLimitReached = false;
|
|
|
|
|
|
|
|
|
|
|
|
mux_assert(pOriginalCommand);
|
|
|
|
|
|
|
|
|
|
|
|
if (!Good_obj(executor))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
STARTLOG(LOG_BUGS, T("CMD"), T("PLYR"));
|
2008-12-27 18:37:01 -08:00
|
|
|
|
log_printf(T("Bad player in process_command: %d"), executor);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
ENDLOG;
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return pOriginalCommand;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure player isn't going or halted.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( Going(executor)
|
|
|
|
|
|
|| ( Halted(executor)
|
|
|
|
|
|
&& !( isPlayer(executor)
|
|
|
|
|
|
&& interactive)))
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(Owner(executor),
|
2008-12-27 18:37:01 -08:00
|
|
|
|
tprintf(T("Attempt to execute command by halted object #%d"), executor));
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return pOriginalCommand;
|
|
|
|
|
|
}
|
Feature: Add MSSP, GMCP, @protect, and benchmark()
Four new features identified from the TinyMUSH/PennMUSH/RhostMUSH survey:
MSSP (MUD Server Status Protocol, telnet option 70):
- Server sends structured key-value data (NAME, PLAYERS, UPTIME, PORT,
CODEBASE, FAMILY) to MU* directory crawlers on IAC DO MSSP
- Stateless response via send_mssp() in telnet.cpp using g_dc config basket
- start_time_utc added to DRIVER_CONFIG for uptime calculation
GMCP (Generic MUD Communication Protocol, telnet option 201):
- Protocol negotiation: server offers WILL GMCP, tracks gmcp_enabled per DESC
- Inbound: GMCP subneg queued as synthetic "\x01GMCP" command, dispatched
to handle_gmcp() which fires A_GMCP attribute with %0=package %1=json
- Outbound: gmcp(<player>, <package>, <json>) softcode function sends
GMCP frames to all GMCP-enabled descriptors via SendGmcp COM method
- Full COM architecture: mux_IConnectionManager::SendGmcp in driver,
send_gmcp() bridge in engine, CConnectionManager impl in modules.cpp
@protect (player name reservation):
- @protect[/add] <name>, @protect/del <name>, @protect/list [<player>]
- A_PROTECTNAME attribute (234) stores space-separated protected names
- protectname_check() hooked into create_player() and do_name()
- max_name_protect config param (default 5)
benchmark(<expression>, <iterations>):
- FN_NOEVAL, CA_PUBLIC, 10000 iteration cap
- Uses clock_gettime(CLOCK_MONOTONIC) / QueryPerformanceCounter
- Returns elapsed seconds as floating point
Also fixes: add unicode_tables.c to libmux.so LIBMUX_C_SRC (resolves
pre-existing tr_tolower_sbt etc. link errors).
505/505 smoke tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:08:55 -06:00
|
|
|
|
// Intercept internal GMCP messages from the telnet layer.
|
|
|
|
|
|
// Format: "\x01GMCP package [json]"
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( '\x01' == pOriginalCommand[0]
|
|
|
|
|
|
&& memcmp(pOriginalCommand + 1, "GMCP ", 5) == 0
|
|
|
|
|
|
&& interactive)
|
|
|
|
|
|
{
|
|
|
|
|
|
handle_gmcp(executor, pOriginalCommand + 6);
|
|
|
|
|
|
g_debug_cmd = cmdsave;
|
|
|
|
|
|
return pOriginalCommand;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( Suspect(executor)
|
|
|
|
|
|
&& (mudconf.log_options & LOG_SUSPECTCMDS))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
STARTLOG(LOG_SUSPECTCMDS, T("CMD"), T("SUSP"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_name_and_loc(executor);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
log_text(T(" entered: "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_text(pOriginalCommand);
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
STARTLOG(LOG_ALLCOMMANDS, T("CMD"), T("ALL"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_name_and_loc(executor);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
log_text(T(" entered: "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_text(pOriginalCommand);
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Reset recursion limits.
|
|
|
|
|
|
//
|
2026-07-24 08:26:59 -06:00
|
|
|
|
// Note: include_nest_lev is intentionally not reset here — it tracks
|
|
|
|
|
|
// recursive process_command_list_inline depth across nested
|
|
|
|
|
|
// @include/@dolist/now invocations and is balanced by that path.
|
|
|
|
|
|
//
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.func_nest_lev = 0;
|
|
|
|
|
|
mudstate.func_invk_ctr = 0;
|
|
|
|
|
|
mudstate.ntfy_nest_lev = 0;
|
|
|
|
|
|
mudstate.lock_nest_lev = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (Verbose(executor))
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(Owner(executor), tprintf(T("%s] %s"), Name(executor), pOriginalCommand));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Eat leading whitespace, and space-compress if configured.
|
|
|
|
|
|
//
|
|
|
|
|
|
while (mux_isspace(*pOriginalCommand))
|
|
|
|
|
|
{
|
|
|
|
|
|
pOriginalCommand++;
|
|
|
|
|
|
}
|
2009-11-12 21:42:05 -08:00
|
|
|
|
mux_strncpy(preserve_cmd, pOriginalCommand, sizeof(preserve_cmd)-1);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = pOriginalCommand;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.curr_cmd = preserve_cmd;
|
|
|
|
|
|
|
2007-03-31 07:04:14 +00:00
|
|
|
|
UTF8 *pCommand;
|
|
|
|
|
|
UTF8 *p, *q, *arg, *bp;
|
|
|
|
|
|
int aflags;
|
|
|
|
|
|
dbref exit, aowner;
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.space_compress)
|
|
|
|
|
|
{
|
2026-07-31 06:26:08 -06:00
|
|
|
|
// Compress out the spaces and use that as the command.
|
|
|
|
|
|
// Leave room for the trailing NUL: writing up to LBUF_SIZE
|
|
|
|
|
|
// then `*q = 0` was one past the end for a full LBUF of
|
|
|
|
|
|
// non-space (WebSocket can deliver LBUF-sized text; #1819).
|
2006-09-01 22:59:23 +00:00
|
|
|
|
//
|
|
|
|
|
|
pCommand = SpaceCompressCommand;
|
|
|
|
|
|
|
|
|
|
|
|
p = pOriginalCommand;
|
|
|
|
|
|
q = SpaceCompressCommand;
|
2026-07-31 06:26:08 -06:00
|
|
|
|
UTF8 *const qend = SpaceCompressCommand + (LBUF_SIZE - 1);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
while ( *p
|
2026-07-31 06:26:08 -06:00
|
|
|
|
&& q < qend)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
while ( *p
|
|
|
|
|
|
&& !mux_isspace(*p)
|
2026-07-31 06:26:08 -06:00
|
|
|
|
&& q < qend)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
*q++ = *p++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (mux_isspace(*p))
|
|
|
|
|
|
{
|
|
|
|
|
|
p++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( *p
|
2026-07-31 06:26:08 -06:00
|
|
|
|
&& q < qend)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
*q++ = ' ';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
*q = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Don't compress the spaces. Use the original command
|
|
|
|
|
|
// (without leading spaces) as the command to use.
|
|
|
|
|
|
//
|
|
|
|
|
|
pCommand = pOriginalCommand;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now comes the fun stuff. First check for single-letter leadins.
|
|
|
|
|
|
// We check these before checking HOME because they are among the
|
|
|
|
|
|
// most frequently executed commands, and they can never be the
|
|
|
|
|
|
// HOME command.
|
|
|
|
|
|
//
|
|
|
|
|
|
int cval = 0;
|
|
|
|
|
|
int hval = 0;
|
2007-03-31 07:04:14 +00:00
|
|
|
|
bool bGoodHookObj = (Good_obj(mudconf.hook_obj) && !Going(mudconf.hook_obj));
|
2007-12-09 00:53:07 +00:00
|
|
|
|
|
|
|
|
|
|
size_t nPrefix = 0;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
CMDENT *cmdp = nullptr;
|
2007-12-09 00:53:07 +00:00
|
|
|
|
if (is_prefix_cmd(pCommand, &nPrefix, &cmdp))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore
|
|
|
|
|
|
//
|
2007-12-09 00:53:07 +00:00
|
|
|
|
UTF8 check2[UTF8_SIZE4+1];
|
|
|
|
|
|
memcpy(check2, pCommand, nPrefix);
|
|
|
|
|
|
check2[nPrefix] = '\0';
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = cmdtest(executor, check2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = cmdtest(Owner(executor), check2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = zonecmdtest(executor, check2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
hval = 0;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & (CEF_HOOK_IGNORE|CEF_HOOK_PERMIT))
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_IGNORE)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_IGNORE, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 2;
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
else if ( (cmdp->flags & CEF_HOOK_PERMIT)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_PERMIT, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 1;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( cval != 2
|
|
|
|
|
|
&& hval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( cval == 1
|
|
|
|
|
|
|| hval == 1)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFAIL)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFAIL, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
2018-10-03 17:54:51 +00:00
|
|
|
|
process_cmdent(cmdp, nullptr, executor, caller, enactor,
|
2006-09-06 05:46:01 +00:00
|
|
|
|
eval, interactive, pCommand, pCommand, args, nargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudstate.bStackLimitReached)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
STARTLOG(LOG_ALWAYS, T("CMD"), T("SPAM"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_name_and_loc(executor);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
log_text(T(" entered: "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_text(pOriginalCommand);
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
}
|
|
|
|
|
|
mudstate.bStackLimitReached = false;
|
|
|
|
|
|
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2026-03-03 21:54:49 -07:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Talk mode: if the player has TALKMODE set and this is interactive
|
|
|
|
|
|
// input, treat unprefix'd input as 'say'. A leading '.' escapes
|
|
|
|
|
|
// to normal command processing.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( interactive
|
|
|
|
|
|
&& isPlayer(executor)
|
|
|
|
|
|
&& TalkMode(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ('.' == pCommand[0])
|
|
|
|
|
|
{
|
|
|
|
|
|
// Strip the dot and fall through to normal command
|
|
|
|
|
|
// processing.
|
|
|
|
|
|
//
|
|
|
|
|
|
pCommand++;
|
|
|
|
|
|
|
|
|
|
|
|
// If the dot was the only character, ignore the empty
|
|
|
|
|
|
// command.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ('\0' == *pCommand)
|
|
|
|
|
|
{
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2026-03-03 21:54:49 -07:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Route to say.
|
|
|
|
|
|
//
|
|
|
|
|
|
do_say(executor, caller, enactor, eval, SAY_SAY, pCommand,
|
|
|
|
|
|
args, nargs);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 12:25:54 -06:00
|
|
|
|
if (!Slave(executor))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-03-08 12:25:54 -06:00
|
|
|
|
bool bHandled = false;
|
|
|
|
|
|
if (nullptr != mudstate.pIComsysControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
mudstate.pIComsysControl->ProcessCommand(executor, pCommand,
|
|
|
|
|
|
&bHandled);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
bHandled = !do_comsystem(executor, pCommand);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (bHandled)
|
|
|
|
|
|
{
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2026-03-08 12:25:54 -06:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for the HOME command.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( Has_location(executor)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
&& string_compare(pCommand, T("home")) == 0)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(executor, T("home"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(Owner(executor), T("home"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = zonecmdtest(executor, T("home"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!check_access(executor, mudconf.restrict_home))
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (cval == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( ( Fixed(executor)
|
|
|
|
|
|
|| Fixed(Owner(executor)))
|
|
|
|
|
|
&& !WizRoy(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, mudconf.fixed_home_msg);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
2026-03-03 18:39:35 -07:00
|
|
|
|
do_move(executor, caller, enactor, eval, 0, const_cast<UTF8 *>(T("home")), nullptr, 0);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Only check for exits if we may use the goto command.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (check_access(executor, goto_cmdp->perms))
|
|
|
|
|
|
{
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore
|
|
|
|
|
|
// Master room exits are not affected.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(executor, T("goto"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(Owner(executor), T("goto"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = zonecmdtest(executor, T("goto"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
hval = 0;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (goto_cmdp->flags & (CEF_HOOK_IGNORE|CEF_HOOK_PERMIT))
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (goto_cmdp->flags & CEF_HOOK_IGNORE)
|
|
|
|
|
|
&& !process_hook(executor, goto_cmdp, CEF_HOOK_IGNORE, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 2;
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
else if ( (goto_cmdp->flags & CEF_HOOK_PERMIT)
|
|
|
|
|
|
&& !process_hook(executor, goto_cmdp, CEF_HOOK_PERMIT, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 1;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( cval != 2
|
|
|
|
|
|
&& hval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check for an exit name.
|
|
|
|
|
|
//
|
|
|
|
|
|
init_match_check_keys(executor, pCommand, TYPE_EXIT);
|
|
|
|
|
|
match_exit_with_parents();
|
|
|
|
|
|
exit = last_match_result();
|
2007-03-31 07:04:14 +00:00
|
|
|
|
bool bMaster = (NOTHING == exit);
|
|
|
|
|
|
|
|
|
|
|
|
if (bMaster)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check for an exit in the master room.
|
|
|
|
|
|
//
|
|
|
|
|
|
init_match_check_keys(executor, pCommand, TYPE_EXIT);
|
|
|
|
|
|
match_master_exit();
|
|
|
|
|
|
exit = last_match_result();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (exit != NOTHING)
|
|
|
|
|
|
{
|
2007-03-31 07:04:14 +00:00
|
|
|
|
if ( 1 == cval
|
|
|
|
|
|
|| 1 == hval)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (goto_cmdp->flags & CEF_HOOK_AFAIL)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, goto_cmdp, CEF_HOOK_AFAIL, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (goto_cmdp->flags & CEF_HOOK_BEFORE)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, goto_cmdp, CEF_HOOK_BEFORE, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!bMaster)
|
|
|
|
|
|
{
|
2026-07-26 21:52:48 -06:00
|
|
|
|
move_exit(executor, exit, false, T("You can’t go that way."), 0);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
move_exit(executor, exit, true, nullptr, 0);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (goto_cmdp->flags & CEF_HOOK_AFTER)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, goto_cmdp, CEF_HOOK_AFTER, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Set up a lowercase command and an arg pointer for the hashed
|
|
|
|
|
|
// command check. Since some types of argument processing destroy
|
|
|
|
|
|
// the arguments, make a copy so that we keep the original command
|
|
|
|
|
|
// line intact. Store the edible copy in LowerCaseCommand after
|
|
|
|
|
|
// the lower-cased command.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
// Make lowercase command (Unicode-aware).
|
2006-09-01 22:59:23 +00:00
|
|
|
|
//
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
size_t iPos = 0;
|
2007-01-23 04:18:52 +00:00
|
|
|
|
while ( pCommand[iPos]
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
&& !mux_isspace(pCommand[iPos]))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-01-23 04:18:52 +00:00
|
|
|
|
iPos++;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2026-03-23 21:52:18 -06:00
|
|
|
|
LBuf TempCmd = LBuf_Src("process_command");
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
size_t nCopy = iPos;
|
|
|
|
|
|
if (nCopy >= LBUF_SIZE)
|
|
|
|
|
|
{
|
|
|
|
|
|
nCopy = LBUF_SIZE - 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
memcpy(TempCmd, pCommand, nCopy);
|
|
|
|
|
|
TempCmd[nCopy] = '\0';
|
|
|
|
|
|
size_t nLowerCaseCommand;
|
|
|
|
|
|
UTF8 *pLower = mux_strlwr(TempCmd, nLowerCaseCommand);
|
|
|
|
|
|
if (nLowerCaseCommand >= LBUF_SIZE)
|
|
|
|
|
|
{
|
|
|
|
|
|
nLowerCaseCommand = LBUF_SIZE - 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
memcpy(LowerCaseCommand, pLower, nLowerCaseCommand);
|
2007-01-23 04:18:52 +00:00
|
|
|
|
LowerCaseCommand[nLowerCaseCommand] = '\0';
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Skip spaces before arg
|
|
|
|
|
|
//
|
2007-01-23 04:18:52 +00:00
|
|
|
|
while (mux_isspace(pCommand[iPos]))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-01-23 04:18:52 +00:00
|
|
|
|
iPos++;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Remember where arg starts
|
|
|
|
|
|
//
|
2007-01-23 04:18:52 +00:00
|
|
|
|
arg = pCommand + iPos;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// Strip off any command switches and save them.
|
|
|
|
|
|
//
|
2026-03-03 18:39:35 -07:00
|
|
|
|
UTF8 *pSlash = reinterpret_cast<UTF8 *>(strchr(reinterpret_cast<char *>(LowerCaseCommand), '/'));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (pSlash)
|
|
|
|
|
|
{
|
|
|
|
|
|
nLowerCaseCommand = pSlash - LowerCaseCommand;
|
|
|
|
|
|
*pSlash++ = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for a builtin command (or an alias of a builtin command)
|
|
|
|
|
|
//
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
auto it_cmd = mudstate.command_htab.find(std::vector<UTF8>(LowerCaseCommand, LowerCaseCommand + nLowerCaseCommand));
|
|
|
|
|
|
cmdp = (it_cmd != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_cmd->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
/* If command is checked to ignore NONMATCHING switches, fall through */
|
|
|
|
|
|
if (cmdp)
|
|
|
|
|
|
{
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore
|
|
|
|
|
|
//
|
|
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = cmdtest(executor, cmdp->cmdname);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = cmdtest(Owner(executor), cmdp->cmdname);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = zonecmdtest(executor, cmdp->cmdname);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
hval = 0;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & (CEF_HOOK_IGNORE|CEF_HOOK_PERMIT))
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_IGNORE)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_IGNORE, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 2;
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
else if ( (cmdp->flags & CEF_HOOK_PERMIT)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_PERMIT, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 1;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the command contains a switch, but the command doesn't support
|
|
|
|
|
|
// any switches or the command contains one that isn't supported,
|
2012-03-15 08:20:40 -07:00
|
|
|
|
// CEF_HOOK_IGSWITCH will allow us to treat the entire command as if it
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// weren't a built-in command.
|
|
|
|
|
|
//
|
|
|
|
|
|
int flagvalue;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_IGSWITCH)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
&& pSlash)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmdp->switches)
|
|
|
|
|
|
{
|
|
|
|
|
|
search_nametab(executor, cmdp->switches, pSlash, &flagvalue);
|
|
|
|
|
|
if (flagvalue & SW_MULTIPLE)
|
|
|
|
|
|
{
|
|
|
|
|
|
// All the switches given a command shouldn't exceed 200 chars together
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 switch_buff[200];
|
|
|
|
|
|
UTF8 *switch_ptr;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mux_strncpy(switch_buff, pSlash, sizeof(switch_buff)-1);
|
2022-03-11 12:36:37 -07:00
|
|
|
|
string_token st(switch_buff, T("/"));
|
|
|
|
|
|
switch_ptr = st.parse();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
while ( switch_ptr
|
|
|
|
|
|
&& *switch_ptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
search_nametab(executor, cmdp->switches, switch_ptr, &flagvalue);
|
|
|
|
|
|
if (flagvalue == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2022-03-11 12:36:37 -07:00
|
|
|
|
switch_ptr = st.parse();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (flagvalue == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Switch exists but no switches allowed for command.
|
|
|
|
|
|
//
|
|
|
|
|
|
cval = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( cval != 2
|
|
|
|
|
|
&& hval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( cval == 1
|
|
|
|
|
|
|| hval == 1)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFAIL)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFAIL, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( mudconf.space_compress
|
|
|
|
|
|
&& (cmdp->callseq & CS_NOSQUISH))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We handle this specially -- there is no space compression
|
|
|
|
|
|
// involved, so we must go back to the original command.
|
|
|
|
|
|
// We skip over the command and a single space to position
|
|
|
|
|
|
// arg at the arguments.
|
|
|
|
|
|
//
|
|
|
|
|
|
arg = pCommand = pOriginalCommand;
|
|
|
|
|
|
while (*arg && !mux_isspace(*arg))
|
|
|
|
|
|
{
|
|
|
|
|
|
arg++;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We stopped on the space, advance to next.
|
|
|
|
|
|
//
|
|
|
|
|
|
arg++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2006-09-06 05:46:01 +00:00
|
|
|
|
process_cmdent(cmdp, pSlash, executor, caller, enactor, eval,
|
|
|
|
|
|
interactive, arg, pCommand, args, nargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudstate.bStackLimitReached)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
STARTLOG(LOG_ALWAYS, T("CMD"), T("SPAM"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_name_and_loc(executor);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
log_text(T(" entered: "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_text(pOriginalCommand);
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
}
|
|
|
|
|
|
mudstate.bStackLimitReached = false;
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for enter and leave aliases, user-defined commands on the
|
|
|
|
|
|
// player, other objects where the player is, on objects in the
|
|
|
|
|
|
// player's inventory, and on the room that holds the player. We
|
|
|
|
|
|
// evaluate the command line here to allow chains of $-commands
|
|
|
|
|
|
// to work.
|
|
|
|
|
|
//
|
|
|
|
|
|
bp = LowerCaseCommand;
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(pCommand, LBUF_SIZE-1, LowerCaseCommand, &bp, executor, caller, enactor,
|
2007-01-28 02:08:08 +00:00
|
|
|
|
eval|EV_EVAL|EV_FCHECK|EV_STRIP_CURLY|EV_TOP, args, nargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
bool succ = false;
|
|
|
|
|
|
|
|
|
|
|
|
// Idea for enter/leave aliases from R'nice@TinyTIM
|
|
|
|
|
|
//
|
|
|
|
|
|
if (Has_location(executor) && Good_obj(Location(executor)))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check for a leave alias.
|
|
|
|
|
|
//
|
|
|
|
|
|
p = atr_pget(Location(executor), A_LALIAS, &aowner, &aflags);
|
|
|
|
|
|
if (*p)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (matches_exit_from_list(LowerCaseCommand, p))
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(p);
|
|
|
|
|
|
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore
|
|
|
|
|
|
//
|
|
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(executor, T("leave"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(Owner(executor), T("leave"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = zonecmdtest(executor, T("leave"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
const UTF8 *tmp_leave = reinterpret_cast<const UTF8*>("leave");
|
|
|
|
|
|
auto it_leave = mudstate.command_htab.find(std::vector<UTF8>(tmp_leave, tmp_leave + 5));
|
|
|
|
|
|
cmdp = (it_leave != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_leave->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
hval = 0;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & (CEF_HOOK_IGNORE|CEF_HOOK_PERMIT))
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_IGNORE)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_IGNORE, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 2;
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
else if ( (cmdp->flags & CEF_HOOK_PERMIT)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_PERMIT, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 1;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( cval != 2
|
|
|
|
|
|
&& hval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( cval == 1
|
|
|
|
|
|
|| hval == 1)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFAIL)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFAIL, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
2007-03-31 07:04:14 +00:00
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_BEFORE)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_BEFORE, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-09-02 11:03:02 -07:00
|
|
|
|
do_leave(executor, caller, executor, 0, 0);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFTER)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFTER, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
free_lbuf(p);
|
|
|
|
|
|
|
|
|
|
|
|
DOLIST(exit, Contents(Location(executor)))
|
|
|
|
|
|
{
|
|
|
|
|
|
p = atr_pget(exit, A_EALIAS, &aowner, &aflags);
|
|
|
|
|
|
if (*p)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (matches_exit_from_list(LowerCaseCommand, p))
|
|
|
|
|
|
{
|
|
|
|
|
|
free_lbuf(p);
|
|
|
|
|
|
|
|
|
|
|
|
// Check for enter aliases.
|
|
|
|
|
|
//
|
|
|
|
|
|
// CmdCheck tests for @icmd. higcheck tests for i/p hooks.
|
|
|
|
|
|
// Both from RhostMUSH.
|
|
|
|
|
|
// cval/hval values: 0 normal, 1 disable, 2 ignore
|
|
|
|
|
|
//
|
|
|
|
|
|
if (CmdCheck(executor))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(executor, T("enter"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else if (CmdCheck(Owner(executor)))
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = cmdtest(Owner(executor), T("enter"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cval = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cval == 0)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cval = zonecmdtest(executor, T("enter"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
const UTF8 *tmp_enter = reinterpret_cast<const UTF8*>("enter");
|
|
|
|
|
|
auto it_enter = mudstate.command_htab.find(std::vector<UTF8>(tmp_enter, tmp_enter + 5));
|
|
|
|
|
|
cmdp = (it_enter != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_enter->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2007-04-10 07:03:12 +00:00
|
|
|
|
hval = 0;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & (CEF_HOOK_IGNORE|CEF_HOOK_PERMIT))
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_IGNORE)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_IGNORE, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 2;
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
else if ( (cmdp->flags & CEF_HOOK_PERMIT)
|
|
|
|
|
|
&& !process_hook(executor, cmdp, CEF_HOOK_PERMIT, true))
|
2007-04-10 07:03:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
hval = 1;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( cval != 2
|
|
|
|
|
|
&& hval != 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( cval == 1
|
|
|
|
|
|
|| hval == 1)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFAIL)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFAIL, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
2007-03-31 07:04:14 +00:00
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_BEFORE)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_BEFORE, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
do_enter_internal(executor, exit, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (cmdp->flags & CEF_HOOK_AFTER)
|
2007-03-31 07:04:14 +00:00
|
|
|
|
&& bGoodHookObj)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
process_hook(executor, cmdp, CEF_HOOK_AFTER, false);
|
2007-03-31 07:04:14 +00:00
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cval == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
notify_quiet(executor, NOPERM_MESSAGE);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
free_lbuf(p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for $-command matches on me.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (mudconf.match_mine && !No_Command(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( ( !isPlayer(executor)
|
|
|
|
|
|
|| mudconf.match_mine_pl)
|
|
|
|
|
|
&& atr_match(executor, executor, AMATCH_CMD, LowerCaseCommand, preserve_cmd, true))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for $-command matches on nearby things and on my room.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (Has_location(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= list_check(Contents(Location(executor)), executor, AMATCH_CMD, LowerCaseCommand, preserve_cmd, true);
|
|
|
|
|
|
|
|
|
|
|
|
if (!No_Command(Location(executor)))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= atr_match(Location(executor), executor, AMATCH_CMD, LowerCaseCommand, preserve_cmd, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check for $-command matches in my inventory.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (Has_contents(executor))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= list_check(Contents(executor), executor, AMATCH_CMD, LowerCaseCommand, preserve_cmd, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( !succ
|
|
|
|
|
|
&& mudconf.have_zones)
|
|
|
|
|
|
{
|
|
|
|
|
|
// now do check on zones.
|
|
|
|
|
|
//
|
|
|
|
|
|
dbref zone = Zone(executor);
|
|
|
|
|
|
dbref loc = Location(executor);
|
|
|
|
|
|
dbref zone_loc = NOTHING;
|
|
|
|
|
|
if ( Good_obj(loc)
|
|
|
|
|
|
&& Good_obj(zone_loc = Zone(loc)))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isRoom(zone_loc))
|
|
|
|
|
|
{
|
|
|
|
|
|
// zone of player's location is a parent room.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (loc != zone)
|
|
|
|
|
|
{
|
|
|
|
|
|
// check parent room exits.
|
|
|
|
|
|
//
|
|
|
|
|
|
init_match_check_keys(executor, pCommand, TYPE_EXIT);
|
|
|
|
|
|
match_zone_exit();
|
|
|
|
|
|
exit = last_match_result();
|
|
|
|
|
|
if (exit != NOTHING)
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
move_exit(executor, exit, true, nullptr, 0);
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
succ |= list_check(Contents(zone_loc), executor,
|
|
|
|
|
|
AMATCH_CMD, LowerCaseCommand, preserve_cmd,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
// end of parent room checks.
|
|
|
|
|
|
//
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// try matching commands on area zone object.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!No_Command(zone_loc))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= atr_match(zone_loc, executor, AMATCH_CMD,
|
|
|
|
|
|
LowerCaseCommand, preserve_cmd, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// End of matching on zone of player's location.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
// if nothing matched with parent room/zone object, try matching
|
|
|
|
|
|
// zone commands on the player's personal zone.
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( !succ
|
|
|
|
|
|
&& Good_obj(zone)
|
|
|
|
|
|
&& !No_Command(zone)
|
|
|
|
|
|
&& zone_loc != zone)
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= atr_match(zone, executor, AMATCH_CMD, LowerCaseCommand, preserve_cmd, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we didn't find anything, try in the master room.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!succ)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( Good_obj(mudconf.master_room)
|
|
|
|
|
|
&& Has_contents(mudconf.master_room))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= list_check(Contents(mudconf.master_room), executor,
|
|
|
|
|
|
AMATCH_CMD, LowerCaseCommand, preserve_cmd, false);
|
|
|
|
|
|
|
|
|
|
|
|
if (!No_Command(mudconf.master_room))
|
|
|
|
|
|
{
|
|
|
|
|
|
succ |= atr_match(mudconf.master_room, executor, AMATCH_CMD,
|
|
|
|
|
|
LowerCaseCommand, preserve_cmd, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we still didn't find anything, tell how to get help.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (!succ)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( Good_obj(mudconf.global_error_obj)
|
|
|
|
|
|
&& !Going(mudconf.global_error_obj))
|
|
|
|
|
|
{
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf errtext = LBuf_Adopt(atr_get("process_command.2491", mudconf.global_error_obj, A_VA, &aowner, &aflags));
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf errbuff = LBuf_Src("process_command.error_msg");
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *errbufc = errbuff;
|
2026-03-07 19:57:24 -07:00
|
|
|
|
mux_exec(errtext, LBUF_SIZE-1, errbuff, &errbufc, mudconf.global_error_obj, caller, enactor,
|
2007-01-28 02:08:08 +00:00
|
|
|
|
AttrTrace(aflags, EV_EVAL|EV_FCHECK|EV_STRIP_CURLY|EV_TOP),
|
2007-04-09 23:40:23 +00:00
|
|
|
|
(const UTF8 **)&pCommand, 1);
|
2007-04-14 04:31:39 +00:00
|
|
|
|
*errbufc = '\0';
|
2006-09-01 22:59:23 +00:00
|
|
|
|
notify(executor, errbuff);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// We use LowerCaseCommand for another purpose.
|
|
|
|
|
|
//
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Huh? (Type “help” for help.)"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
STARTLOG(LOG_BADCOMMANDS, "CMD", "BAD");
|
|
|
|
|
|
log_name_and_loc(executor);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
log_text(T(" entered: "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
log_text(pCommand);
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-09 15:12:06 -06:00
|
|
|
|
g_debug_cmd = cmdsave;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return preserve_cmd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_cmdtable: List internal commands.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void list_cmdtable(dbref player)
|
|
|
|
|
|
{
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf buf = LBuf_Src("list_cmdtable");
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *bp = buf;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
ITL itl;
|
|
|
|
|
|
ItemToList_Init(&itl, buf, &bp);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
ItemToList_AddString(&itl, T("Commands:"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for ( CMDENT_NO_ARG *cmdp0a = command_table_no_arg;
|
|
|
|
|
|
cmdp0a->cmdname;
|
|
|
|
|
|
cmdp0a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp0a->perms)
|
|
|
|
|
|
&& !(cmdp0a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
ItemToList_AddString(&itl, cmdp0a->cmdname);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
2007-09-03 17:57:33 -07:00
|
|
|
|
for ( CMDENT_ONE_ARG *cmdp1a = command_table_one_arg;
|
2007-04-09 05:34:50 +00:00
|
|
|
|
cmdp1a->cmdname;
|
|
|
|
|
|
cmdp1a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp1a->perms)
|
|
|
|
|
|
&& !(cmdp1a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
ItemToList_AddString(&itl, cmdp1a->cmdname);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG *cmdp2a = command_table_two_arg;
|
|
|
|
|
|
cmdp2a->cmdname;
|
|
|
|
|
|
cmdp2a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp2a->perms)
|
|
|
|
|
|
&& !(cmdp2a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
ItemToList_AddString(&itl, cmdp2a->cmdname);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG_ARGV *cmdp2av = command_table_two_arg_argv;
|
|
|
|
|
|
cmdp2av->cmdname;
|
|
|
|
|
|
cmdp2av++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp2av->perms)
|
|
|
|
|
|
&& !(cmdp2av->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
ItemToList_AddString(&itl, cmdp2av->cmdname);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// Players get the list of logged-out cmds too
|
|
|
|
|
|
//
|
|
|
|
|
|
if (isPlayer(player))
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for (NAMETAB *nt = logout_cmdtable; nt->name; nt++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( God(player)
|
|
|
|
|
|
|| check_access(player, nt->perm))
|
|
|
|
|
|
{
|
|
|
|
|
|
ItemToList_AddString(&itl, nt->name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
ItemToList_Final(&itl);
|
|
|
|
|
|
|
|
|
|
|
|
notify(player, buf);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_attrtable: List available attributes.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void list_attrtable(dbref player)
|
|
|
|
|
|
{
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf buf = LBuf_Src("list_attrtable");
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *bp = buf;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
ITL itl;
|
|
|
|
|
|
ItemToList_Init(&itl, buf, &bp);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
ItemToList_AddString(&itl, T("Attributes:"));
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for (ATTR *ap = AttrTable; ap->name; ap++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (See_attr(player, player, ap))
|
|
|
|
|
|
{
|
2007-03-14 19:32:44 +00:00
|
|
|
|
ItemToList_AddString(&itl, ap->name);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ItemToList_Final(&itl);
|
|
|
|
|
|
*bp = '\0';
|
|
|
|
|
|
raw_notify(player, buf);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_cmdaccess: List access commands.
|
|
|
|
|
|
//
|
|
|
|
|
|
NAMETAB access_nametab[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("builder"), 6, CA_WIZARD, CA_BUILDER},
|
|
|
|
|
|
{T("dark"), 4, CA_GOD, CF_DARK},
|
|
|
|
|
|
{T("disabled"), 4, CA_GOD, CA_DISABLED},
|
|
|
|
|
|
{T("global_build"), 8, CA_PUBLIC, CA_GBL_BUILD},
|
|
|
|
|
|
{T("global_interp"), 8, CA_PUBLIC, CA_GBL_INTERP},
|
|
|
|
|
|
{T("god"), 2, CA_GOD, CA_GOD},
|
|
|
|
|
|
{T("head"), 2, CA_WIZARD, CA_HEAD},
|
|
|
|
|
|
{T("immortal"), 3, CA_WIZARD, CA_IMMORTAL},
|
|
|
|
|
|
{T("need_location"), 6, CA_PUBLIC, CA_LOCATION},
|
|
|
|
|
|
{T("need_contents"), 6, CA_PUBLIC, CA_CONTENTS},
|
|
|
|
|
|
{T("need_player"), 6, CA_PUBLIC, CA_PLAYER},
|
|
|
|
|
|
{T("no_haven"), 4, CA_PUBLIC, CA_NO_HAVEN},
|
|
|
|
|
|
{T("no_robot"), 4, CA_WIZARD, CA_NO_ROBOT},
|
|
|
|
|
|
{T("no_slave"), 5, CA_PUBLIC, CA_NO_SLAVE},
|
|
|
|
|
|
{T("no_suspect"), 5, CA_WIZARD, CA_NO_SUSPECT},
|
|
|
|
|
|
{T("no_guest"), 5, CA_WIZARD, CA_NO_GUEST},
|
|
|
|
|
|
{T("no_uninspected"), 5, CA_WIZARD, CA_NO_UNINS},
|
|
|
|
|
|
{T("robot"), 2, CA_WIZARD, CA_ROBOT},
|
|
|
|
|
|
{T("staff"), 4, CA_WIZARD, CA_STAFF},
|
|
|
|
|
|
{T("static"), 4, CA_GOD, CA_STATIC},
|
|
|
|
|
|
{T("uninspected"), 5, CA_WIZARD, CA_UNINS},
|
|
|
|
|
|
{T("wizard"), 3, CA_WIZARD, CA_WIZARD},
|
2026-03-03 19:38:14 -07:00
|
|
|
|
{nullptr, 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void list_cmdaccess(dbref player)
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for ( CMDENT_NO_ARG *cmdp0a = command_table_no_arg;
|
|
|
|
|
|
cmdp0a->cmdname;
|
|
|
|
|
|
cmdp0a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp0a->perms)
|
|
|
|
|
|
&& !(cmdp0a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, access_nametab, cmdp0a->perms, cmdp0a->cmdname, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_ONE_ARG *cmdp1a = command_table_one_arg;
|
|
|
|
|
|
cmdp1a->cmdname;
|
|
|
|
|
|
cmdp1a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp1a->perms)
|
|
|
|
|
|
&& !(cmdp1a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, access_nametab, cmdp1a->perms, cmdp1a->cmdname, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG *cmdp2a = command_table_two_arg;
|
|
|
|
|
|
cmdp2a->cmdname;
|
|
|
|
|
|
cmdp2a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp2a->perms)
|
|
|
|
|
|
&& !(cmdp2a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, access_nametab, cmdp2a->perms, cmdp2a->cmdname, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG_ARGV *cmdp2av = command_table_two_arg_argv;
|
|
|
|
|
|
cmdp2av->cmdname;
|
|
|
|
|
|
cmdp2av++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( check_access(player, cmdp2av->perms)
|
|
|
|
|
|
&& !(cmdp2av->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, access_nametab, cmdp2av->perms, cmdp2av->cmdname, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for (ATTR *ap = AttrTable; ap->name; ap++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (ap->flags & AF_NOCMD)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t nBuffer;
|
|
|
|
|
|
bool bValid;
|
2007-03-12 08:15:29 +00:00
|
|
|
|
UTF8 *buff2 = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
auto it_b2 = mudstate.command_htab.find(std::vector<UTF8>(buff2, buff2 + nBuffer));
|
|
|
|
|
|
CMDENT *cmdp = (it_b2 != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_b2->second) : nullptr;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if ( nullptr != cmdp
|
2007-04-09 05:34:50 +00:00
|
|
|
|
&& check_access(player, cmdp->perms)
|
|
|
|
|
|
&& !(cmdp->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, access_nametab, cmdp->perms, cmdp->cmdname, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_cmdswitches: List switches for commands.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void list_cmdswitches(dbref player)
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for ( CMDENT_NO_ARG *cmdp0a = command_table_no_arg;
|
|
|
|
|
|
cmdp0a->cmdname;
|
|
|
|
|
|
cmdp0a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( cmdp0a->switches
|
|
|
|
|
|
&& check_access(player, cmdp0a->perms)
|
|
|
|
|
|
&& !(cmdp0a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
display_nametab(player, cmdp0a->switches, cmdp0a->cmdname, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_ONE_ARG *cmdp1a = command_table_one_arg;
|
|
|
|
|
|
cmdp1a->cmdname;
|
|
|
|
|
|
cmdp1a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( cmdp1a->switches
|
|
|
|
|
|
&& check_access(player, cmdp1a->perms)
|
|
|
|
|
|
&& !(cmdp1a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
display_nametab(player, cmdp1a->switches, cmdp1a->cmdname, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG *cmdp2a = command_table_two_arg;
|
|
|
|
|
|
cmdp2a->cmdname;
|
|
|
|
|
|
cmdp2a++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( cmdp2a->switches
|
|
|
|
|
|
&& check_access(player, cmdp2a->perms)
|
|
|
|
|
|
&& !(cmdp2a->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
display_nametab(player, cmdp2a->switches, cmdp2a->cmdname, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-04-09 05:34:50 +00:00
|
|
|
|
|
|
|
|
|
|
for ( CMDENT_TWO_ARG_ARGV *cmdp2av = command_table_two_arg_argv;
|
|
|
|
|
|
cmdp2av->cmdname;
|
|
|
|
|
|
cmdp2av++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
if ( cmdp2av->switches
|
|
|
|
|
|
&& check_access(player, cmdp2av->perms)
|
|
|
|
|
|
&& !(cmdp2av->perms & CF_DARK))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
display_nametab(player, cmdp2av->switches, cmdp2av->cmdname, false);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_attraccess: List access to attributes.
|
|
|
|
|
|
//
|
|
|
|
|
|
NAMETAB attraccess_nametab[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("const"), 1, CA_PUBLIC, AF_CONST},
|
|
|
|
|
|
{T("dark"), 2, CA_WIZARD, AF_DARK},
|
|
|
|
|
|
{T("deleted"), 2, CA_WIZARD, AF_DELETED},
|
|
|
|
|
|
{T("god"), 1, CA_PUBLIC, AF_GOD},
|
|
|
|
|
|
{T("hidden"), 1, CA_WIZARD, AF_MDARK},
|
|
|
|
|
|
{T("ignore"), 2, CA_WIZARD, AF_NOCMD},
|
|
|
|
|
|
{T("internal"), 2, CA_WIZARD, AF_INTERNAL},
|
|
|
|
|
|
{T("is_lock"), 4, CA_PUBLIC, AF_IS_LOCK},
|
|
|
|
|
|
{T("locked"), 1, CA_PUBLIC, AF_LOCK},
|
|
|
|
|
|
{T("no_command"), 4, CA_PUBLIC, AF_NOPROG},
|
|
|
|
|
|
{T("no_inherit"), 4, CA_PUBLIC, AF_PRIVATE},
|
|
|
|
|
|
{T("private"), 1, CA_PUBLIC, AF_ODARK},
|
|
|
|
|
|
{T("regexp"), 1, CA_PUBLIC, AF_REGEXP},
|
|
|
|
|
|
{T("visual"), 1, CA_PUBLIC, AF_VISUAL},
|
|
|
|
|
|
{T("wizard"), 1, CA_PUBLIC, AF_WIZARD},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
NAMETAB indiv_attraccess_nametab[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("case"), 1, CA_PUBLIC, AF_CASE},
|
|
|
|
|
|
{T("hidden"), 1, CA_WIZARD, AF_MDARK},
|
|
|
|
|
|
{T("html"), 2, CA_PUBLIC, AF_HTML},
|
|
|
|
|
|
{T("no_command"), 4, CA_PUBLIC, AF_NOPROG},
|
|
|
|
|
|
{T("no_inherit"), 4, CA_PUBLIC, AF_PRIVATE},
|
Implement NOEVAL object flag and attribute flag (#11).
Add NOEVAL object flag (FLAG_WORD3) and AF_NOEVAL attribute flag so that
attribute contents can be stored as literal data without evaluation.
When either flag is set, u(), ulocal(), get_eval(), @trigger, did_it()
messages/actions, @function, modSpeech, check_filter, make_prefix,
process_hook, sortby comparison, eval_boolexp, and format attributes
(EXITFORMAT/CONFORMAT/NAMEFORMAT/DESCFORMAT) all return raw text with
no function calls, %-substitutions, or escape processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:04:14 -07:00
|
|
|
|
{T("no_eval"), 4, CA_PUBLIC, AF_NOEVAL},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("no_name"), 4, CA_PUBLIC, AF_NONAME},
|
|
|
|
|
|
{T("no_parse"), 4, CA_PUBLIC, AF_NOPARSE},
|
|
|
|
|
|
{T("regexp"), 1, CA_PUBLIC, AF_REGEXP},
|
|
|
|
|
|
{T("trace"), 1, CA_PUBLIC, AF_TRACE},
|
|
|
|
|
|
{T("visual"), 1, CA_PUBLIC, AF_VISUAL},
|
|
|
|
|
|
{T("wizard"), 1, CA_WIZARD, AF_WIZARD},
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void list_attraccess(dbref player)
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
for (ATTR *ap = AttrTable; ap->name; ap++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (bCanReadAttr(player, player, ap, false))
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
listset_nametab(player, attraccess_nametab, ap->flags, ap->name, true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// cf_access: Change command or switch permissions.
|
|
|
|
|
|
//
|
|
|
|
|
|
CF_HAND(cf_access)
|
|
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(vp);
|
|
|
|
|
|
|
|
|
|
|
|
CMDENT *cmdp;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *ap;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
bool set_switch;
|
|
|
|
|
|
|
|
|
|
|
|
for (ap = str; *ap && !mux_isspace(*ap) && (*ap != '/'); ap++) ;
|
|
|
|
|
|
if (*ap == '/')
|
|
|
|
|
|
{
|
|
|
|
|
|
set_switch = true;
|
|
|
|
|
|
*ap++ = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
set_switch = false;
|
|
|
|
|
|
if (*ap)
|
|
|
|
|
|
{
|
|
|
|
|
|
*ap++ = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
while (mux_isspace(*ap))
|
|
|
|
|
|
{
|
|
|
|
|
|
ap++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
size_t nStr = strlen(reinterpret_cast<char*>(str));
|
|
|
|
|
|
auto it_str = mudstate.command_htab.find(std::vector<UTF8>(str, str + nStr));
|
|
|
|
|
|
cmdp = (it_str != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_str->second) : nullptr;
|
|
|
|
|
|
}
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (cmdp != nullptr)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (set_switch)
|
|
|
|
|
|
{
|
2026-03-03 18:39:35 -07:00
|
|
|
|
return cf_ntab_access(reinterpret_cast<int *>(cmdp->switches), ap, pExtra, nExtra,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
player, cmd);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return cf_modify_bits(&(cmdp->perms), ap, pExtra, nExtra, player,
|
|
|
|
|
|
cmd);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
if (!mux_stricmp(str, T("home")))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
return cf_modify_bits(&(mudconf.restrict_home), ap, pExtra,
|
|
|
|
|
|
nExtra, player, cmd);
|
|
|
|
|
|
}
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cf_log_notfound(player, cmd, T("Command"), str);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// cf_acmd_access: Change command permissions for all attr-setting cmds.
|
|
|
|
|
|
//
|
|
|
|
|
|
CF_HAND(cf_acmd_access)
|
|
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(vp);
|
|
|
|
|
|
|
|
|
|
|
|
ATTR *ap;
|
|
|
|
|
|
|
|
|
|
|
|
for (ap = AttrTable; ap->name; ap++)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t nBuffer;
|
|
|
|
|
|
bool bValid;
|
2007-03-12 08:15:29 +00:00
|
|
|
|
UTF8 *buff = MakeCanonicalAttributeCommand(ap->name, &nBuffer, &bValid);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
auto it_bf = mudstate.command_htab.find(std::vector<UTF8>(buff, buff + nBuffer));
|
|
|
|
|
|
CMDENT *cmdp = (it_bf != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_bf->second) : nullptr;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (cmdp != nullptr)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
int save = cmdp->perms;
|
|
|
|
|
|
int failure = cf_modify_bits(&(cmdp->perms), str, pExtra, nExtra,
|
|
|
|
|
|
player, cmd);
|
|
|
|
|
|
if (failure != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
cmdp->perms = save;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// cf_attr_access: Change access on an attribute.
|
|
|
|
|
|
//
|
|
|
|
|
|
CF_HAND(cf_attr_access)
|
|
|
|
|
|
{
|
|
|
|
|
|
ATTR *ap;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *sp;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2010-12-31 10:57:44 -08:00
|
|
|
|
ATTRPERM **ppv = (ATTRPERM **)vp;
|
|
|
|
|
|
|
2006-09-01 22:59:23 +00:00
|
|
|
|
for (sp = str; *sp && !mux_isspace(*sp); sp++)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*sp)
|
|
|
|
|
|
{
|
|
|
|
|
|
*sp++ = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
while (mux_isspace(*sp))
|
|
|
|
|
|
{
|
|
|
|
|
|
sp++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 18:39:35 -07:00
|
|
|
|
ap = atr_str(reinterpret_cast<UTF8 *>(str));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (ap)
|
|
|
|
|
|
{
|
2010-12-31 10:57:44 -08:00
|
|
|
|
// This is a straight-out built-in attribute, so we'll just modify directly.
|
|
|
|
|
|
//
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return cf_modify_bits(&(ap->flags), sp, pExtra, nExtra, player, cmd);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2010-12-31 10:57:44 -08:00
|
|
|
|
// This is either a wildcard or a vattr, so should be added to the table.
|
|
|
|
|
|
//
|
2018-10-03 17:54:51 +00:00
|
|
|
|
ATTRPERM *perm = nullptr;
|
2010-12-31 10:57:44 -08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
perm = new ATTRPERM;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (...)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr == perm)
|
2010-12-31 10:57:44 -08:00
|
|
|
|
{
|
|
|
|
|
|
cf_log_syntax(player, cmd, T("Out of memory."));
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
perm->wildcard = StringClone(str);
|
|
|
|
|
|
perm->flags = 0;
|
|
|
|
|
|
|
|
|
|
|
|
ATTRPERM *head = *ppv;
|
|
|
|
|
|
|
|
|
|
|
|
// Add our permission to the list.
|
|
|
|
|
|
//
|
|
|
|
|
|
if (mudstate.bReadingConfiguration)
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (nullptr == head)
|
2010-12-31 10:57:44 -08:00
|
|
|
|
{
|
|
|
|
|
|
*ppv = perm;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ATTRPERM *last;
|
|
|
|
|
|
for (last = head; last->next; last = last->next)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
|
|
|
|
|
last->next = perm;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
perm->next = head;
|
|
|
|
|
|
*ppv = perm;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Call the standard permission parser.
|
|
|
|
|
|
//
|
|
|
|
|
|
return cf_modify_bits(&(perm->flags), sp, pExtra, nExtra, player, cmd);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// cf_cmd_alias: Add a command alias.
|
|
|
|
|
|
//
|
|
|
|
|
|
CF_HAND(cf_cmd_alias)
|
|
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(pExtra);
|
|
|
|
|
|
UNUSED_PARAMETER(nExtra);
|
|
|
|
|
|
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *ap;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
CMDENT *cmdp, *cmd2;
|
|
|
|
|
|
NAMETAB *nt;
|
|
|
|
|
|
|
2022-03-11 12:36:37 -07:00
|
|
|
|
string_token st(str, T(" \t=,"));
|
|
|
|
|
|
UTF8 *alias = st.parse();
|
|
|
|
|
|
UTF8 *orig = st.parse();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
if (!orig)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We only got one argument to @alias. Bad.
|
|
|
|
|
|
//
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (ap = orig; *ap && (*ap != '/'); ap++) ;
|
|
|
|
|
|
if (*ap == '/')
|
|
|
|
|
|
{
|
|
|
|
|
|
// Switch form of command aliasing: create an alias for
|
|
|
|
|
|
// a command + a switch
|
|
|
|
|
|
//
|
|
|
|
|
|
*ap++ = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
// Look up the command
|
|
|
|
|
|
//
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
StringPtrMap *htab = reinterpret_cast<StringPtrMap*>(vp);
|
|
|
|
|
|
size_t nOrig = strlen(reinterpret_cast<char*>(orig));
|
|
|
|
|
|
auto it_orig = htab->find(std::vector<UTF8>(orig, orig + nOrig));
|
|
|
|
|
|
cmdp = (it_orig != htab->end()) ? static_cast<CMDENT*>(it_orig->second) : nullptr;
|
|
|
|
|
|
}
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (cmdp == nullptr || cmdp->switches == nullptr)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cf_log_notfound(player, cmd, T("Command"), orig);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Look up the switch
|
|
|
|
|
|
//
|
2026-03-03 18:39:35 -07:00
|
|
|
|
nt = find_nametab_ent(player, reinterpret_cast<NAMETAB *>(cmdp->switches), ap);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!nt)
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cf_log_notfound(player, cmd, T("Switch"), ap);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
StringPtrMap *htab_chk = reinterpret_cast<StringPtrMap*>(vp);
|
|
|
|
|
|
size_t nAlias = strlen(reinterpret_cast<char*>(alias));
|
|
|
|
|
|
auto it_alias = htab_chk->find(std::vector<UTF8>(alias, alias + nAlias));
|
|
|
|
|
|
if (it_alias == htab_chk->end())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
// Create the new command table entry.
|
|
|
|
|
|
//
|
|
|
|
|
|
cmd2 = nullptr;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
cmd2 = new CMDENT;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (...)
|
|
|
|
|
|
{
|
|
|
|
|
|
; // Nothing.
|
|
|
|
|
|
}
|
Remove ISOUTOFMEMORY macro; add per-site OOM recovery and fix g_dump_child_pid
Eliminate the ISOUTOFMEMORY macro that unconditionally aborted on allocation
failure. Each of the 23 call sites now handles OOM appropriately:
- Fatal sites (buffer pools, db array, anum table): mux_assert or OutOfMemory
- Recoverable sites (queue, mail, commands, guests, vattrs, config, restart,
forward lists): log the failure and return gracefully
Also fix g_dump_child_pid portability: volatile pid_t -> volatile sig_atomic_t
with explicit casts in ganl_adapter.cpp.
Close integer overflow issue as false alarm (getstring_noalloc uses a bounded
static buffer, so nBuffer+1 cannot wrap).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:31:20 -06:00
|
|
|
|
if (nullptr == cmd2)
|
|
|
|
|
|
{
|
|
|
|
|
|
STARTLOG(LOG_PROBLEMS, "CMD", "MEM");
|
|
|
|
|
|
log_printf(T("cf_alias: out of memory creating switch alias."));
|
|
|
|
|
|
ENDLOG;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
cmd2->cmdname = StringClone(alias);
|
|
|
|
|
|
cmd2->switches = cmdp->switches;
|
|
|
|
|
|
cmd2->perms = cmdp->perms | nt->perm;
|
|
|
|
|
|
cmd2->extra = (cmdp->extra | nt->flag) & ~SW_MULTIPLE;
|
|
|
|
|
|
if (!(nt->flag & SW_MULTIPLE))
|
|
|
|
|
|
{
|
|
|
|
|
|
cmd2->extra |= SW_GOT_UNIQUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
cmd2->callseq = cmdp->callseq;
|
|
|
|
|
|
cmd2->handler = cmdp->handler;
|
|
|
|
|
|
cmd2->flags = CEF_ALLOC;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nCmd2 = strlen(reinterpret_cast<char*>(cmd2->cmdname));
|
|
|
|
|
|
htab_chk->emplace(std::vector<UTF8>(cmd2->cmdname, cmd2->cmdname + nCmd2), cmd2);
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// A normal (non-switch) alias
|
|
|
|
|
|
//
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
StringPtrMap *htab_ns = reinterpret_cast<StringPtrMap*>(vp);
|
|
|
|
|
|
size_t nOrig2 = strlen(reinterpret_cast<char*>(orig));
|
|
|
|
|
|
auto it_hp = htab_ns->find(std::vector<UTF8>(orig, orig + nOrig2));
|
|
|
|
|
|
void *hp = (it_hp != htab_ns->end()) ? it_hp->second : nullptr;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if (hp == nullptr)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
cf_log_notfound(player, cmd, T("Entry"), orig);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
size_t nAlias2 = strlen(reinterpret_cast<char*>(alias));
|
|
|
|
|
|
htab_ns->emplace(std::vector<UTF8>(alias, alias + nAlias2), hp);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_df_flags: List default flags at create time.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void list_df_flags(dbref player)
|
|
|
|
|
|
{
|
|
|
|
|
|
FLAGSET fs;
|
|
|
|
|
|
|
|
|
|
|
|
fs = mudconf.player_flags;
|
|
|
|
|
|
fs.word[FLAG_WORD1] |= TYPE_PLAYER;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *playerb = decode_flags(player, &fs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
fs = mudconf.room_flags;
|
|
|
|
|
|
fs.word[FLAG_WORD1] |= TYPE_ROOM;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *roomb = decode_flags(player, &fs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
fs = mudconf.exit_flags;
|
|
|
|
|
|
fs.word[FLAG_WORD1] |= TYPE_EXIT;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *exitb = decode_flags(player, &fs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
fs = mudconf.thing_flags;
|
|
|
|
|
|
fs.word[FLAG_WORD1] |= TYPE_THING;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *thingb = decode_flags(player, &fs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
fs = mudconf.robot_flags;
|
|
|
|
|
|
fs.word[FLAG_WORD1] |= TYPE_PLAYER;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *robotb = decode_flags(player, &fs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf buff = LBuf_Src("list_df_flags");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mux_sprintf(buff, LBUF_SIZE,
|
2008-12-27 18:37:01 -08:00
|
|
|
|
T("Default flags: Players...%s Rooms...%s Exits...%s Things...%s Robots...%s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
playerb, roomb, exitb, thingb, robotb);
|
|
|
|
|
|
|
|
|
|
|
|
free_sbuf(playerb);
|
|
|
|
|
|
free_sbuf(roomb);
|
|
|
|
|
|
free_sbuf(exitb);
|
|
|
|
|
|
free_sbuf(thingb);
|
|
|
|
|
|
free_sbuf(robotb);
|
|
|
|
|
|
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_costs: List the costs of things.
|
|
|
|
|
|
//
|
|
|
|
|
|
#define coin_name(s) (((s)==1) ? mudconf.one_coin : mudconf.many_coins)
|
|
|
|
|
|
|
|
|
|
|
|
static void list_costs(dbref player)
|
|
|
|
|
|
{
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *buff = alloc_mbuf("list_costs");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
if (mudconf.quotas)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T(" and %d quota"), mudconf.room_quota);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Digging a room costs %d %s%s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.digcost, coin_name(mudconf.digcost), buff));
|
|
|
|
|
|
if (mudconf.quotas)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T(" and %d quota"), mudconf.exit_quota);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Opening a new exit costs %d %s%s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.opencost, coin_name(mudconf.opencost), buff));
|
|
|
|
|
|
notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Linking an exit, home, or dropto costs %d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.linkcost, coin_name(mudconf.linkcost)));
|
|
|
|
|
|
if (mudconf.quotas)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T(" and %d quota"), mudconf.thing_quota);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (mudconf.createmin == mudconf.createmax)
|
|
|
|
|
|
{
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Creating a new thing costs %d %s%s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.createmin,
|
|
|
|
|
|
coin_name(mudconf.createmin), buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Creating a new thing costs between %d and %d %s%s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.createmin, mudconf.createmax,
|
|
|
|
|
|
mudconf.many_coins, buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (mudconf.quotas)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T(" and %d quota"), mudconf.player_quota);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Creating a robot costs %d %s%s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.robotcost, coin_name(mudconf.robotcost), buff));
|
|
|
|
|
|
if (mudconf.killmin == mudconf.killmax)
|
|
|
|
|
|
{
|
|
|
|
|
|
int chance = 100;
|
|
|
|
|
|
if (0 < mudconf.killguarantee)
|
|
|
|
|
|
{
|
|
|
|
|
|
chance = (mudconf.killmin * 100) / mudconf.killguarantee;
|
|
|
|
|
|
}
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("Killing costs %d %s, with a %d%% chance of success."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.killmin, coin_name(mudconf.digcost), chance));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
int cost_surething;
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("Killing costs between %d and %d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.killmin, mudconf.killmax, mudconf.many_coins));
|
|
|
|
|
|
if (0 < mudconf.killguarantee)
|
|
|
|
|
|
{
|
|
|
|
|
|
cost_surething = mudconf.killguarantee;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
cost_surething = mudconf.killmin;
|
|
|
|
|
|
}
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("You must spend %d %s to guarantee success."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
cost_surething, coin_name(cost_surething)));
|
|
|
|
|
|
}
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Computationally expensive commands and functions (ie: @entrances, @find, @search, @stats (with an argument or switch), search(), and stats()) cost %d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.searchcost, coin_name(mudconf.searchcost)));
|
|
|
|
|
|
if (mudconf.machinecost > 0)
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Each command run from the queue costs 1/%d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.machinecost, mudconf.one_coin));
|
|
|
|
|
|
if (mudconf.waitcost > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("A %d %s deposit is charged for putting a command on the queue."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.waitcost, mudconf.one_coin));
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The deposit is refunded when the command is run or canceled."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (mudconf.sacfactor == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
mux_ltoa(mudconf.sacadjust, buff);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (mudconf.sacfactor == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mudconf.sacadjust < 0)
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("<create cost> - %d"), -mudconf.sacadjust);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else if (mudconf.sacadjust > 0)
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("<create cost> + %d"), mudconf.sacadjust);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("<create cost>"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mudconf.sacadjust < 0)
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("(<create cost> / %d) - %d"), mudconf.sacfactor, -mudconf.sacadjust);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else if (mudconf.sacadjust > 0)
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("(<create cost> / %d) + %d"), mudconf.sacfactor, mudconf.sacadjust);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("<create cost> / %d"), mudconf.sacfactor);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("The value of an object is %s."), buff));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.clone_copy_cost)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The default value of cloned objects is the value of the original object."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("The default value of cloned objects is %d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.createmin, coin_name(mudconf.createmin)));
|
|
|
|
|
|
|
|
|
|
|
|
free_mbuf(buff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_options: List more game options from mudconf.
|
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
|
static const UTF8 *switchd[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("/first"),
|
|
|
|
|
|
T("/all")
|
2007-03-14 00:55:08 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static const UTF8 *examd[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("/brief"),
|
|
|
|
|
|
T("/full")
|
2007-03-14 00:55:08 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static const UTF8 *ed[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("Disabled"),
|
|
|
|
|
|
T("Enabled")
|
2007-03-14 00:55:08 +00:00
|
|
|
|
};
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
static void list_options(dbref player)
|
|
|
|
|
|
{
|
2007-03-14 00:55:08 +00:00
|
|
|
|
UTF8 *buff;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
CLinearTimeAbsolute ltaNow;
|
|
|
|
|
|
ltaNow.GetUTC();
|
|
|
|
|
|
|
|
|
|
|
|
if (mudconf.quotas)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Building quotas are enforced."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.name_spaces)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Player names may contain spaces."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Player names may not contain spaces."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.robot_speak)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Robots are not allowed to speak in public areas."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.player_listen)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The @Listen/@Ahear attribute set works on player objects."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.ex_flags)
|
2008-01-31 22:06:21 -08:00
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘examine’ command lists the flag names for the object’s flags."));
|
2008-01-31 22:06:21 -08:00
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.quiet_look)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘look’ command shows visible attributes in addition to the description."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.see_own_dark)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘look’ command lists DARK objects owned by you."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.dark_sleepers)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘look’ command shows disconnected players."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.terse_look)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘look’ command obeys the TERSE flag."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.trace_topdown)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Trace output is presented top-down (whole expression first, then sub-exprs)."));
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("Only %d lines of trace output are displayed."), mudconf.trace_limit));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Trace output is presented bottom-up (subexpressions first)."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (!mudconf.quiet_whisper)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘whisper’ command lets others in the room with you know you whispered."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.pemit_players)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘@pemit’ command may be used to emit to faraway players."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.terse_contents)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The TERSE flag suppresses listing the contents of a location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.terse_exits)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The TERSE flag suppresses listing obvious exits in a location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!mudconf.terse_movemsg)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The TERSE flag suppresses enter/leave/succ/drop messages generated by moving."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.pub_flags)
|
2008-01-31 22:06:21 -08:00
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘flags()’ function will return the flags of any object."));
|
2008-01-31 22:06:21 -08:00
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.read_rem_desc)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘get()’ function will return the description of faraway objects,"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.read_rem_name)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The ‘name()’ function will return the name of faraway objects."));
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("The default switch for the ‘@switch’ command is %s."), switchd[mudconf.switch_df_all]));
|
2008-01-31 22:06:21 -08:00
|
|
|
|
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
raw_notify(player, tprintf(M_("The default switch for the ‘examine’ command is %s."), examd[mudconf.exam_public]));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.sweep_dark)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Players may @sweep dark locations."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.fascist_tport)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("You may only @teleport out of locations that are JUMP_OK or that you control."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Players may have at most %d commands in the queue at one time."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.queuemax));
|
|
|
|
|
|
if (mudconf.match_mine)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mudconf.match_mine_pl)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("All objects search themselves for $-commands."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Objects other than players search themselves for $-commands."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (!Wizard(player))
|
|
|
|
|
|
return;
|
|
|
|
|
|
buff = alloc_mbuf("list_options");
|
|
|
|
|
|
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("%d commands are run from the queue when there is no net activity."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.queue_chunk));
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("%d commands are run from the queue when there is net activity."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.active_q_chunk));
|
|
|
|
|
|
if (mudconf.idle_wiz_dark)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Wizards idle for longer than the default timeout are automatically set DARK."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.safe_unowned)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Objects not owned by you are automatically considered SAFE."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.paranoid_alloc)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("The buffer pools are checked for consistency on each allocate or free."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.cache_names)
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("A separate name cache is used."));
|
2007-12-26 08:17:12 +00:00
|
|
|
|
#if defined(HAVE_WORKING_FORK)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.fork_dump)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Database dumps are performed by a fork()ed process."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2007-12-26 08:17:12 +00:00
|
|
|
|
#endif // HAVE_WORKING_FORK
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (mudconf.max_players >= 0)
|
|
|
|
|
|
raw_notify(player,
|
fix(nls): plural morphology baked into msgids, and a fragment that could not be translated (#1717)
Found while translating mail (#1419). The tell was a line wrong in English
before translation is even involved:
MAIL: 1 messages in folder 0 [unnamed] (1 unread, 0 cleared).
MN_() exists for this (#1622) and #1655 converted the @mail/stats family;
this set was missed. A translator cannot work around it -- the msgid has no
msgid_plural, so there is no second form for a catalogue to supply, and es
must pick one wording for all counts while ru and pl need three and can
express none of them. The fix is in the C++, not the .po.
## Converted, 11 sites
mail.cpp, mail_mod.cpp mailbox is full; URGENT MAIL urgent messages
walkdb.cpp universe contains; objects @chowned; objects marked
object.cpp objects @chowned to you
wiz.cpp You toaded ... objects @chowned
command.cpp at most N players logged in
The mail module duplicates are converted alongside the engine's so the two
implementations do not drift (#1614).
## One was a different bug than the issue described
walkdb.cpp built its message as M_("%d objects %smarked") with %s = "" or
"un". That is fragment assembly, not a missing plural: a translator handed
that %s cannot use it, because the prefix is English morphology rather than
a word. Split into two whole sentences, each pluralised -- the #1575 /
#1588 rule. Now renders "1 object marked" / "8 objects unmarked" instead of
a %s a catalogue has no way to fill.
## Two deliberately NOT converted
MAIL: %d messages in folder %d [%s] (%d unread, %d cleared).
%d objects = %d rooms, %d exits, %d things, %d players. (%d garbage)
MN_(s, p, n) selects one form from one n. Four independent counts are four
independent plural decisions, and in Russian each noun needs its own form.
These want rewording, which is a design call rather than a mechanical
conversion, so they are left and recorded rather than half-fixed.
## Catalogue fallout
.pot 18 -> 27 plural entries; all three catalogues msgmerge'd.
xx is `complete` policy, so its nine new entries had to be filled and
unfuzzied or the guard fails -- which it duly did, first try. msgmerge had
copied the old singular-only text into BOTH forms, so msgstr[0] said
"messages"; each form is now prefixed from its own msgid.
es and ko received real translations for all nine.
es.po 190 -> 198/976 (20.3%)
ko.po 229 -> 236/976 (24.2%)
## Verified end to end, at n=1 and n>1
en 1 object marked 8 objects marked
es 1 objeto marcado 8 objetos marcados
ko 사물 1개를 표시했습니다 사물 8개를 표시했습니다
xx [xx] 1 object marked [xx] 8 objects marked
Korean renders identically for both, which is correct: it declares
nplurals=1, so the catalogue's own rule is being honoured rather than
English's imposed on it.
The unconverted multi-count line still reads "1 messages", as documented.
make test: Smoke 1561 x3, tests/nls 7, ko 4, plural 43. TESTEXIT=0.
Refs #1419, #1575, #1588, #1614, #1622, #1655, #1702.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 15:29:08 -06:00
|
|
|
|
tprintf(MN_("There may be at most %d player logged in at once.",
|
|
|
|
|
|
"There may be at most %d players logged in at once.",
|
|
|
|
|
|
mudconf.max_players),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.max_players));
|
|
|
|
|
|
if (mudconf.quotas)
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T(" and %d quota"), mudconf.start_quota);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
else
|
|
|
|
|
|
*buff = '\0';
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("New players are given %d %s to start with."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.paystart, mudconf.many_coins));
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Players are given %d %s each day they connect."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.paycheck, mudconf.many_coins));
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Earning money is difficult if you have more than %d %s."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.paylimit, mudconf.many_coins));
|
|
|
|
|
|
if (mudconf.payfind > 0)
|
|
|
|
|
|
raw_notify(player,
|
nls: mark cque/command/predicates/mail notify prose with M_() (#1681)
Phase 3 coverage, parallel to mux_table table-header work:
cque @ps timer labels, WaitQ warp, commands processed
command switch errors, dig/open/create/kill costs, money help,
queue/login limits, lua/cache stats display
predicates not-enough-money, command table add/not-found
mail folder/send/clear/reject/stats *sentences* only
Left alone: mail %-column layouts, pose "%s %s", softcode __name keys,
NOPERM_MESSAGE, tabular predicate listings. pot 723-ish -> 795 msgids;
xx filled; ko msgmerge only.
2026-07-28 08:54:03 -06:00
|
|
|
|
tprintf(M_("Players have a 1 in %d chance of finding a %s each time they move."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.payfind, mudconf.one_coin));
|
|
|
|
|
|
raw_notify(player,
|
2008-12-27 18:37:01 -08:00
|
|
|
|
tprintf(T("The head of the object freelist is #%d."),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.freelist));
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Intervals: Dump...%d Clean...%d Idlecheck...%d"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.dump_interval, mudconf.check_interval,
|
|
|
|
|
|
mudconf.idle_interval);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
|
|
|
|
|
CLinearTimeDelta ltdDump = mudstate.dump_counter - ltaNow;
|
|
|
|
|
|
CLinearTimeDelta ltdCheck = mudstate.check_counter - ltaNow;
|
|
|
|
|
|
CLinearTimeDelta ltdIdle = mudstate.idle_counter - ltaNow;
|
|
|
|
|
|
|
|
|
|
|
|
long lDump = ltdDump.ReturnSeconds();
|
|
|
|
|
|
long lCheck = ltdCheck.ReturnSeconds();
|
|
|
|
|
|
long lIdle = ltdIdle.ReturnSeconds();
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Timers: Dump...%ld Clean...%ld Idlecheck...%ld"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
lDump, lCheck, lIdle);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Timeouts: Idle...%d Connect...%d Tries...%d"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.idle_timeout, mudconf.conn_timeout,
|
|
|
|
|
|
mudconf.retry_limit);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Scheduling: Timeslice...%s Max_Quota...%d Increment...%d"),
|
2007-11-03 21:34:30 -07:00
|
|
|
|
mudconf.timeslice.ReturnSecondsString(3), mudconf.cmd_quota_max,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.cmd_quota_incr);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
2026-03-04 15:37:58 -07:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Spaces...%s"),
|
|
|
|
|
|
ed[mudconf.space_compress]);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("New characters: Room...#%d Home...#%d DefaultHome...#%d Quota...%d"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.start_room, mudconf.start_home, mudconf.default_home,
|
|
|
|
|
|
mudconf.start_quota);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, MBUF_SIZE, T("Misc: GuestChar...#%d IdleQueueChunk...%d ActiveQueueChunk...%d Master_room...#%d"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.guest_char, mudconf.queue_chunk,
|
|
|
|
|
|
mudconf.active_q_chunk, mudconf.master_room);
|
|
|
|
|
|
raw_notify(player, buff);
|
|
|
|
|
|
|
|
|
|
|
|
free_mbuf(buff);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_vattrs: List user-defined attributes
|
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
|
static void list_vattrs(dbref player, UTF8 *s_mask)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
bool wild_mtch = s_mask
|
|
|
|
|
|
&& s_mask[0] != '\0';
|
|
|
|
|
|
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf buff = LBuf_Src("list_vattrs");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// If wild_match, then only list attributes that match wildcard(s)
|
|
|
|
|
|
//
|
2008-12-27 18:37:01 -08:00
|
|
|
|
UTF8 *p = tprintf(T("--- User-Defined Attributes %s---"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
wild_mtch ? "(wildmatched) " : "");
|
|
|
|
|
|
raw_notify(player, p);
|
|
|
|
|
|
|
|
|
|
|
|
ATTR *va;
|
|
|
|
|
|
int na;
|
|
|
|
|
|
int wna = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (va = vattr_first(), na = 0; va; va = vattr_next(va), na++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!(va->flags & AF_DELETED))
|
|
|
|
|
|
{
|
|
|
|
|
|
// We need to be extremely careful that s_mask is !null and valid
|
|
|
|
|
|
//
|
|
|
|
|
|
if (wild_mtch)
|
|
|
|
|
|
{
|
|
|
|
|
|
mudstate.wild_invk_ctr = 0;
|
2007-03-14 00:55:08 +00:00
|
|
|
|
if (!quick_wild(s_mask, va->name))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
wna++;
|
|
|
|
|
|
}
|
2008-12-27 18:37:01 -08:00
|
|
|
|
mux_sprintf(buff, LBUF_SIZE, T("%s(%d)"), va->name, va->number);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
listset_nametab(player, attraccess_nametab, va->flags, buff, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (wild_mtch)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
p = tprintf(T("%d attributes matched, %d attributes total, next=%d"), wna,
|
2006-09-01 22:59:23 +00:00
|
|
|
|
na, mudstate.attr_next);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
p = tprintf(T("%d attributes, next=%d"), na, mudstate.attr_next);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
raw_notify(player, p);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 13:44:58 -06:00
|
|
|
|
// LeftJustifyString and RightJustifyNumber moved to stringutil.cpp (libmux.so).
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// list_hashstats: List information from hash tables
|
|
|
|
|
|
//
|
2026-07-28 11:31:23 -06:00
|
|
|
|
// Hash table size list (#1667 Phase 4 C3). The old full-stat header
|
|
|
|
|
|
// (Size/Num/Del/Lookups/…) did not match the abbreviated rows (name +
|
|
|
|
|
|
// entry count only). Header and rows now share one schema.
|
|
|
|
|
|
//
|
|
|
|
|
|
static const size_t kHashNameCols = 13;
|
|
|
|
|
|
static const size_t kHashEntriesCols = 11;
|
|
|
|
|
|
|
2022-03-14 14:11:12 -06:00
|
|
|
|
static void list_hashstat_abbreviated(const dbref player, const UTF8* tab_name, const int entries)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2022-03-14 14:11:12 -06:00
|
|
|
|
UTF8 buff[MBUF_SIZE];
|
2026-07-28 11:31:23 -06:00
|
|
|
|
UTF8 num[16];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
pos = mux_table_append_ljust(buff, sizeof(buff), pos, tab_name, kHashNameCols);
|
|
|
|
|
|
pos = mux_table_append_bytes(buff, sizeof(buff), pos, " ");
|
2026-07-28 17:34:14 +00:00
|
|
|
|
// RightJustifyNumber — mux_vsnprintf has no %* width (#1429).
|
|
|
|
|
|
//
|
|
|
|
|
|
size_t nw = RightJustifyNumber(num, kHashEntriesCols,
|
|
|
|
|
|
static_cast<int64_t>(entries), ' ');
|
|
|
|
|
|
num[nw] = '\0';
|
2026-07-28 11:31:23 -06:00
|
|
|
|
pos = mux_table_append_bytes(buff, sizeof(buff), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(num));
|
2022-03-14 14:11:12 -06:00
|
|
|
|
raw_notify(player, buff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-14 15:56:59 -06:00
|
|
|
|
static void list_hashstats(const dbref player)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-07-28 11:31:23 -06:00
|
|
|
|
{
|
|
|
|
|
|
UTF8 header[MBUF_SIZE];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
pos = mux_table_append_ljust(header, sizeof(header), pos,
|
|
|
|
|
|
M_("Name"), kHashNameCols);
|
|
|
|
|
|
pos = mux_table_append_bytes(header, sizeof(header), pos, " ");
|
|
|
|
|
|
pos = mux_table_append_ljust(header, sizeof(header), pos,
|
|
|
|
|
|
M_("Entries"), kHashEntriesCols);
|
|
|
|
|
|
raw_notify(player, header);
|
|
|
|
|
|
}
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
list_hashstat_abbreviated(player, T("Commands"), static_cast<int>(mudstate.command_htab.size()));
|
|
|
|
|
|
list_hashstat_abbreviated(player, T("Logout Cmds"), static_cast<int>(mudstate.logout_cmd_htab.size()));
|
2022-03-19 15:26:57 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Functions"), static_cast<int>(mudstate.builtin_functions.size()));;
|
2022-03-18 23:33:03 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Flags"), static_cast<int>(mudstate.flag_names_map.size()));;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
list_hashstat_abbreviated(player, T("Powers"), static_cast<int>(mudstate.powers_htab.size()));
|
2022-03-14 14:11:12 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Attr Names"), static_cast<int>(mudstate.builtin_attribute_names.size()));
|
2026-03-05 13:01:20 -07:00
|
|
|
|
list_hashstat_abbreviated(player, T("Vattr Names"), static_cast<int>(mudstate.vattr_name_map.size()));
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
list_hashstat_abbreviated(player, T("Player Names"), static_cast<int>(mudstate.player_htab.size()));
|
2026-03-08 21:47:01 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Net Descr."), get_total_connections());
|
2022-03-22 15:46:53 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Fwd. lists"), static_cast<int>(mudstate.forward_lists.size()));
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
list_hashstat_abbreviated(player, T("Excl. $-cmds"), static_cast<int>(mudstate.parent_htab.size()));
|
|
|
|
|
|
list_hashstat_abbreviated(player, T("Mail Messages"), static_cast<int>(mudstate.mail_htab.size()));
|
2022-03-14 17:30:38 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Channel Names"), static_cast<int>(mudstate.channel_names.size()));;
|
2022-03-14 14:11:12 -06:00
|
|
|
|
list_hashstat_abbreviated(player, T("Attr. Cache"), static_cast<int>(mudstate.attribute_lru_cache_list.size()));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
for (int i = 0; i < mudstate.nHelpDesc; i++)
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
list_hashstat_abbreviated(player, mudstate.aHelpDesc[i].pBaseFilename,
|
|
|
|
|
|
static_cast<int>(mudstate.aHelpDesc[i].ht->size()));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// list_process: List local resource usage stats of the mux process.
|
|
|
|
|
|
// Adapted from code by Claudius@PythonMUCK,
|
|
|
|
|
|
// posted to the net by Howard/Dark_Lord.
|
|
|
|
|
|
//
|
|
|
|
|
|
static void list_process(dbref player)
|
|
|
|
|
|
{
|
|
|
|
|
|
#ifdef HAVE_GETRUSAGE
|
|
|
|
|
|
struct rusage usage;
|
|
|
|
|
|
int ixrss, idrss, isrss, curr, last, dur;
|
|
|
|
|
|
|
|
|
|
|
|
getrusage(RUSAGE_SELF, &usage);
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate memory use from the aggregate totals.
|
|
|
|
|
|
//
|
|
|
|
|
|
curr = mudstate.mstat_curr;
|
|
|
|
|
|
last = 1 - curr;
|
|
|
|
|
|
dur = mudstate.mstat_secs[curr] - mudstate.mstat_secs[last];
|
|
|
|
|
|
if (dur > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
ixrss = (mudstate.mstat_ixrss[curr] -
|
|
|
|
|
|
mudstate.mstat_ixrss[last]) / dur;
|
|
|
|
|
|
idrss = (mudstate.mstat_idrss[curr] -
|
|
|
|
|
|
mudstate.mstat_idrss[last]) / dur;
|
|
|
|
|
|
isrss = (mudstate.mstat_isrss[curr] -
|
|
|
|
|
|
mudstate.mstat_isrss[last]) / dur;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ixrss = 0;
|
|
|
|
|
|
idrss = 0;
|
|
|
|
|
|
isrss = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif // HAVE_GETRUSAGE
|
|
|
|
|
|
|
2008-01-29 12:16:54 -08:00
|
|
|
|
#if defined(UNIX_NETWORKING)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef HAVE_GETDTABLESIZE
|
|
|
|
|
|
int maxfds = getdtablesize();
|
|
|
|
|
|
#else // HAVE_GETDTABLESIZE
|
|
|
|
|
|
int maxfds = sysconf(_SC_OPEN_MAX);
|
|
|
|
|
|
#endif // HAVE_GETDTABLESIZE
|
2026-03-03 16:30:37 -07:00
|
|
|
|
long psize = sysconf(_SC_PAGESIZE);
|
|
|
|
|
|
if (psize <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
psize = 4096;
|
|
|
|
|
|
}
|
|
|
|
|
|
raw_notify(player, tprintf(T("Process ID: %10d %10ld bytes per page"), game_pid, psize));
|
2008-01-29 12:16:54 -08:00
|
|
|
|
#else // UNIX_NETWORKING
|
2008-12-27 18:37:01 -08:00
|
|
|
|
raw_notify(player, tprintf(T("Process ID: %10d"), game_pid));
|
2008-01-29 12:16:54 -08:00
|
|
|
|
#endif // UNIX_NETWORKING
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_GETRUSAGE
|
2008-12-27 18:37:01 -08:00
|
|
|
|
raw_notify(player, tprintf(T("Time used: %10d user %10d sys"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_utime.tv_sec, usage.ru_stime.tv_sec));
|
2008-12-27 18:37:01 -08:00
|
|
|
|
raw_notify(player, tprintf(T("Resident mem:%10d shared %10d private%10d stack"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
ixrss, idrss, isrss));
|
|
|
|
|
|
raw_notify(player,
|
2009-02-09 07:54:48 -08:00
|
|
|
|
tprintf(T("Integral mem:%10ld shared %10ld private%10ld stack"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss));
|
|
|
|
|
|
raw_notify(player,
|
2009-02-08 20:43:31 -08:00
|
|
|
|
tprintf(T("Max res mem: %10ld pages %10ld bytes"),
|
2026-03-03 18:39:35 -07:00
|
|
|
|
usage.ru_maxrss, (usage.ru_maxrss * static_cast<long>(psize))));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
raw_notify(player,
|
2009-02-09 07:54:48 -08:00
|
|
|
|
tprintf(T("Page faults: %10ld hard %10ld soft %10ld swapouts"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_majflt, usage.ru_minflt, usage.ru_nswap));
|
|
|
|
|
|
raw_notify(player,
|
2009-02-08 20:43:31 -08:00
|
|
|
|
tprintf(T("Disk I/O: %10ld reads %10ld writes"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_inblock, usage.ru_oublock));
|
|
|
|
|
|
raw_notify(player,
|
2009-02-08 20:43:31 -08:00
|
|
|
|
tprintf(T("Network I/O: %10ld in %10ld out"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_msgrcv, usage.ru_msgsnd));
|
|
|
|
|
|
raw_notify(player,
|
2009-02-08 20:43:31 -08:00
|
|
|
|
tprintf(T("Context swi: %10ld vol %10ld forced %10ld sigs"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
usage.ru_nvcsw, usage.ru_nivcsw, usage.ru_nsignals));
|
|
|
|
|
|
raw_notify(player,
|
2008-12-27 18:37:01 -08:00
|
|
|
|
tprintf(T("Descs avail: %10d"), maxfds));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#endif // HAVE_GETRUSAGE
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2007-04-09 22:37:02 +00:00
|
|
|
|
// list_modules
|
|
|
|
|
|
//
|
2006-09-01 22:59:23 +00:00
|
|
|
|
//
|
2007-04-09 22:37:02 +00:00
|
|
|
|
static void list_modules(dbref executor)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(executor, M_("Modules:"));
|
2007-04-09 22:37:02 +00:00
|
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; ; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
MUX_MODULE_INFO ModuleInfo;
|
|
|
|
|
|
MUX_RESULT mr = mux_ModuleInfo(i, &ModuleInfo);
|
|
|
|
|
|
if ( MUX_FAILED(mr)
|
|
|
|
|
|
|| MUX_S_FALSE == mr)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
raw_notify(executor, tprintf(T("%s (%s)"), ModuleInfo.pName, ModuleInfo.bLoaded ? T("loaded") : T("unloaded")));
|
2007-04-09 22:37:02 +00:00
|
|
|
|
}
|
2007-09-19 22:16:30 -07:00
|
|
|
|
|
|
|
|
|
|
#ifdef STUB_SLAVE
|
|
|
|
|
|
{
|
2026-03-18 01:49:16 +00:00
|
|
|
|
mux_ISlaveControl *pISlaveControl = nullptr;
|
|
|
|
|
|
MUX_RESULT mr = mux_CreateInstance(CID_StubSlave, nullptr,
|
|
|
|
|
|
UseSlaveProcess, IID_ISlaveControl,
|
|
|
|
|
|
(void **)&pISlaveControl);
|
|
|
|
|
|
if (MUX_SUCCEEDED(mr) && nullptr != pISlaveControl)
|
2007-09-19 22:16:30 -07:00
|
|
|
|
{
|
2026-03-18 01:49:16 +00:00
|
|
|
|
for (i = 0; ; i++)
|
2007-09-19 22:16:30 -07:00
|
|
|
|
{
|
2026-03-18 01:49:16 +00:00
|
|
|
|
MUX_MODULE_INFO ModuleInfo;
|
|
|
|
|
|
mr = pISlaveControl->ModuleInfo(i, &ModuleInfo);
|
|
|
|
|
|
if ( MUX_FAILED(mr)
|
|
|
|
|
|
|| MUX_S_FALSE == mr)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2007-09-26 12:04:34 -07:00
|
|
|
|
|
2026-03-18 01:49:16 +00:00
|
|
|
|
raw_notify(executor, tprintf(T("%s (%s) by stubslave"), ModuleInfo.pName, ModuleInfo.bLoaded ? T("loaded") : T("unloaded")));
|
|
|
|
|
|
}
|
|
|
|
|
|
pISlaveControl->Release();
|
2007-09-19 22:16:30 -07:00
|
|
|
|
}
|
fix(stubslave): say so when @list modules cannot reach the slave (#1535)
list_modules() enumerates a second time through the stubslave under
STUB_SLAVE, printing each entry as "<name> (loaded) by stubslave". It
obtains the management interface with no else on failure, so the whole
slave section vanished silently and @list modules answered as though the
slave held nothing -- while the slave process demonstrably had the module
mapped. The operator could not tell "nothing is loaded there" from "I
could not ask", which on the release build is the only question this
command exists to answer about the slave.
It fails every time today. Measured on aarch64 with a throwaway game,
`module comsys_mod slave` in the config, and comsys_mod.so confirmed
present in /proc/<slave pid>/maps while the process ran:
Modules:
engine (loaded)
libmux (unloaded)
No slave line, no error. Instrumenting the path: list_modules creates a
second CID_StubSlave instance, Pipe_SendCallPacketAndWait succeeds, the
reply frame comes back with 0 of 8 bytes for cidProxy, and
mux_UnmarshalInterface reports MUX_E_CLASSNOTAVAILABLE (-3). So the pipe
round trip happens and returns nothing to unmarshal.
That defect is NOT fixed here. Repairing a repeat CreateInstance in the
marshalling layer is delicate work on a path with no test coverage that I
cannot validate on Windows, and it deserves its own change. This makes it
visible instead of invisible -- the same fail-loudly argument as #1512,
where a silent fall-through turned an unreachable path into wrong data.
After:
Modules:
engine (loaded)
libmux (unloaded)
Could not query the stubslave module list (error -3).
Uses T() to match the surrounding raw_notify calls; whether operator
diagnostics should be M_() is an #1419 question, not one to settle inside
a one-branch fix.
Textually inside #ifdef STUB_SLAVE, so a default build is unaffected.
Verified on a --enable-stubslave build: make test smoke route 1 passes
1509/1509, 316/316 dispatched.
Note for anyone running the suite on this configuration: route 2 hit an
intermittent SEGV at shutdown, after all 316 files dispatched and all 1509
assertions passed, and did not recur in three further runs. That is
#1433's character rather than anything this touches, and is reported
there; it is not caused by this change and is not fixed by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 06:37:33 -06:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Say so, rather than printing nothing (#1535).
|
|
|
|
|
|
//
|
|
|
|
|
|
// Without this the whole slave section vanished on failure, and
|
|
|
|
|
|
// @list modules answered as if the slave held no modules -- while
|
|
|
|
|
|
// the slave process demonstrably had them mapped. The operator
|
|
|
|
|
|
// could not tell "nothing is loaded there" from "I could not ask",
|
|
|
|
|
|
// which on the release build (--enable-stubslave) is the only
|
|
|
|
|
|
// question this command exists to answer about the slave.
|
|
|
|
|
|
//
|
|
|
|
|
|
// It fails every time today: the interface is created a second
|
|
|
|
|
|
// time here, the slave's reply frame comes back empty, and
|
|
|
|
|
|
// mux_UnmarshalInterface reports MUX_E_CLASSNOTAVAILABLE (-3).
|
|
|
|
|
|
// Measured on aarch64 with a module confirmed loaded in the slave
|
|
|
|
|
|
// via /proc/<pid>/maps. That defect is not fixed here -- this
|
|
|
|
|
|
// only stops it being invisible.
|
|
|
|
|
|
//
|
|
|
|
|
|
raw_notify(executor, tprintf(
|
|
|
|
|
|
T("Could not query the stubslave module list (error %d)."),
|
|
|
|
|
|
static_cast<int>(mr)));
|
|
|
|
|
|
}
|
2007-09-19 22:16:30 -07:00
|
|
|
|
}
|
|
|
|
|
|
#endif
|
2007-04-09 22:37:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
// list_rlevels
|
|
|
|
|
|
//
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
#ifdef REALITY_LVLS
|
|
|
|
|
|
static void list_rlevels(dbref player)
|
|
|
|
|
|
{
|
2026-07-28 11:37:23 -06:00
|
|
|
|
// Reality levels (#1667 Phase 4 C9): labeled freeform fields with
|
|
|
|
|
|
// mux_table name width for the level name.
|
|
|
|
|
|
//
|
|
|
|
|
|
static const size_t kRlevelNameCols = 20;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
int i;
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("Reality levels:"));
|
2007-03-14 07:40:08 +00:00
|
|
|
|
for (i = 0; i < mudconf.no_levels; ++i)
|
|
|
|
|
|
{
|
2026-07-28 11:37:23 -06:00
|
|
|
|
UTF8 line[LBUF_SIZE];
|
|
|
|
|
|
UTF8 valbuf[32];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, " ");
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(M_("Level")));
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, ": ");
|
|
|
|
|
|
pos = mux_table_append_ljust(line, sizeof(line), pos,
|
|
|
|
|
|
mudconf.reality_level[i].name, kRlevelNameCols);
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, " ");
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(M_("Value")));
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, ": ");
|
|
|
|
|
|
mux_sprintf(valbuf, sizeof(valbuf), T("0x%08x"),
|
|
|
|
|
|
mudconf.reality_level[i].value);
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(valbuf));
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, " ");
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(M_("Desc")));
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, ": ");
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(mudconf.reality_level[i].attr));
|
|
|
|
|
|
raw_notify(player, line);
|
2007-03-14 07:40:08 +00:00
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
raw_notify(player, M_("--Completed."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2006-11-27 05:25:42 +00:00
|
|
|
|
#endif // REALITY_LVLS
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// do_list: List information stored in internal structures.
|
|
|
|
|
|
//
|
|
|
|
|
|
#define LIST_ATTRIBUTES 1
|
|
|
|
|
|
#define LIST_COMMANDS 2
|
|
|
|
|
|
#define LIST_COSTS 3
|
|
|
|
|
|
#define LIST_FLAGS 4
|
|
|
|
|
|
#define LIST_FUNCTIONS 5
|
|
|
|
|
|
#define LIST_GLOBALS 6
|
|
|
|
|
|
#define LIST_ALLOCATOR 7
|
|
|
|
|
|
#define LIST_LOGGING 8
|
|
|
|
|
|
#define LIST_DF_FLAGS 9
|
|
|
|
|
|
#define LIST_PERMS 10
|
|
|
|
|
|
#define LIST_ATTRPERMS 11
|
|
|
|
|
|
#define LIST_OPTIONS 12
|
|
|
|
|
|
#define LIST_HASHSTATS 13
|
|
|
|
|
|
#define LIST_BUFTRACE 14
|
|
|
|
|
|
#define LIST_CONF_PERMS 15
|
|
|
|
|
|
#define LIST_SITEINFO 16
|
|
|
|
|
|
#define LIST_POWERS 17
|
|
|
|
|
|
#define LIST_SWITCHES 18
|
|
|
|
|
|
#define LIST_VATTRS 19
|
|
|
|
|
|
#define LIST_DB_STATS 20
|
|
|
|
|
|
#define LIST_PROCESS 21
|
|
|
|
|
|
#define LIST_BADNAMES 22
|
|
|
|
|
|
#define LIST_GUESTS 24
|
2007-04-09 22:37:02 +00:00
|
|
|
|
#define LIST_MODULES 25
|
2026-03-05 09:12:46 -07:00
|
|
|
|
#define LIST_CACHE 26
|
2026-03-18 08:38:44 -06:00
|
|
|
|
#define LIST_LUA 27
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef REALITY_LVLS
|
2026-03-18 08:38:44 -06:00
|
|
|
|
#define LIST_RLEVELS 28
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
NAMETAB list_names[] =
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("allocations"), 2, CA_WIZARD, LIST_ALLOCATOR},
|
|
|
|
|
|
{T("attr_permissions"), 5, CA_WIZARD, LIST_ATTRPERMS},
|
|
|
|
|
|
{T("attributes"), 2, CA_PUBLIC, LIST_ATTRIBUTES},
|
|
|
|
|
|
{T("bad_names"), 2, CA_WIZARD, LIST_BADNAMES},
|
|
|
|
|
|
{T("buffers"), 2, CA_WIZARD, LIST_BUFTRACE},
|
2026-03-05 09:12:46 -07:00
|
|
|
|
{T("cache"), 2, CA_WIZARD, LIST_CACHE},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("commands"), 3, CA_PUBLIC, LIST_COMMANDS},
|
|
|
|
|
|
{T("config_permissions"), 3, CA_GOD, LIST_CONF_PERMS},
|
|
|
|
|
|
{T("costs"), 3, CA_PUBLIC, LIST_COSTS},
|
|
|
|
|
|
{T("db_stats"), 2, CA_WIZARD, LIST_DB_STATS},
|
|
|
|
|
|
{T("default_flags"), 1, CA_PUBLIC, LIST_DF_FLAGS},
|
|
|
|
|
|
{T("flags"), 2, CA_PUBLIC, LIST_FLAGS},
|
|
|
|
|
|
{T("functions"), 2, CA_PUBLIC, LIST_FUNCTIONS},
|
|
|
|
|
|
{T("globals"), 2, CA_WIZARD, LIST_GLOBALS},
|
|
|
|
|
|
{T("hashstats"), 1, CA_WIZARD, LIST_HASHSTATS},
|
|
|
|
|
|
{T("logging"), 1, CA_GOD, LIST_LOGGING},
|
2026-03-18 08:38:44 -06:00
|
|
|
|
{T("lua"), 2, CA_PUBLIC, LIST_LUA},
|
2007-04-09 22:37:02 +00:00
|
|
|
|
{T("modules"), 1, CA_WIZARD, LIST_MODULES},
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("options"), 1, CA_PUBLIC, LIST_OPTIONS},
|
|
|
|
|
|
{T("permissions"), 2, CA_WIZARD, LIST_PERMS},
|
|
|
|
|
|
{T("powers"), 2, CA_WIZARD, LIST_POWERS},
|
|
|
|
|
|
{T("process"), 2, CA_WIZARD, LIST_PROCESS},
|
|
|
|
|
|
{T("site_information"), 2, CA_WIZARD, LIST_SITEINFO},
|
|
|
|
|
|
{T("switches"), 2, CA_PUBLIC, LIST_SWITCHES},
|
|
|
|
|
|
{T("user_attributes"), 1, CA_WIZARD, LIST_VATTRS},
|
|
|
|
|
|
{T("guests"), 2, CA_WIZARD, LIST_GUESTS},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef REALITY_LVLS
|
2007-03-14 22:33:04 +00:00
|
|
|
|
{T("rlevels"), 3, CA_PUBLIC, LIST_RLEVELS},
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#endif
|
2022-03-13 13:16:46 -06:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_list(dbref executor, dbref caller, dbref enactor, int eval, const int key,
|
|
|
|
|
|
UTF8 *arg, const UTF8 *cargs[], const int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(caller);
|
|
|
|
|
|
UNUSED_PARAMETER(enactor);
|
2006-09-06 06:17:46 +00:00
|
|
|
|
UNUSED_PARAMETER(eval);
|
2007-09-02 13:48:10 -07:00
|
|
|
|
UNUSED_PARAMETER(key);
|
|
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2022-03-11 12:36:37 -07:00
|
|
|
|
string_token st(arg, T(" \t=,"));
|
|
|
|
|
|
UTF8* s_option = st.parse();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
int flagvalue;
|
|
|
|
|
|
if (!search_nametab(executor, list_names, arg, &flagvalue))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (flagvalue == -1)
|
|
|
|
|
|
{
|
2007-04-09 05:34:50 +00:00
|
|
|
|
display_nametab(executor, list_names, T("Unknown option. Use one of"), true);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2006-11-13 06:50:20 +00:00
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (flagvalue)
|
|
|
|
|
|
{
|
|
|
|
|
|
case LIST_ALLOCATOR:
|
|
|
|
|
|
list_bufstats(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_BUFTRACE:
|
|
|
|
|
|
list_buftrace(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_ATTRIBUTES:
|
|
|
|
|
|
list_attrtable(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_COMMANDS:
|
|
|
|
|
|
list_cmdtable(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_SWITCHES:
|
|
|
|
|
|
list_cmdswitches(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_COSTS:
|
|
|
|
|
|
list_costs(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_OPTIONS:
|
|
|
|
|
|
list_options(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_HASHSTATS:
|
|
|
|
|
|
list_hashstats(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_SITEINFO:
|
|
|
|
|
|
list_siteinfo(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_FLAGS:
|
|
|
|
|
|
display_flagtab(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_FUNCTIONS:
|
|
|
|
|
|
list_functable(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_GLOBALS:
|
|
|
|
|
|
interp_nametab(executor, enable_names, mudconf.control_flags,
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("Global parameters:"), T("enabled"), T("disabled"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case LIST_DF_FLAGS:
|
|
|
|
|
|
list_df_flags(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_PERMS:
|
|
|
|
|
|
list_cmdaccess(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_CONF_PERMS:
|
|
|
|
|
|
list_cf_access(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_POWERS:
|
|
|
|
|
|
display_powertab(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_ATTRPERMS:
|
|
|
|
|
|
list_attraccess(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_VATTRS:
|
2022-03-11 12:36:37 -07:00
|
|
|
|
s_option = st.parse();
|
2006-09-01 22:59:23 +00:00
|
|
|
|
list_vattrs(executor, s_option);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_LOGGING:
|
|
|
|
|
|
interp_nametab(executor, logoptions_nametab, mudconf.log_options,
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("Events Logged:"), T("enabled"), T("disabled"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
interp_nametab(executor, logdata_nametab, mudconf.log_info,
|
2007-03-14 22:33:04 +00:00
|
|
|
|
T("Information Logged:"), T("yes"), T("no"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case LIST_DB_STATS:
|
2026-03-05 13:17:01 -07:00
|
|
|
|
list_cache_stats(executor);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case LIST_PROCESS:
|
|
|
|
|
|
list_process(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LIST_BADNAMES:
|
2007-03-14 22:33:04 +00:00
|
|
|
|
badname_list(executor, T("Disallowed names:"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case LIST_GUESTS:
|
|
|
|
|
|
Guest.ListAll(executor);
|
|
|
|
|
|
break;
|
2007-04-09 22:37:02 +00:00
|
|
|
|
case LIST_MODULES:
|
|
|
|
|
|
list_modules(executor);
|
|
|
|
|
|
break;
|
2026-03-05 09:12:46 -07:00
|
|
|
|
case LIST_CACHE:
|
|
|
|
|
|
list_cache_stats(executor);
|
|
|
|
|
|
break;
|
2026-03-18 08:38:44 -06:00
|
|
|
|
case LIST_LUA:
|
|
|
|
|
|
if (nullptr != mudstate.pILuaControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t nCalls, nErrors, nInsnHits, nMemHits, nBytes;
|
2026-03-18 09:14:01 -06:00
|
|
|
|
size_t nCacheHits, nCacheMisses, nCacheEntries;
|
2026-03-18 08:38:44 -06:00
|
|
|
|
mudstate.pILuaControl->GetStats(&nCalls, &nErrors,
|
2026-03-18 09:14:01 -06:00
|
|
|
|
&nInsnHits, &nMemHits, &nBytes,
|
|
|
|
|
|
&nCacheHits, &nCacheMisses, &nCacheEntries);
|
2026-07-27 12:59:45 +00:00
|
|
|
|
notify(executor, M_("Lua module loaded (Lua 5.4)."));
|
2026-07-25 22:44:45 -06:00
|
|
|
|
notify(executor, tprintf(T(" Lua JIT: %s"),
|
feat(lua/jit): default lua_jit on (#1325)
The gates in #1325 are met and the closing of #1433 was the last one:
- The differential harness executes every supported shape -- 140
chunks, EXEC requiring lua_run_ok to advance, declines all deliberate
(os.time, two pins, select arity).
- All three loop forms run under an aborting instruction budget whose
exhaustion surfaces the interpreter's own error, verbatim (#1732).
- The compiled path wins or ties every benched shape; loops beat the
VM's marginal per-iteration cost after #1743 (#1741).
- #1433 closed unreproduced: three machines, thousands of process
runs, including the original commit on the machine that first saw it.
- Windows gates closed by the maintainer.
A chunk the compiler cannot honestly run declines to the interpreter,
so OFF now buys nothing but the slower path; lua_jit=0 remains the
diagnostic switch. With the default on, ordinary smoke exercises the
engaged path -- TC006 asserts lua_run_ok advances under the default
config -- and the explicit lua_jit-0 cases keep the gate itself tested.
smoke 1561/0 with the JIT engaged; luajit harness 140 chunks, 0 wrong;
full make test clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 21:16:55 -06:00
|
|
|
|
mudconf.lua_jit ? T("enabled (default)") : T("disabled")));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
notify(executor, tprintf(T(" Calls: %zu"), nCalls));
|
|
|
|
|
|
notify(executor, tprintf(T(" Errors: %zu"), nErrors));
|
|
|
|
|
|
notify(executor, tprintf(T(" Insn limit hits: %zu"), nInsnHits));
|
|
|
|
|
|
notify(executor, tprintf(T(" Mem limit hits: %zu"), nMemHits));
|
|
|
|
|
|
notify(executor, tprintf(T(" Memory in use: %zu bytes"), nBytes));
|
2026-03-18 09:14:01 -06:00
|
|
|
|
notify(executor, tprintf(T(" Cache entries: %zu"), nCacheEntries));
|
|
|
|
|
|
notify(executor, tprintf(T(" Cache hits: %zu"), nCacheHits));
|
|
|
|
|
|
notify(executor, tprintf(T(" Cache misses: %zu"), nCacheMisses));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Lua module is not loaded."));
|
2026-03-18 08:38:44 -06:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
#ifdef REALITY_LVLS
|
|
|
|
|
|
case LIST_RLEVELS:
|
|
|
|
|
|
list_rlevels(executor);
|
|
|
|
|
|
break;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_assert(const dbref executor, const dbref caller, dbref enactor, const int eval, int key,
|
|
|
|
|
|
int nargs, UTF8 *arg1, UTF8 *command, const UTF8 *cargs[], const int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(key);
|
2007-09-02 21:44:11 -07:00
|
|
|
|
UNUSED_PARAMETER(nargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2006-12-27 19:26:46 +00:00
|
|
|
|
if (!xlate(arg1))
|
|
|
|
|
|
{
|
|
|
|
|
|
break_called = true;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if ( nullptr != command
|
2006-12-27 19:26:46 +00:00
|
|
|
|
&& '\0' != command[0])
|
|
|
|
|
|
{
|
2012-07-10 09:48:56 -07:00
|
|
|
|
if (key & BREAK_INLINE)
|
|
|
|
|
|
{
|
|
|
|
|
|
process_command(executor, caller, enactor, eval, false, command, cargs, ncargs);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CLinearTimeAbsolute lta;
|
|
|
|
|
|
wait_que(executor, caller, enactor, eval, false, lta, NOTHING, 0,
|
|
|
|
|
|
command,
|
|
|
|
|
|
ncargs, cargs,
|
|
|
|
|
|
mudstate.global_regs);
|
|
|
|
|
|
}
|
2006-12-27 19:26:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_break(const dbref executor, const dbref caller, const dbref enactor, const int eval, int key,
|
|
|
|
|
|
const int nargs, UTF8 *arg1, UTF8 *command, const UTF8 *cargs[], const int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(key);
|
2007-09-02 21:44:11 -07:00
|
|
|
|
UNUSED_PARAMETER(nargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2006-12-27 19:26:46 +00:00
|
|
|
|
if (xlate(arg1))
|
|
|
|
|
|
{
|
|
|
|
|
|
break_called = true;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if ( nullptr != command
|
2006-12-27 19:26:46 +00:00
|
|
|
|
&& '\0' != command[0])
|
|
|
|
|
|
{
|
2012-07-10 09:48:56 -07:00
|
|
|
|
if (key & BREAK_INLINE)
|
|
|
|
|
|
{
|
|
|
|
|
|
process_command(executor, caller, enactor, eval, false, command, cargs, ncargs);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
CLinearTimeAbsolute lta;
|
|
|
|
|
|
wait_que(executor, caller, enactor, eval, false, lta, NOTHING, 0,
|
|
|
|
|
|
command,
|
|
|
|
|
|
ncargs, cargs,
|
|
|
|
|
|
mudstate.global_regs);
|
|
|
|
|
|
}
|
2006-12-27 19:26:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// do_icmd: Ignore or disable commands on a per-player or per-room basis.
|
|
|
|
|
|
// Used with express permission of RhostMUSH developers.
|
|
|
|
|
|
// Bludgeoned into MUX by Jake Nelson 7/2002.
|
|
|
|
|
|
//
|
2006-12-27 17:53:42 +00:00
|
|
|
|
void do_icmd(dbref player, dbref cause, dbref enactor, int eval, int key,
|
2007-09-02 22:02:33 -07:00
|
|
|
|
UTF8 *name, UTF8 *args[], int nargs, const UTF8 *cargs[], int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2006-12-27 17:53:42 +00:00
|
|
|
|
UNUSED_PARAMETER(eval);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
UNUSED_PARAMETER(cause);
|
|
|
|
|
|
UNUSED_PARAMETER(enactor);
|
2007-09-02 22:02:33 -07:00
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
CMDENT *cmdp;
|
2022-03-13 13:16:46 -06:00
|
|
|
|
UTF8 *pt3, *atrpt;
|
|
|
|
|
|
int aflags;
|
|
|
|
|
|
dbref target = NOTHING, aowner;
|
|
|
|
|
|
bool set;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
int loc_set = -1;
|
|
|
|
|
|
if ( key == ICMD_IROOM
|
|
|
|
|
|
|| key == ICMD_DROOM
|
|
|
|
|
|
|| key == ICMD_CROOM
|
|
|
|
|
|
|| key == ICMD_LROOM
|
|
|
|
|
|
|| key == ICMD_LALLROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (key != ICMD_LALLROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
target = match_thing_quiet(player, name);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( key != ICMD_LALLROOM
|
|
|
|
|
|
&& ( !Good_obj(target)
|
|
|
|
|
|
|| !( isRoom(target)
|
|
|
|
|
|
|| isThing(target))))
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Bad Location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key == ICMD_CROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
atr_clr(target, A_CMDCHECK);
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Location - All cleared."));
|
|
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_LROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atrpt1 = LBuf_Adopt(atr_get("do_icmd.4060", target, A_CMDCHECK, &aowner, &aflags));
|
|
|
|
|
|
if (*atrpt1.get())
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("Location CmdCheck attribute is:"));
|
2026-04-05 18:34:51 -06:00
|
|
|
|
notify(player, atrpt1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("Location CmdCheck attribute is empty."));
|
2026-04-05 18:34:51 -06:00
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_LALLROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
target = Location(player);
|
|
|
|
|
|
if ( !Good_obj(target)
|
|
|
|
|
|
|| Going(target)
|
|
|
|
|
|
|| isPlayer(target))
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Bad Location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("Scanning all locations and zones from your current location:"));
|
2022-03-13 13:16:46 -06:00
|
|
|
|
bool bFound = false;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atrpt2 = LBuf_Adopt(atr_get("do_icmd.4086", target, A_CMDCHECK, &aowner, &aflags));
|
|
|
|
|
|
if (*atrpt2.get())
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(player, tprintf(T("%c --- At %s(#%d) :"),
|
|
|
|
|
|
(Zone(target) == target ? '*' : ' '), Name(target), target));
|
|
|
|
|
|
notify(player, atrpt2);
|
|
|
|
|
|
bFound = true;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (Zone(target) != target)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
dbref zone = Zone(target);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( Good_obj(zone)
|
|
|
|
|
|
&& ( isRoom(zone)
|
|
|
|
|
|
|| isThing(zone)))
|
|
|
|
|
|
{
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atrpt3 = LBuf_Adopt(atr_get("do_icmd.4102", zone, A_CMDCHECK, &aowner, &aflags));
|
|
|
|
|
|
if (*atrpt3.get())
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(player, tprintf(T("%c z-- At %s(#%d) :"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
'*', Name(zone), zone));
|
2026-04-05 18:34:51 -06:00
|
|
|
|
notify(player, atrpt3);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
bFound = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!bFound)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Location - No icmds found at current location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_IROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
loc_set = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_DROOM)
|
|
|
|
|
|
{
|
|
|
|
|
|
loc_set = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (loc_set == -1 )
|
|
|
|
|
|
{
|
|
|
|
|
|
target = lookup_player(player, name, false);
|
|
|
|
|
|
if (!Good_obj(target) || God(target))
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Bad player."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((key == ICMD_OFF) || (key == ICMD_CLEAR))
|
|
|
|
|
|
{
|
|
|
|
|
|
s_Flags(target, FLAG_WORD3, Flags3(target) & ~CMDCHECK);
|
|
|
|
|
|
if (key == ICMD_CLEAR)
|
|
|
|
|
|
{
|
|
|
|
|
|
atr_clr(target, A_CMDCHECK);
|
|
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: All cleared."));
|
|
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_ON)
|
|
|
|
|
|
{
|
|
|
|
|
|
s_Flags(target, FLAG_WORD3, Flags3(target) | CMDCHECK);
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Activated."));
|
|
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (key == ICMD_CHECK)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (CmdCheck(target))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("CmdCheck is active."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("CmdCheck is not active."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
{
|
2026-04-05 18:34:51 -06:00
|
|
|
|
LBuf atrpt4 = LBuf_Adopt(atr_get("do_icmd.4166", target, A_CMDCHECK, &aowner, &aflags));
|
|
|
|
|
|
if (*atrpt4.get())
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("CmdCheck attribute is:"));
|
2026-04-05 18:34:51 -06:00
|
|
|
|
notify(player, atrpt4);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(player, M_("CmdCheck attribute is empty."));
|
2026-04-05 18:34:51 -06:00
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
key = loc_set;
|
|
|
|
|
|
}
|
2007-03-14 00:55:08 +00:00
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
auto message = T("");
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf buff1 = LBuf_Src("do_icmd");
|
2022-03-13 13:16:46 -06:00
|
|
|
|
for (int x = 0; x < nargs; x++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
// Lowercase the argument (Unicode-aware).
|
|
|
|
|
|
//
|
|
|
|
|
|
size_t nLower;
|
|
|
|
|
|
UTF8 *pLower = mux_strlwr(args[x], nLower);
|
|
|
|
|
|
if (nLower >= LBUF_SIZE)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
nLower = LBUF_SIZE - 1;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
memcpy(buff1, pLower, nLower);
|
|
|
|
|
|
buff1[nLower] = '\0';
|
|
|
|
|
|
UTF8* pt1;
|
|
|
|
|
|
UTF8* pt2;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( buff1[0] == '!'
|
|
|
|
|
|
&& buff1[1] != '\0')
|
|
|
|
|
|
{
|
|
|
|
|
|
pt1 = buff1 + 1;
|
|
|
|
|
|
set = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
pt1 = buff1;
|
|
|
|
|
|
set = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*pt1)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
bool bHome;
|
2007-03-14 22:33:04 +00:00
|
|
|
|
if (!string_compare(pt1, T("home")))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
bHome = true;
|
2018-10-03 17:54:51 +00:00
|
|
|
|
cmdp = nullptr;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
bHome = false;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
size_t nPt1 = strlen(reinterpret_cast<char*>(pt1));
|
|
|
|
|
|
auto it_pt1 = mudstate.command_htab.find(std::vector<UTF8>(pt1, pt1 + nPt1));
|
|
|
|
|
|
cmdp = (it_pt1 != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_pt1->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (cmdp || bHome)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
bool bColon = false;
|
2007-03-07 05:14:20 +00:00
|
|
|
|
atrpt = atr_get("do_icmd.4223", target, A_CMDCHECK, &aowner, &aflags);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (cmdp)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
aflags = static_cast<int>(strlen(reinterpret_cast<char*>(cmdp->cmdname)));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
bColon = ( aflags == 1
|
|
|
|
|
|
&& *(cmdp->cmdname) == ':');
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
aflags = 4;
|
|
|
|
|
|
}
|
2022-03-13 13:16:46 -06:00
|
|
|
|
UTF8* pt5 = atrpt;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
while (pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmdp)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bColon)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
pt1 = reinterpret_cast<UTF8*>(strstr(reinterpret_cast<char*>(pt5), "::"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
pt1++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
pt1 = reinterpret_cast<UTF8*>(strstr(reinterpret_cast<char*>(pt5), reinterpret_cast<char*>(cmdp->cmdname)));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
pt1 = reinterpret_cast<UTF8*>(strstr(reinterpret_cast<char*>(pt5), "home"));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
if ( pt1
|
|
|
|
|
|
&& (pt1 > atrpt)
|
|
|
|
|
|
&& (*(pt1 - 1) == ':')
|
|
|
|
|
|
&& ( mux_isspace(*(pt1 + aflags))
|
|
|
|
|
|
|| !*(pt1 + aflags)))
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (*pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
pt5 = pt1 + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2018-10-03 17:54:51 +00:00
|
|
|
|
pt1 = nullptr;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (set)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmdp)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
pt3 = tprintf(T(" %d:%s"), key + 1, cmdp->cmdname);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
pt3 = tprintf(T(" %d:home"), key + 1);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const size_t natrpt = strlen(reinterpret_cast<char*>(atrpt));
|
|
|
|
|
|
const size_t npt3 = strlen(reinterpret_cast<char*>(pt3));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ((natrpt + npt3) < LBUF_SIZE - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
mux_strncpy(atrpt + natrpt, pt3, LBUF_SIZE-natrpt-1);
|
|
|
|
|
|
atr_add_raw(target, A_CMDCHECK, atrpt);
|
|
|
|
|
|
if ( loc_set == -1 )
|
|
|
|
|
|
{
|
|
|
|
|
|
s_Flags(target, FLAG_WORD3, Flags3(target) | CMDCHECK);
|
|
|
|
|
|
}
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Set");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Command already present");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pt1)
|
|
|
|
|
|
{
|
|
|
|
|
|
pt2 = pt1 - 1;
|
|
|
|
|
|
while ((pt2 > atrpt) && !mux_isspace(*pt2))
|
|
|
|
|
|
{
|
|
|
|
|
|
pt2--;
|
|
|
|
|
|
}
|
2022-03-13 13:16:46 -06:00
|
|
|
|
size_t y = pt2 - atrpt + 1;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
// Save the char that'll be nulled by mux_strncpy.
|
|
|
|
|
|
// (Even though it may be unneeded by this point.)
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const UTF8 cSave = buff1[y];
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mux_strncpy(buff1, atrpt, y);
|
|
|
|
|
|
buff1[y] = cSave;
|
|
|
|
|
|
if (y == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
*atrpt = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
*(atrpt + y) = '\0';
|
|
|
|
|
|
pt2 = pt1 + aflags;
|
|
|
|
|
|
if (*pt2)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (*pt2 && mux_isspace(*pt2))
|
|
|
|
|
|
{
|
|
|
|
|
|
pt2++;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (*pt2)
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const size_t natrpt = strlen(reinterpret_cast<char*>(atrpt));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mux_strncpy(atrpt + natrpt, pt2, LBUF_SIZE-natrpt-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((y > 1) && !*pt2)
|
|
|
|
|
|
{
|
|
|
|
|
|
pt2 = atrpt + y;
|
|
|
|
|
|
while ((pt2 > atrpt) && mux_isspace(*pt2))
|
|
|
|
|
|
{
|
|
|
|
|
|
pt2--;
|
|
|
|
|
|
}
|
|
|
|
|
|
*(pt2 + 1) = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((y == 1) && !*pt2)
|
|
|
|
|
|
{
|
|
|
|
|
|
atr_clr(target, A_CMDCHECK);
|
|
|
|
|
|
if (loc_set == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
s_Flags(target, FLAG_WORD3, Flags3(target) & ~CMDCHECK);
|
|
|
|
|
|
}
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Cleared");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
atr_add_raw(target, A_CMDCHECK, atrpt);
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Cleared");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Command not present");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
free_lbuf(atrpt);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2007-03-14 22:33:04 +00:00
|
|
|
|
message = T("Bad command");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(player, tprintf(T("@icmd:%s %s."), (loc_set == -1) ? T("") : T(" Location -"), message));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(player, M_("@icmd: Done."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// do_train: show someone else in the same room what code you're entering and the result
|
|
|
|
|
|
// From RhostMUSH, changed to use notify_all_from_inside.
|
|
|
|
|
|
//
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_train(const dbref executor, const dbref caller, const dbref enactor, const int eval, const int key, UTF8 *string, const UTF8 *cargs[], int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(key);
|
2007-09-02 13:48:10 -07:00
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
if (0 < mudstate.train_nest_lev)
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Train cannot be used to teach command, train."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
mudstate.train_nest_lev++;
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const dbref loc = Location(executor);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!Good_obj(loc))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Bad location."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.train_nest_lev--;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( !string
|
|
|
|
|
|
|| !*string)
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify(executor, M_("Train requires an argument."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.train_nest_lev--;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify_all_from_inside(loc, executor, tprintf(T("%s types -=> %s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
Moniker(executor), string));
|
2018-10-03 17:54:51 +00:00
|
|
|
|
process_command(executor, caller, enactor, eval, true, string, nullptr, 0);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudstate.train_nest_lev--;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_moniker(const dbref executor, const dbref caller, const dbref enactor, const int eval, const int key,
|
|
|
|
|
|
int nargs, UTF8 *name, UTF8 *instr, const UTF8 *cargs[], int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(caller);
|
|
|
|
|
|
UNUSED_PARAMETER(enactor);
|
2007-09-01 23:47:27 -07:00
|
|
|
|
UNUSED_PARAMETER(eval);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
UNUSED_PARAMETER(key);
|
2007-09-02 21:44:11 -07:00
|
|
|
|
UNUSED_PARAMETER(nargs);
|
|
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const dbref thing = match_thing(executor, name);
|
2006-11-13 06:50:20 +00:00
|
|
|
|
if (!Good_obj(thing))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2006-11-13 06:50:20 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!Controls(executor, thing))
|
|
|
|
|
|
{
|
|
|
|
|
|
notify(executor, NOPERM_MESSAGE);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-10-03 17:54:51 +00:00
|
|
|
|
if ( instr == nullptr
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|| instr[0] == '\0')
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify_quiet(executor, M_("Moniker cleared."));
|
2018-10-03 17:54:51 +00:00
|
|
|
|
s_Moniker(thing, nullptr);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
s_Moniker(thing, instr);
|
|
|
|
|
|
if ( !Quiet(executor)
|
|
|
|
|
|
&& !Quiet(thing))
|
|
|
|
|
|
{
|
2026-07-27 11:49:19 +00:00
|
|
|
|
notify_quiet(executor, M_("Moniker set."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
set_modified(thing);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// do_hook: run softcode before or after running a hardcode command, or
|
|
|
|
|
|
// softcode access. Original idea from TinyMUSH 3, code from RhostMUSH.
|
|
|
|
|
|
// Used with express permission of RhostMUSH developers.
|
|
|
|
|
|
// Bludgeoned into MUX by Jake Nelson 7/2002.
|
|
|
|
|
|
//
|
2007-03-14 00:55:08 +00:00
|
|
|
|
static void show_hook(UTF8 *bf, UTF8 *bfptr, int key)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_BEFORE)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("before "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_AFTER)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("after "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_PERMIT)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("permit "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_IGNORE)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("ignore "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_IGSWITCH)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("igswitch "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_AFAIL)
|
2007-03-14 22:33:04 +00:00
|
|
|
|
safe_str(T("afail "), bf, &bfptr);
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_ARGS)
|
2007-11-03 21:34:30 -07:00
|
|
|
|
safe_str(T("args "), bf, &bfptr);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
*bfptr = '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-28 11:37:23 -06:00
|
|
|
|
// @hook list row (#1667 Phase 4 C7): command 32 + " | " + mask freeform.
|
|
|
|
|
|
// Single-character aliases keep a 1-letter tag and a 30-col description.
|
|
|
|
|
|
//
|
|
|
|
|
|
static const size_t kHookCmdCols = 32;
|
|
|
|
|
|
static const size_t kHookTagCmdCols = 30;
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
static void hook_loop(const dbref executor, CMDENT *cmdp, UTF8 *s_ptr, UTF8 *s_ptrbuff)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
show_hook(s_ptrbuff, s_ptr, HOOKMASK(cmdp->flags));
|
2007-03-14 00:55:08 +00:00
|
|
|
|
const UTF8 *pCmd = cmdp->cmdname;
|
2026-07-28 11:37:23 -06:00
|
|
|
|
UTF8 tag = '\0';
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( pCmd[0] != '\0'
|
|
|
|
|
|
&& pCmd[1] == '\0')
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (pCmd[0])
|
|
|
|
|
|
{
|
|
|
|
|
|
case '"':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'S';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘\"’ hook on ‘say’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case ':':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'P';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘:’ hook on ‘pose’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case ';':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'P';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘;’ hook on ‘pose’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case '\\':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'E';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘\\\\’ hook on ‘@emit’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case '#':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'F';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘#’ hook on ‘@force’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case '&':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'V';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘&’ hook on ‘@set’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case '-':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'M';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘-’ hook on ‘@mail’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case '~':
|
2026-07-28 11:37:23 -06:00
|
|
|
|
tag = 'M';
|
2026-07-26 21:52:48 -06:00
|
|
|
|
pCmd = T("(‘~’ hook on ‘@mail’)");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-28 11:37:23 -06:00
|
|
|
|
|
|
|
|
|
|
UTF8 line[LBUF_SIZE];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
if ('\0' != tag)
|
|
|
|
|
|
{
|
|
|
|
|
|
UTF8 tagbuf[4];
|
|
|
|
|
|
tagbuf[0] = tag;
|
|
|
|
|
|
tagbuf[1] = ' ';
|
|
|
|
|
|
tagbuf[2] = '\0';
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(tagbuf));
|
|
|
|
|
|
pos = mux_table_append_ljust(line, sizeof(line), pos,
|
|
|
|
|
|
pCmd, kHookTagCmdCols);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
pos = mux_table_append_ljust(line, sizeof(line), pos,
|
|
|
|
|
|
pCmd, kHookCmdCols);
|
|
|
|
|
|
}
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos, " | ");
|
|
|
|
|
|
pos = mux_table_append_bytes(line, sizeof(line), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(s_ptrbuff));
|
|
|
|
|
|
notify(executor, line);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 13:16:46 -06:00
|
|
|
|
void do_hook(const dbref executor, const dbref caller, const dbref enactor, const int eval, int key, UTF8 *name, const UTF8 *cargs[], int ncargs)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
UNUSED_PARAMETER(caller);
|
|
|
|
|
|
UNUSED_PARAMETER(enactor);
|
2006-09-06 06:17:46 +00:00
|
|
|
|
UNUSED_PARAMETER(eval);
|
2007-09-02 13:48:10 -07:00
|
|
|
|
UNUSED_PARAMETER(cargs);
|
|
|
|
|
|
UNUSED_PARAMETER(ncargs);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
2022-03-11 14:36:04 -07:00
|
|
|
|
bool negate;
|
2022-03-13 13:16:46 -06:00
|
|
|
|
UTF8 *s_ptr, *s_ptrbuff, *p;
|
2007-03-12 08:15:29 +00:00
|
|
|
|
const UTF8 *q;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
auto* cmdp = static_cast<CMDENT*>(nullptr);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|
|
|
|
|
|
if ( ( key
|
2012-03-15 08:20:40 -07:00
|
|
|
|
&& !(key & CEF_HOOK_LIST))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|| ( ( !key
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|| (key & CEF_HOOK_LIST))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
&& *name))
|
|
|
|
|
|
{
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
size_t nName = strlen(reinterpret_cast<char*>(name));
|
|
|
|
|
|
auto it_name = mudstate.command_htab.find(std::vector<UTF8>(name, name + nName));
|
|
|
|
|
|
cmdp = (it_name != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_name->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if (!cmdp)
|
|
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(executor, M_("@hook: Non-existent command name given."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if ( (key & CEF_HOOK_CLEAR)
|
|
|
|
|
|
&& (key & CEF_HOOK_LIST))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-07-27 12:38:40 +00:00
|
|
|
|
notify(executor, M_("@hook: Incompatible switches."));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & CEF_HOOK_CLEAR)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
negate = true;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
key = ~CEF_HOOK_CLEAR & key;
|
|
|
|
|
|
key = ~SW_MULTIPLE & key;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
negate = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (key & (CEF_HOOK_BEFORE|CEF_HOOK_AFTER|CEF_HOOK_PERMIT|CEF_HOOK_IGNORE|CEF_HOOK_IGSWITCH|CEF_HOOK_AFAIL|CEF_HOOK_ARGS))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (negate)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
cmdp->flags = cmdp->flags & ~key;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2022-03-13 13:16:46 -06:00
|
|
|
|
cmdp->flags = cmdp->flags | key;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|
|
|
|
|
|
if (cmdp->flags)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf hookbuf = LBuf_Src("@hook");
|
|
|
|
|
|
s_ptr = s_ptrbuff = hookbuf;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
show_hook(s_ptrbuff, s_ptr, HOOKMASK(cmdp->flags));
|
2026-07-26 21:52:48 -06:00
|
|
|
|
notify(executor, tprintf(T("@hook: New mask for ‘%s’ -> %s"), cmdp->cmdname, s_ptrbuff));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-26 21:52:48 -06:00
|
|
|
|
notify(executor, tprintf(T("@hook: New mask for ‘%s’ is empty."), cmdp->cmdname));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-03-15 08:20:40 -07:00
|
|
|
|
|
|
|
|
|
|
if ( (key & CEF_HOOK_LIST)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
|| !key)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmdp)
|
|
|
|
|
|
{
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (cmdp->flags)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf hookbuf = LBuf_Src("@hook");
|
|
|
|
|
|
s_ptr = s_ptrbuff = hookbuf;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
show_hook(s_ptrbuff, s_ptr, HOOKMASK(cmdp->flags));
|
2026-07-26 21:52:48 -06:00
|
|
|
|
notify(executor, tprintf(T("@hook: Mask for hashed command ‘%s’ -> %s"), cmdp->cmdname, s_ptrbuff));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-07-26 21:52:48 -06:00
|
|
|
|
notify(executor, tprintf(T("@hook: Mask for hashed command ‘%s’ is empty."), cmdp->cmdname));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%.32s-+-%s"),
|
2022-03-11 14:36:04 -07:00
|
|
|
|
"--------------------------------",
|
|
|
|
|
|
"--------------------------------------------"));
|
2026-07-28 11:37:23 -06:00
|
|
|
|
{
|
|
|
|
|
|
UTF8 header[LBUF_SIZE];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
pos = mux_table_append_ljust(header, sizeof(header), pos,
|
|
|
|
|
|
M_("Built-in Command"), kHookCmdCols);
|
|
|
|
|
|
pos = mux_table_append_bytes(header, sizeof(header), pos, " | ");
|
|
|
|
|
|
pos = mux_table_append_bytes(header, sizeof(header), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(M_("Hook Mask Values")));
|
|
|
|
|
|
notify(executor, header);
|
|
|
|
|
|
}
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%.32s-+-%s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
"--------------------------------",
|
|
|
|
|
|
"--------------------------------------------"));
|
2022-03-11 14:36:04 -07:00
|
|
|
|
bool found = false;
|
Migrate ~55 alloc_lbuf/free_lbuf sites in large engine files to LBuf RAII
Fourth wave: ast (11), funceval (10), funceval2 (7), comsys (3),
speech (10), set (6), engine (7), command (10). Covers the NOEVAL
handlers (cand/cor/if/switch/iter), function evaluators (ifelse,
letq, objeval, sortby, munge, while, sandbox), notify_check message
buffers, and command dispatch paths. Buffers stored in fargs[]
arrays, returned through output pointers, or used in ping-pong swap
patterns are left manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:14:49 -06:00
|
|
|
|
LBuf hookbuf3 = LBuf_Src("@hook");
|
|
|
|
|
|
s_ptr = s_ptrbuff = hookbuf3;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (CMDENT_NO_ARG* cmdp2 = command_table_no_arg; cmdp2->cmdname; cmdp2++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
s_ptrbuff[0] = '\0';
|
|
|
|
|
|
s_ptr = s_ptrbuff;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (0 != HOOKMASK(cmdp2->flags))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
hook_loop(executor, reinterpret_cast<CMDENT*>(cmdp2), s_ptr, s_ptrbuff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (CMDENT_ONE_ARG* cmdp2 = command_table_one_arg; cmdp2->cmdname; cmdp2++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
s_ptrbuff[0] = '\0';
|
|
|
|
|
|
s_ptr = s_ptrbuff;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (0 != HOOKMASK(cmdp2->flags))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
hook_loop(executor, reinterpret_cast<CMDENT*>(cmdp2), s_ptr, s_ptrbuff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (CMDENT_TWO_ARG* cmdp2 = command_table_two_arg; cmdp2->cmdname; cmdp2++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
s_ptrbuff[0] = '\0';
|
|
|
|
|
|
s_ptr = s_ptrbuff;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (0 != HOOKMASK(cmdp2->flags))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
hook_loop(executor, reinterpret_cast<CMDENT*>(cmdp2), s_ptr, s_ptrbuff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2022-03-11 14:36:04 -07:00
|
|
|
|
for (CMDENT_TWO_ARG_ARGV* cmdp2 = command_table_two_arg_argv; cmdp2->cmdname; cmdp2++)
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
s_ptrbuff[0] = '\0';
|
|
|
|
|
|
s_ptr = s_ptrbuff;
|
2012-03-15 08:20:40 -07:00
|
|
|
|
if (0 != HOOKMASK(cmdp2->flags))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2022-03-11 14:36:04 -07:00
|
|
|
|
hook_loop(executor, reinterpret_cast<CMDENT*>(cmdp2), s_ptr, s_ptrbuff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!found)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%26s -- No @hooks defined --"), " "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
found = false;
|
|
|
|
|
|
/* We need to search the attribute table as well */
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%.32s-+-%s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
"--------------------------------",
|
|
|
|
|
|
"--------------------------------------------"));
|
2026-07-28 11:37:23 -06:00
|
|
|
|
{
|
|
|
|
|
|
UTF8 header[LBUF_SIZE];
|
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
|
pos = mux_table_append_ljust(header, sizeof(header), pos,
|
|
|
|
|
|
M_("Built-in Attribute"), kHookCmdCols);
|
|
|
|
|
|
pos = mux_table_append_bytes(header, sizeof(header), pos, " | ");
|
|
|
|
|
|
pos = mux_table_append_bytes(header, sizeof(header), pos,
|
|
|
|
|
|
reinterpret_cast<const char *>(M_("Hook Mask Values")));
|
|
|
|
|
|
notify(executor, header);
|
|
|
|
|
|
}
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%.32s-+-%s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
"--------------------------------",
|
|
|
|
|
|
"--------------------------------------------"));
|
2022-03-13 13:16:46 -06:00
|
|
|
|
UTF8* cbuff = alloc_sbuf("cbuff_hook");
|
2006-09-01 22:59:23 +00:00
|
|
|
|
for (ATTR *ap = AttrTable; ap->name; ap++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ap->flags & AF_NOCMD)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
s_ptrbuff[0] = '\0';
|
|
|
|
|
|
s_ptr = s_ptrbuff;
|
|
|
|
|
|
|
|
|
|
|
|
p = cbuff;
|
|
|
|
|
|
safe_sb_chr('@', cbuff, &p);
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
|
|
|
|
|
|
// Lowercase attr name code-point-at-a-time (Unicode-aware).
|
|
|
|
|
|
//
|
2026-03-05 21:35:51 -07:00
|
|
|
|
for (q = ap->name; '\0' != *q; )
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
2026-03-05 21:35:51 -07:00
|
|
|
|
size_t n = utf8_FirstByte[static_cast<unsigned char>(*q)];
|
|
|
|
|
|
if (n >= UTF8_CONTINUE)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
bool bValid = true;
|
|
|
|
|
|
for (size_t j = 1; j < n; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( '\0' == q[j]
|
|
|
|
|
|
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(q[j])])
|
|
|
|
|
|
{
|
|
|
|
|
|
bValid = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
bool bXor;
|
|
|
|
|
|
const string_desc *qDesc = mux_tolower(q, bXor);
|
|
|
|
|
|
if (nullptr == qDesc)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (size_t j = 0; j < n; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_sb_chr(q[j], cbuff, &p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (bXor)
|
|
|
|
|
|
{
|
2026-03-05 21:35:51 -07:00
|
|
|
|
if (qDesc->n_bytes != n)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (size_t j = 0; j < n; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_sb_chr(q[j], cbuff, &p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else for (size_t j = 0; j < qDesc->n_bytes; j++)
|
Unicode case-folding at all call sites (#415, #416, #417, #418, #420, #421, #422, #423).
Replace mux_toupper_ascii[]/mux_tolower_ascii[] with Unicode-aware
state-machine transforms (mux_toupper()/mux_tolower()) at 12 call
sites across 9 files:
- Add mux_toupper_first() helper for first-code-point uppercasing
- Rewrite mux_stricmp, mux_memicmp, string_compare, string_prefix,
minmatch, matches_exit_from_list for code-point-at-a-time comparison
- Rewrite BMH*I functions to pre-lowercase and delegate to
case-sensitive versions
- Convert string canonicalization sites in eval.cpp, flags.cpp,
functions.cpp, command.cpp to use mux_strupr()/mux_strlwr()
- Pre-lowercase wildcard patterns in wild.cpp entry points
- Add safe-ASCII comments at sites with guaranteed-ASCII data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:20:53 -07:00
|
|
|
|
{
|
|
|
|
|
|
safe_sb_chr(q[j] ^ qDesc->p[j], cbuff, &p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
for (size_t j = 0; j < qDesc->n_bytes; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
safe_sb_chr(qDesc->p[j], cbuff, &p);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-05 21:35:51 -07:00
|
|
|
|
q += n;
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
*p = '\0';
|
2022-03-13 13:16:46 -06:00
|
|
|
|
const size_t ncbuff = p - cbuff;
|
Replace 8 CHashTable instances with std::unordered_map (Phase 1).
Migrate command_htab, logout_cmd_htab, player_htab, powers_htab,
reference_htab, ufunc_htab to StringPtrMap and mail_htab, parent_htab,
pcache_htab to DbrefPtrMap. Eliminate the htab wrapper layer
(hashfindLEN, hashaddLEN, hashdeleteLEN, hashreplLEN, hashreplall,
hashflush, hashreset, hash_firstentry/nextentry/firstkey/nextkey)
and convert all 132 call sites to direct STL map operations.
Help system tables (HELP_DESC.ht) also migrated. vattr_name_htab
remains CHashTable for Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:37 -07:00
|
|
|
|
{
|
|
|
|
|
|
auto it_cb = mudstate.command_htab.find(std::vector<UTF8>(cbuff, cbuff + ncbuff));
|
|
|
|
|
|
cmdp = (it_cb != mudstate.command_htab.end()) ? static_cast<CMDENT*>(it_cb->second) : nullptr;
|
|
|
|
|
|
}
|
2006-09-01 22:59:23 +00:00
|
|
|
|
if ( cmdp
|
2012-03-15 08:20:40 -07:00
|
|
|
|
&& 0 != HOOKMASK(cmdp->flags))
|
2006-09-01 22:59:23 +00:00
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2026-07-28 17:39:01 +00:00
|
|
|
|
// Same C7 schema as the built-in command table.
|
|
|
|
|
|
//
|
|
|
|
|
|
hook_loop(executor, cmdp, s_ptr, s_ptrbuff);
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
free_sbuf(cbuff);
|
|
|
|
|
|
if (!found)
|
|
|
|
|
|
{
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%26s -- No @hooks defined --"), " "));
|
2006-09-01 22:59:23 +00:00
|
|
|
|
}
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("%.32s-+-%s"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
"--------------------------------",
|
|
|
|
|
|
"--------------------------------------------"));
|
2008-12-27 18:37:01 -08:00
|
|
|
|
notify(executor, tprintf(T("The hook object is currently: #%d (%s)"),
|
2006-09-01 22:59:23 +00:00
|
|
|
|
mudconf.hook_obj,
|
|
|
|
|
|
( ( Good_obj(mudconf.hook_obj)
|
|
|
|
|
|
&& !Going(mudconf.hook_obj))
|
|
|
|
|
|
? "VALID" : "INVALID")));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2007-12-21 17:46:20 -08:00
|
|
|
|
|
2010-06-16 10:00:20 -07:00
|
|
|
|
NAMETAB allow_charset_nametab[] =
|
2007-12-21 17:46:20 -08:00
|
|
|
|
{
|
2007-12-23 12:16:23 -08:00
|
|
|
|
{T("ascii"), 5, 0, ALLOW_CHARSET_ASCII},
|
2013-08-21 13:11:54 -06:00
|
|
|
|
{T("hangul"), 6, 0, ALLOW_CHARSET_HANGUL},
|
|
|
|
|
|
{T("hiragana"), 8, 0, ALLOW_CHARSET_HIRAGANA},
|
2009-03-07 14:35:15 -08:00
|
|
|
|
{T("iso8859-1"), 9, 0, ALLOW_CHARSET_8859_1},
|
|
|
|
|
|
{T("iso8859-2"), 9, 0, ALLOW_CHARSET_8859_2},
|
2013-08-21 13:11:54 -06:00
|
|
|
|
{T("kanji"), 5, 0, ALLOW_CHARSET_KANJI},
|
|
|
|
|
|
{T("katakana"), 8, 0, ALLOW_CHARSET_KATAKANA},
|
|
|
|
|
|
{T("latin-1"), 7, 0, ALLOW_CHARSET_8859_1},
|
|
|
|
|
|
{T("latin-2"), 7, 0, ALLOW_CHARSET_8859_2},
|
2022-03-11 14:36:04 -07:00
|
|
|
|
{static_cast<UTF8*>(nullptr), 0, 0, 0}
|
2007-12-21 17:46:20 -08:00
|
|
|
|
};
|