mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
decompile_flags and decompile_powers emit executable MUSH script for @decompile replay, not player prose. Marking them M_() made LANGUAGE=xx emit "[xx] @set Foo=WIZARD", which does not replay. Revert to T(); drop the msgids from the catalogues. Also reverts @power from #1671 — same decompile-script class. Flagged on #1674 review.
1499 lines
50 KiB
C++
1499 lines
50 KiB
C++
/*! \file flags.cpp
|
||
* \brief Flag manipulation routines.
|
||
*
|
||
*/
|
||
|
||
#include "copyright.h"
|
||
#include "autoconf.h"
|
||
#include "config.h"
|
||
#include "externs.h"
|
||
#include "routing.h"
|
||
using namespace std;
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_any: set or clear indicated bit, no security checking
|
||
*/
|
||
|
||
static bool fh_any(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
// Never let God drop his/her own wizbit.
|
||
//
|
||
if ( God(target)
|
||
&& reset
|
||
&& flag == WIZARD
|
||
&& fflags == FLAG_WORD1)
|
||
{
|
||
notify(player, M_("You cannot make God mortal."));
|
||
return false;
|
||
}
|
||
|
||
// Otherwise we can go do it.
|
||
//
|
||
if (reset)
|
||
{
|
||
s_Flags(target, fflags, db[target].fs.word[fflags] & ~flag);
|
||
}
|
||
else
|
||
{
|
||
s_Flags(target, fflags, db[target].fs.word[fflags] | flag);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_room_bit: only settable on rooms (TYPE_ROOM).
|
||
*/
|
||
|
||
static bool fh_room_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!isRoom(target))
|
||
{
|
||
return false;
|
||
}
|
||
bool result = fh_any(target, player, flag, fflags, reset);
|
||
if (result)
|
||
{
|
||
route_invalidate();
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_god: only GOD may set or clear the bit
|
||
*/
|
||
|
||
static bool fh_god(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!God(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_wiz: only WIZARDS (or GOD) may set or clear the bit
|
||
*/
|
||
|
||
static bool fh_wiz(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!Wizard(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit
|
||
*/
|
||
|
||
static bool fh_wizroy(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!WizRoy(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_restrict_player (renamed from fh_fixed): Only Wizards can set
|
||
* * this on players, but ordinary players can set it on other types
|
||
* * of objects.
|
||
*/
|
||
static bool fh_restrict_player
|
||
(
|
||
dbref target,
|
||
dbref player,
|
||
FLAG flag,
|
||
int fflags,
|
||
bool reset
|
||
)
|
||
{
|
||
if ( isPlayer(target)
|
||
&& !Wizard(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_privileged: You can set this flag on a non-player object, if you
|
||
* yourself have this flag and are a player who owns themselves (i.e.,
|
||
* no robots). Only God can set this on a player.
|
||
*/
|
||
static bool fh_privileged
|
||
(
|
||
dbref target,
|
||
dbref player,
|
||
FLAG flag,
|
||
int fflags,
|
||
bool reset
|
||
)
|
||
{
|
||
if (!God(player))
|
||
{
|
||
if ( isPlayer(target)
|
||
|| !isPlayer(player)
|
||
|| player != Owner(player)
|
||
|| (db[player].fs.word[fflags] & flag) == 0)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_inherit: only players may set or clear this bit.
|
||
*/
|
||
|
||
static bool fh_inherit(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!Inherits(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_dark_bit: manipulate the dark bit. Nonwizards may not set on players.
|
||
*/
|
||
|
||
static bool fh_dark_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if ( !reset
|
||
&& isPlayer(target)
|
||
&& !( (target == player)
|
||
&& (Can_Hide(player) || Can_Dark(player)))
|
||
&& !Wizard(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_going_bit: manipulate the going bit. Non-gods may only clear.
|
||
*/
|
||
|
||
static bool fh_going_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if ( Going(target)
|
||
&& reset
|
||
&& (Typeof(target) != TYPE_GARBAGE))
|
||
{
|
||
notify(player, M_("Your object has been spared from destruction."));
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
if (!God(player))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// Even God should not be allowed set protected dbrefs GOING.
|
||
//
|
||
if ( !reset
|
||
&& ( target == 0
|
||
|| God(target)
|
||
|| target == mudconf.start_home
|
||
|| target == mudconf.start_room
|
||
|| target == mudconf.default_home
|
||
|| target == mudconf.master_room))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_hear_bit: set or clear bits that affect hearing.
|
||
*/
|
||
|
||
static bool fh_hear_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (isPlayer(target) && (flag & MONITOR))
|
||
{
|
||
if (Can_Monitor(player))
|
||
{
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
bool could_hear = Hearer(target);
|
||
bool result = fh_any(target, player, flag, fflags, reset);
|
||
handle_ears(target, could_hear, Hearer(target));
|
||
return result;
|
||
}
|
||
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_player_bit: Can set and reset this on everything but players.
|
||
*/
|
||
static bool fh_player_bit
|
||
(
|
||
dbref target,
|
||
dbref player,
|
||
FLAG flag,
|
||
int fflags,
|
||
bool reset
|
||
)
|
||
{
|
||
if (isPlayer(target))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* fh_staff: only STAFF, WIZARDS, ROYALTY, (or GOD) may set or clear
|
||
* the bit.
|
||
*/
|
||
static bool fh_staff
|
||
(
|
||
dbref target,
|
||
dbref player,
|
||
FLAG flag,
|
||
int fflags,
|
||
bool reset
|
||
)
|
||
{
|
||
if (!Staff(player) && !God(player))
|
||
{
|
||
return false;
|
||
}
|
||
return (fh_any(target, player, flag, fflags, reset));
|
||
}
|
||
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_unicode: only players may set or clear this bit.
|
||
*/
|
||
|
||
static bool fh_unicode(dbref target, dbref player, FLAG flag, int fflags, bool reset)
|
||
{
|
||
if (!isPlayer(target))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (fh_any(target, player, flag, fflags, reset))
|
||
{
|
||
if (!reset)
|
||
{
|
||
set_player_encoding(target, CHARSET_UTF8);
|
||
}
|
||
else
|
||
{
|
||
reset_player_encoding(target);
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * fh_ascii: only players may set or clear this bit.
|
||
*/
|
||
|
||
static bool fh_ascii(const dbref target, const dbref player, FLAG flag, int fflags, const bool reset)
|
||
{
|
||
if (!isPlayer(target))
|
||
{
|
||
return false;
|
||
}
|
||
const bool result = fh_any(target, player, flag, fflags, reset);
|
||
|
||
if (result)
|
||
{
|
||
if (!reset)
|
||
{
|
||
set_player_encoding(target, CHARSET_ASCII);
|
||
}
|
||
else
|
||
{
|
||
reset_player_encoding(target);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
static FLAGBITENT fbeAbode = { ABODE, 'A', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeAnsi = { ANSI, 'X', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeAudible = { HEARTHRU, 'a', FLAG_WORD1, 0, fh_hear_bit};
|
||
static FLAGBITENT fbeAuditorium = { AUDITORIUM, 'b', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeBlind = { BLIND, 'B', FLAG_WORD2, 0, fh_wiz};
|
||
static FLAGBITENT fbeChownOk = { CHOWN_OK, 'C', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeColor256 = { COLOR256, ' ', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeTruecolor = { TRUECOLOR, ' ', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeConnected = { CONNECTED, 'c', FLAG_WORD2, CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbeDark = { DARK, 'D', FLAG_WORD1, 0, fh_dark_bit};
|
||
static FLAGBITENT fbeDestroyOk = { DESTROY_OK, 'd', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeEnterOk = { ENTER_OK, 'e', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeFixed = { FIXED_FLAG, 'f', FLAG_WORD2, 0, fh_restrict_player};
|
||
static FLAGBITENT fbeFloating = { FLOATING, 'F', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeGagged = { GAGGED, 'j', FLAG_WORD2, 0, fh_wiz};
|
||
static FLAGBITENT fbeGoing = { GOING, 'G', FLAG_WORD1, CA_NO_DECOMP, fh_going_bit};
|
||
static FLAGBITENT fbeHalted = { HALT, 'h', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeHasDaily = { HAS_DAILY, '*', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbeHasForwardList = { HAS_FWDLIST, '&', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbeHasListen = { HAS_LISTEN, '@', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbeHasStartup = { HAS_STARTUP, '+', FLAG_WORD1, CA_GOD|CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbeHaven = { HAVEN, 'H', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeHead = { HEAD_FLAG, '?', FLAG_WORD2, 0, fh_wiz};
|
||
static FLAGBITENT fbeHtml = { HTML, '(', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeImmortal = { IMMORTAL, 'i', FLAG_WORD1, 0, fh_wiz};
|
||
static FLAGBITENT fbeInherit = { INHERIT, 'I', FLAG_WORD1, 0, fh_inherit};
|
||
static FLAGBITENT fbeJumpOk = { JUMP_OK, 'J', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeKeepAlive = { CKEEPALIVE, 'k', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeKey = { KEY, 'K', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeLight = { LIGHT, 'l', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeLinkOk = { LINK_OK, 'L', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeMonitor = { MONITOR, 'M', FLAG_WORD1, 0, fh_hear_bit};
|
||
static FLAGBITENT fbeMyopic = { MYOPIC, 'm', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeNoCommand = { NO_COMMAND, 'n', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeAscii = { ASCII , '~', FLAG_WORD2, 0, fh_ascii};
|
||
static FLAGBITENT fbeNoBleed = { NOBLEED, '-', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeNoSpoof = { NOSPOOF, 'N', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeOpaque = { MUX_OPAQUE, 'O', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeOpenOk = { OPEN_OK, 'z', FLAG_WORD2, 0, fh_wiz};
|
||
static FLAGBITENT fbeParentOk = { PARENT_OK, 'Y', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbePlayerMails = { PLAYER_MAILS, ' ', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god};
|
||
static FLAGBITENT fbePuppet = { PUPPET, 'p', FLAG_WORD1, 0, fh_hear_bit};
|
||
static FLAGBITENT fbeQuiet = { QUIET, 'Q', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeRobot = { ROBOT, 'r', FLAG_WORD1, 0, fh_player_bit};
|
||
static FLAGBITENT fbeRoyalty = { ROYALTY, 'Z', FLAG_WORD1, 0, fh_wiz};
|
||
static FLAGBITENT fbeSafe = { SAFE, 's', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeSlave = { SLAVE, 'x', FLAG_WORD2, CA_WIZARD, fh_wiz};
|
||
static FLAGBITENT fbeStaff = { STAFF, 'w', FLAG_WORD2, 0, fh_wiz};
|
||
static FLAGBITENT fbeSticky = { STICKY, 'S', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeSuspect = { SUSPECT, 'u', FLAG_WORD2, CA_WIZARD, fh_wiz};
|
||
static FLAGBITENT fbeTalkMode = { TALKMODE, ' ', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeTerse = { TERSE, 'q', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeTrace = { TRACE, 'T', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeTransparent = { SEETHRU, 't', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeUnfindable = { UNFINDABLE, 'U', FLAG_WORD2, 0, fh_any};
|
||
static FLAGBITENT fbeUnicode = { MUX_UNICODE, ' ', FLAG_WORD3, CA_NO_DECOMP, fh_unicode};
|
||
static FLAGBITENT fbeUninspected = { UNINSPECTED, 'g', FLAG_WORD2, 0, fh_wizroy};
|
||
static FLAGBITENT fbeVacation = { VACATION, '|', FLAG_WORD2, 0, fh_restrict_player};
|
||
static FLAGBITENT fbeVerbose = { VERBOSE, 'v', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeVisual = { VISUAL, 'V', FLAG_WORD1, 0, fh_any};
|
||
static FLAGBITENT fbeWizard = { WIZARD, 'W', FLAG_WORD1, 0, fh_god};
|
||
static FLAGBITENT fbeAlone = { ALONE, ' ', FLAG_WORD3, 0, fh_wiz};
|
||
static FLAGBITENT fbeNoExamine = { NOEXAMINE, 'E', FLAG_WORD3, 0, fh_wizroy};
|
||
static FLAGBITENT fbeNoModify = { NOMODIFY, ' ', FLAG_WORD3, 0, fh_wizroy};
|
||
static FLAGBITENT fbeIndestructible = { INDESTRUCTIBLE, ' ', FLAG_WORD3, 0, fh_wizroy};
|
||
static FLAGBITENT fbeNoEval = { NOEVAL, ' ', FLAG_WORD3, 0, fh_any};
|
||
static FLAGBITENT fbeNavigable = { NAVIGABLE, ' ', FLAG_WORD3, 0, fh_room_bit};
|
||
static FLAGBITENT fbeSitemon = { SITEMON, '$', FLAG_WORD3, 0, fh_wiz};
|
||
#ifdef WOD_REALMS
|
||
static FLAGBITENT fbeFae = { FAE, '0', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeChimera = { CHIMERA, '1', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbePeering = { PEERING, '2', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeUmbra = { UMBRA, '3', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeShroud = { SHROUD, '4', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeMatrix = { MATRIX, '5', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeObf = { OBF, '6', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeHss = { HSS, '7', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeMedium = { MEDIUM, '8', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeDead = { DEAD, '9', FLAG_WORD3, CA_STAFF, fh_wizroy};
|
||
static FLAGBITENT fbeMarker0 = { MARK_0, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker1 = { MARK_1, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker2 = { MARK_2, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker3 = { MARK_3, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker4 = { MARK_4, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker5 = { MARK_5, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker6 = { MARK_6, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker7 = { MARK_7, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker8 = { MARK_8, ' ', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker9 = { MARK_9, ' ', FLAG_WORD3, 0, fh_god};
|
||
#else // WOD_REALMS
|
||
static FLAGBITENT fbeMarker0 = { MARK_0, '0', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker1 = { MARK_1, '1', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker2 = { MARK_2, '2', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker3 = { MARK_3, '3', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker4 = { MARK_4, '4', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker5 = { MARK_5, '5', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker6 = { MARK_6, '6', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker7 = { MARK_7, '7', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker8 = { MARK_8, '8', FLAG_WORD3, 0, fh_god};
|
||
static FLAGBITENT fbeMarker9 = { MARK_9, '9', FLAG_WORD3, 0, fh_god};
|
||
#endif // WOD_REALMS
|
||
|
||
FLAGNAMEENT gen_flag_names[] =
|
||
{
|
||
{T("ALONE"), true, &fbeAlone },
|
||
{T("ABODE"), true, &fbeAbode },
|
||
{T("ACCENTS"), false, &fbeAscii },
|
||
{T("ANSI"), true, &fbeAnsi },
|
||
{T("ASCII"), true, &fbeAscii },
|
||
{T("AUDIBLE"), true, &fbeAudible },
|
||
{T("AUDITORIUM"), true, &fbeAuditorium },
|
||
{T("BLEED"), false, &fbeNoBleed },
|
||
{T("BLIND"), true, &fbeBlind },
|
||
{T("COMMANDS"), false, &fbeNoCommand },
|
||
{T("CHOWN_OK"), true, &fbeChownOk },
|
||
{T("COLOR256"), true, &fbeColor256 },
|
||
{T("CONNECTED"), true, &fbeConnected },
|
||
{T("DARK"), true, &fbeDark },
|
||
{T("DESTROY_OK"), true, &fbeDestroyOk },
|
||
{T("ENTER_OK"), true, &fbeEnterOk },
|
||
{T("FIXED"), true, &fbeFixed },
|
||
{T("FLOATING"), true, &fbeFloating },
|
||
{T("GAGGED"), true, &fbeGagged },
|
||
{T("GOING"), true, &fbeGoing },
|
||
{T("HALTED"), true, &fbeHalted },
|
||
{T("HAS_DAILY"), true, &fbeHasDaily },
|
||
{T("HAS_FORWARDLIST"), true, &fbeHasForwardList },
|
||
{T("HAS_LISTEN"), true, &fbeHasListen },
|
||
{T("HAS_STARTUP"), true, &fbeHasStartup },
|
||
{T("HAVEN"), true, &fbeHaven },
|
||
{T("HEAD"), true, &fbeHead },
|
||
{T("HTML"), true, &fbeHtml },
|
||
{T("IMMORTAL"), true, &fbeImmortal },
|
||
{T("INDESTRUCTIBLE"), true, &fbeIndestructible },
|
||
{T("INHERIT"), true, &fbeInherit },
|
||
{T("JUMP_OK"), true, &fbeJumpOk },
|
||
{T("KEEPALIVE"), true, &fbeKeepAlive },
|
||
{T("KEY"), true, &fbeKey },
|
||
{T("LIGHT"), true, &fbeLight },
|
||
{T("LINK_OK"), true, &fbeLinkOk },
|
||
{T("MARKER0"), true, &fbeMarker0 },
|
||
{T("MARKER1"), true, &fbeMarker1 },
|
||
{T("MARKER2"), true, &fbeMarker2 },
|
||
{T("MARKER3"), true, &fbeMarker3 },
|
||
{T("MARKER4"), true, &fbeMarker4 },
|
||
{T("MARKER5"), true, &fbeMarker5 },
|
||
{T("MARKER6"), true, &fbeMarker6 },
|
||
{T("MARKER7"), true, &fbeMarker7 },
|
||
{T("MARKER8"), true, &fbeMarker8 },
|
||
{T("MARKER9"), true, &fbeMarker9 },
|
||
{T("MONITOR"), true, &fbeMonitor },
|
||
{T("MYOPIC"), true, &fbeMyopic },
|
||
{T("NAVIGABLE"), true, &fbeNavigable },
|
||
{T("NO_COMMAND"), true, &fbeNoCommand },
|
||
{T("NO_EXAMINE"), true, &fbeNoExamine },
|
||
{T("NOBLEED"), true, &fbeNoBleed },
|
||
{T("NOEVAL"), true, &fbeNoEval },
|
||
{T("NOEXAMINE"), true, &fbeNoExamine },
|
||
{T("NOMODIFY"), true, &fbeNoModify },
|
||
{T("NO_MODIFY"), true, &fbeNoModify },
|
||
{T("NOSPOOF"), true, &fbeNoSpoof },
|
||
{T("OPAQUE"), true, &fbeOpaque },
|
||
{T("OPEN_OK"), true, &fbeOpenOk },
|
||
{T("PARENT_OK"), true, &fbeParentOk },
|
||
{T("PLAYER_MAILS"), true, &fbePlayerMails },
|
||
{T("PUPPET"), true, &fbePuppet },
|
||
{T("QUIET"), true, &fbeQuiet },
|
||
{T("ROBOT"), true, &fbeRobot },
|
||
{T("ROYALTY"), true, &fbeRoyalty },
|
||
{T("SAFE"), true, &fbeSafe },
|
||
{T("SITEMON"), true, &fbeSitemon },
|
||
{T("SLAVE"), true, &fbeSlave },
|
||
{T("SPOOF"), false, &fbeNoSpoof },
|
||
{T("STAFF"), true, &fbeStaff },
|
||
{T("STICKY"), true, &fbeSticky },
|
||
{T("SUSPECT"), true, &fbeSuspect },
|
||
{T("TALKMODE"), true, &fbeTalkMode },
|
||
{T("TERSE"), true, &fbeTerse },
|
||
{T("TRACE"), true, &fbeTrace },
|
||
{T("TRANSPARENT"), true, &fbeTransparent },
|
||
{T("TRUECOLOR"), true, &fbeTruecolor },
|
||
{T("UNFINDABLE"), true, &fbeUnfindable },
|
||
{T("UNICODE"), true, &fbeUnicode },
|
||
{T("UNINSPECTED"), true, &fbeUninspected },
|
||
{T("VACATION"), true, &fbeVacation },
|
||
{T("VERBOSE"), true, &fbeVerbose },
|
||
{T("VISUAL"), true, &fbeVisual },
|
||
{T("WIZARD"), true, &fbeWizard },
|
||
#ifdef WOD_REALMS
|
||
{T("FAE"), true, &fbeFae },
|
||
{T("CHIMERA"), true, &fbeChimera },
|
||
{T("PEERING"), true, &fbePeering },
|
||
{T("UMBRA"), true, &fbeUmbra },
|
||
{T("SHROUD"), true, &fbeShroud },
|
||
{T("MATRIX"), true, &fbeMatrix },
|
||
{T("OBF"), true, &fbeObf },
|
||
{T("HSS"), true, &fbeHss },
|
||
{T("MEDIUM"), true, &fbeMedium },
|
||
{T("DEAD"), true, &fbeDead },
|
||
#endif // WOD_REALMS
|
||
{nullptr, false, nullptr}
|
||
};
|
||
|
||
OBJENT object_types[8] =
|
||
{
|
||
{T("ROOM"), 'R', CA_PUBLIC, OF_CONTENTS|OF_EXITS|OF_DROPTO|OF_HOME},
|
||
{T("THING"), ' ', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
|
||
{T("EXIT"), 'E', CA_PUBLIC, OF_SIBLINGS},
|
||
{T("PLAYER"), 'P', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_OWNER|OF_SIBLINGS},
|
||
{T("TYPE5"), '+', CA_GOD, 0},
|
||
{T("GARBAGE"), '-', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
|
||
{T("GARBAGE"), '#', CA_GOD, 0},
|
||
{T("GARBAGE"), '=', CA_GOD, 0}
|
||
};
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* init_flagtab: initialize flag hash tables.
|
||
*/
|
||
|
||
void init_flagtab(void)
|
||
{
|
||
for (FLAGNAMEENT *flag_name_entity = gen_flag_names; flag_name_entity->pOrigName; flag_name_entity++)
|
||
{
|
||
flag_name_entity->flagname = const_cast<UTF8*>(flag_name_entity->pOrigName);
|
||
const size_t flag_name_length = strlen(reinterpret_cast<const char*>(flag_name_entity->pOrigName));
|
||
vector<UTF8> flag_name(flag_name_entity->pOrigName, flag_name_entity->pOrigName + flag_name_length);
|
||
auto it = mudstate.flag_names_map.find(flag_name);
|
||
if (it == mudstate.flag_names_map.end())
|
||
{
|
||
mudstate.flag_names_map.insert(make_pair(flag_name, flag_name_entity));
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* display_flags: display available flags.
|
||
*/
|
||
|
||
void display_flagtab(dbref player)
|
||
{
|
||
FLAGNAMEENT *fp;
|
||
|
||
LBuf buf = LBuf_Src("display_flagtab");
|
||
UTF8 *bp = buf.get();
|
||
safe_str(M_("Flags:"), buf, &bp);
|
||
for (fp = gen_flag_names; fp->flagname; fp++)
|
||
{
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
if ( ( (fbe->listperm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (fbe->listperm & CA_GOD)
|
||
&& !God(player)))
|
||
{
|
||
continue;
|
||
}
|
||
safe_chr(' ', buf, &bp);
|
||
safe_str(fp->flagname, buf, &bp);
|
||
if (fbe->flaglett != ' ')
|
||
{
|
||
safe_chr('(', buf, &bp);
|
||
if (!fp->bPositive)
|
||
{
|
||
safe_chr('!', buf, &bp);
|
||
}
|
||
safe_chr(fbe->flaglett, buf, &bp);
|
||
safe_chr(')', buf, &bp);
|
||
}
|
||
}
|
||
*bp = '\0';
|
||
notify(player, buf);
|
||
}
|
||
|
||
UTF8 *MakeCanonicalFlagName
|
||
(
|
||
const UTF8 *pName,
|
||
int *pnName,
|
||
bool *pbValid
|
||
)
|
||
{
|
||
thread_local UTF8 buff[SBUF_SIZE];
|
||
UTF8 *p = buff;
|
||
int nName = 0;
|
||
|
||
// Uppercase flag name one code point at a time (Unicode-aware).
|
||
//
|
||
while ('\0' != *pName)
|
||
{
|
||
size_t n = utf8_FirstByte[static_cast<unsigned char>(*pName)];
|
||
if (n >= UTF8_CONTINUE)
|
||
{
|
||
*pnName = 0;
|
||
*pbValid = false;
|
||
return nullptr;
|
||
}
|
||
|
||
for (size_t j = 1; j < n; j++)
|
||
{
|
||
if ( '\0' == pName[j]
|
||
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(pName[j])])
|
||
{
|
||
*pnName = 0;
|
||
*pbValid = false;
|
||
return nullptr;
|
||
}
|
||
}
|
||
|
||
bool bXor;
|
||
const string_desc *qDesc = mux_toupper(pName, bXor);
|
||
size_t m;
|
||
if (nullptr == qDesc)
|
||
{
|
||
m = n;
|
||
if (nName + static_cast<int>(m) >= SBUF_SIZE)
|
||
{
|
||
break;
|
||
}
|
||
for (size_t j = 0; j < m; j++)
|
||
{
|
||
*p++ = pName[j];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
m = qDesc->n_bytes;
|
||
if ( bXor
|
||
&& m != n)
|
||
{
|
||
*pnName = 0;
|
||
*pbValid = false;
|
||
return nullptr;
|
||
}
|
||
if (nName + static_cast<int>(m) >= SBUF_SIZE)
|
||
{
|
||
break;
|
||
}
|
||
if (bXor)
|
||
{
|
||
for (size_t j = 0; j < m; j++)
|
||
{
|
||
*p++ = pName[j] ^ qDesc->p[j];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (size_t j = 0; j < m; j++)
|
||
{
|
||
*p++ = qDesc->p[j];
|
||
}
|
||
}
|
||
}
|
||
nName += static_cast<int>(m);
|
||
pName += n;
|
||
}
|
||
*p = '\0';
|
||
if ( 0 < nName
|
||
&& nName < SBUF_SIZE)
|
||
{
|
||
*pnName = nName;
|
||
*pbValid = true;
|
||
return buff;
|
||
}
|
||
else
|
||
{
|
||
*pnName = 0;
|
||
*pbValid = false;
|
||
return nullptr;
|
||
}
|
||
}
|
||
|
||
static FLAGNAMEENT* find_flag(const UTF8* input_flag_name)
|
||
{
|
||
// Convert input_flag_name to canonical lowercase format.
|
||
//
|
||
int flag_name_length;
|
||
bool valid;
|
||
UTF8* flag_name = MakeCanonicalFlagName(input_flag_name, &flag_name_length, &valid);
|
||
if (valid)
|
||
{
|
||
const vector<UTF8> name(flag_name, flag_name + flag_name_length);
|
||
const auto it = mudstate.flag_names_map.find(name);
|
||
if (it != mudstate.flag_names_map.end())
|
||
{
|
||
return it->second;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// flag_set: Set or clear a specified flag on an object.
|
||
//
|
||
void flag_set(dbref target, dbref player, UTF8 *flag, int key)
|
||
{
|
||
bool bDone = false;
|
||
|
||
do
|
||
{
|
||
// Trim spaces, and handle the negation character.
|
||
//
|
||
while (mux_isspace(*flag))
|
||
{
|
||
flag++;
|
||
}
|
||
|
||
bool bNegate = false;
|
||
if (*flag == '!')
|
||
{
|
||
bNegate = true;
|
||
do
|
||
{
|
||
flag++;
|
||
} while (mux_isspace(*flag));
|
||
}
|
||
|
||
// Beginning of flag name is now 'flag'.
|
||
//
|
||
UTF8 *nflag = flag;
|
||
while ( *nflag != '\0'
|
||
&& !mux_isspace(*nflag))
|
||
{
|
||
nflag++;
|
||
}
|
||
|
||
if (*nflag == '\0')
|
||
{
|
||
bDone = true;
|
||
}
|
||
else
|
||
{
|
||
*nflag = '\0';
|
||
}
|
||
|
||
// Make sure a flag name was specified.
|
||
//
|
||
if (*flag == '\0')
|
||
{
|
||
if (bNegate)
|
||
{
|
||
notify(player, M_("You must specify a flag to clear."));
|
||
}
|
||
else
|
||
{
|
||
notify(player, M_("You must specify a flag to set."));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
FLAGNAMEENT *fp = find_flag(flag);
|
||
if (!fp)
|
||
{
|
||
notify(player, M_("I do not understand that flag."));
|
||
}
|
||
else
|
||
{
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
|
||
bool bClearSet = bNegate;
|
||
if (!fp->bPositive)
|
||
{
|
||
bNegate = !bNegate;
|
||
}
|
||
|
||
// Check if the flag is already in the desired state.
|
||
//
|
||
bool bCurrentlySet = (db[target].fs.word[fbe->flagflag] & fbe->flagvalue) != 0;
|
||
if (bNegate == bCurrentlySet)
|
||
{
|
||
// State needs to change. Check NOMODIFY first.
|
||
//
|
||
if (NoModify(target) && !WizRoy(player))
|
||
{
|
||
notify(player, NOPERM_MESSAGE);
|
||
bDone = true;
|
||
continue;
|
||
}
|
||
|
||
// Invoke the flag handler, and print feedback.
|
||
//
|
||
if (!fbe->handler(target, player, fbe->flagvalue, fbe->flagflag, bNegate))
|
||
{
|
||
notify(player, NOPERM_MESSAGE);
|
||
}
|
||
else if (!(key & SET_QUIET) && !Quiet(player))
|
||
{
|
||
notify(player, (bClearSet ? M_("Cleared.") : M_("Set.")));
|
||
}
|
||
}
|
||
else if (!(key & SET_QUIET) && !Quiet(player))
|
||
{
|
||
notify(player, (bClearSet ? M_("Already cleared.") : M_("Already set.")));
|
||
}
|
||
}
|
||
}
|
||
flag = nflag + 1;
|
||
|
||
} while (!bDone);
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * decode_flags: converts a flags word into corresponding letters.
|
||
*/
|
||
|
||
UTF8 *decode_flags(dbref player, FLAGSET *fs)
|
||
{
|
||
UTF8 *buf, *bp;
|
||
buf = bp = alloc_sbuf("decode_flags");
|
||
*bp = '\0';
|
||
|
||
if (!Good_obj(player))
|
||
{
|
||
mux_strncpy(buf, S_("#-2 ERROR"), SBUF_SIZE-1);
|
||
return buf;
|
||
}
|
||
int flagtype = fs->word[FLAG_WORD1] & TYPE_MASK;
|
||
bool bNeedColon = true;
|
||
if (object_types[flagtype].lett != ' ')
|
||
{
|
||
safe_sb_chr(object_types[flagtype].lett, buf, &bp);
|
||
bNeedColon = false;
|
||
}
|
||
|
||
FLAGNAMEENT *fp;
|
||
for (fp = gen_flag_names; fp->flagname; fp++)
|
||
{
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
if ( !fp->bPositive
|
||
|| fbe->flaglett == ' ')
|
||
{
|
||
// Only look at positive-sense entries that have non-space flag
|
||
// letters.
|
||
//
|
||
continue;
|
||
}
|
||
if (fs->word[fbe->flagflag] & fbe->flagvalue)
|
||
{
|
||
if ( ( (fbe->listperm & CA_STAFF)
|
||
&& !Staff(player))
|
||
|| ( (fbe->listperm & CA_ADMIN)
|
||
&& !WizRoy(player))
|
||
|| ( (fbe->listperm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (fbe->listperm & CA_GOD)
|
||
&& !God(player)))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Don't show CONNECT on hidden players to those who can't see
|
||
// them. Test DARK alone -- that is what Hidden() means -- to
|
||
// match has_flag() and flag_description(). Requiring WIZARD too
|
||
// leaked the 'c' letter for every dark non-wizard: royalty,
|
||
// staff, and any mortal able to set itself DARK (#1184). This
|
||
// takes a FLAGSET rather than a dbref, so the test is on the
|
||
// flagset the caller passed, which is the target's.
|
||
//
|
||
if ( flagtype == TYPE_PLAYER
|
||
&& fbe->flagflag == FLAG_WORD2
|
||
&& fbe->flagvalue == CONNECTED
|
||
&& (fs->word[FLAG_WORD1] & DARK) != 0
|
||
&& !See_Hidden(player))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if ( bNeedColon
|
||
&& mux_isdigit(fbe->flaglett))
|
||
{
|
||
// We can't allow numerical digits at the beginning.
|
||
//
|
||
safe_sb_chr(':', buf, &bp);
|
||
}
|
||
safe_sb_chr(fbe->flaglett, buf, &bp);
|
||
bNeedColon = false;
|
||
}
|
||
}
|
||
*bp = '\0';
|
||
return buf;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * has_flag: does object have flag visible to player?
|
||
*/
|
||
|
||
bool has_flag(dbref player, dbref it, const UTF8 *flagname)
|
||
{
|
||
FLAGNAMEENT *fp = find_flag(flagname);
|
||
if (!fp)
|
||
{
|
||
return false;
|
||
}
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
|
||
if ( ( fp->bPositive
|
||
&& (db[it].fs.word[fbe->flagflag] & fbe->flagvalue))
|
||
|| ( !fp->bPositive
|
||
&& (db[it].fs.word[fbe->flagflag] & fbe->flagvalue) == 0))
|
||
{
|
||
if ( ( (fbe->listperm & CA_STAFF)
|
||
&& !Staff(player))
|
||
|| ( (fbe->listperm & CA_ADMIN)
|
||
&& !WizRoy(player))
|
||
|| ( (fbe->listperm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (fbe->listperm & CA_GOD)
|
||
&& !God(player)))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// Don't show CONNECT on dark wizards to mortals
|
||
//
|
||
if ( isPlayer(it)
|
||
&& (fbe->flagvalue == CONNECTED)
|
||
&& (fbe->flagflag == FLAG_WORD2)
|
||
&& Hidden(it)
|
||
&& !See_Hidden(player))
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * flag_description: Return an mbuf containing the type and flags on thing.
|
||
*/
|
||
|
||
UTF8 *flag_description(dbref player, dbref target)
|
||
{
|
||
// Allocate the return buffer.
|
||
//
|
||
int otype = Typeof(target);
|
||
UTF8 *buff = alloc_mbuf("flag_description");
|
||
UTF8 *bp = buff;
|
||
|
||
// Store the header strings and object type.
|
||
//
|
||
safe_mb_str(T("Type: "), buff, &bp);
|
||
safe_mb_str(object_types[otype].name, buff, &bp);
|
||
safe_mb_str(T(" Flags:"), buff, &bp);
|
||
if (object_types[otype].perm != CA_PUBLIC)
|
||
{
|
||
*bp = '\0';
|
||
return buff;
|
||
}
|
||
|
||
// Store the type-invariant flags.
|
||
//
|
||
FLAGNAMEENT *fp;
|
||
for (fp = gen_flag_names; fp->flagname; fp++)
|
||
{
|
||
if (!fp->bPositive)
|
||
{
|
||
continue;
|
||
}
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
if (db[target].fs.word[fbe->flagflag] & fbe->flagvalue)
|
||
{
|
||
if ( ( (fbe->listperm & CA_STAFF)
|
||
&& !Staff(player))
|
||
|| ( (fbe->listperm & CA_ADMIN)
|
||
&& !WizRoy(player))
|
||
|| ( (fbe->listperm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (fbe->listperm & CA_GOD)
|
||
&& !God(player)))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Don't show CONNECT on dark wizards to mortals.
|
||
//
|
||
if ( isPlayer(target)
|
||
&& (fbe->flagvalue == CONNECTED)
|
||
&& (fbe->flagflag == FLAG_WORD2)
|
||
&& Hidden(target)
|
||
&& !See_Hidden(player))
|
||
{
|
||
continue;
|
||
}
|
||
safe_mb_chr(' ', buff, &bp);
|
||
safe_mb_str(fp->flagname, buff, &bp);
|
||
}
|
||
}
|
||
|
||
// Terminate the string, and return the buffer to the caller.
|
||
//
|
||
*bp = '\0';
|
||
return buff;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * Return an lbuf containing the name and number of an object
|
||
*/
|
||
|
||
UTF8 *unparse_object_numonly(dbref target)
|
||
{
|
||
LBuf buf = LBuf_Src("unparse_object_numonly");
|
||
if (target < 0)
|
||
{
|
||
mux_strncpy(buf, aszSpecialDBRefNames[-target], LBUF_SIZE-1);
|
||
}
|
||
else if (!Good_obj(target))
|
||
{
|
||
mux_sprintf(buf, LBUF_SIZE, T("*ILLEGAL*(#%d)"), target);
|
||
}
|
||
else
|
||
{
|
||
mux_sprintf(buf, LBUF_SIZE, T("%s(#%d)"), PureName(target), target);
|
||
}
|
||
return buf.release();
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * Return an lbuf pointing to the object name and possibly the db# and flags
|
||
*/
|
||
UTF8 *unparse_object(dbref player, dbref target, bool obey_myopic)
|
||
{
|
||
LBuf buf = LBuf_Src("unparse_object");
|
||
if (NOPERM <= target && target < 0)
|
||
{
|
||
mux_strncpy(buf, aszSpecialDBRefNames[-target], LBUF_SIZE-1);
|
||
}
|
||
else if (!Good_obj(target))
|
||
{
|
||
mux_sprintf(buf, LBUF_SIZE, T("*ILLEGAL*(#%d)"), target);
|
||
}
|
||
else
|
||
{
|
||
bool exam;
|
||
if (obey_myopic)
|
||
{
|
||
exam = MyopicExam(player, target);
|
||
}
|
||
else
|
||
{
|
||
exam = Examinable(player, target);
|
||
}
|
||
|
||
// Leave and extra 100 bytes for the dbref and flags at the end and
|
||
// color at the beginning if necessary..
|
||
//
|
||
mux_field fldName = StripTabsAndTruncate( Moniker(target), buf,
|
||
LBUF_SIZE-100, LBUF_SIZE-100);
|
||
UTF8 *bp = buf + fldName.m_byte;
|
||
|
||
if ( exam
|
||
|| (Flags(target) & (CHOWN_OK | JUMP_OK | LINK_OK | DESTROY_OK))
|
||
|| (Flags2(target) & ABODE))
|
||
{
|
||
// Show everything.
|
||
//
|
||
UTF8 *fp = decode_flags(player, &(db[target].fs));
|
||
|
||
safe_str(T("(#"), buf, &bp);
|
||
safe_ltoa(target, buf, &bp);
|
||
safe_str(fp, buf, &bp);
|
||
safe_chr(')', buf, &bp);
|
||
|
||
free_sbuf(fp);
|
||
}
|
||
*bp = '\0';
|
||
}
|
||
return buf.release();
|
||
}
|
||
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* cf_flag_access: Modify who can set a flag.
|
||
*/
|
||
|
||
CF_HAND(cf_flag_access)
|
||
{
|
||
UNUSED_PARAMETER(vp);
|
||
UNUSED_PARAMETER(pExtra);
|
||
UNUSED_PARAMETER(nExtra);
|
||
|
||
string_token st(str, T(" \t=,"));
|
||
UTF8 *fstr = st.parse();
|
||
UTF8 *permstr = st.parse();
|
||
|
||
if ( nullptr == fstr
|
||
|| '\0' == fstr[0]
|
||
|| nullptr == permstr
|
||
|| '\0' == permstr[0])
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
FLAGNAMEENT *fp;
|
||
if ((fp = find_flag(fstr)) == nullptr)
|
||
{
|
||
cf_log_notfound(player, cmd, T("No such flag"), fstr);
|
||
return -1;
|
||
}
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
|
||
// Don't change the handlers on special things.
|
||
//
|
||
if ( (fbe->handler != fh_any)
|
||
&& (fbe->handler != fh_wizroy)
|
||
&& (fbe->handler != fh_wiz)
|
||
&& (fbe->handler != fh_god)
|
||
&& (fbe->handler != fh_restrict_player)
|
||
&& (fbe->handler != fh_privileged))
|
||
{
|
||
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM");
|
||
log_text(T("Cannot change access for flag: "));
|
||
log_text(fp->flagname);
|
||
ENDLOG;
|
||
|
||
notify(player, M_("Special flags cannot be modified with flag_access."));
|
||
|
||
return -1;
|
||
}
|
||
|
||
bool negate = false;
|
||
|
||
if ('!' == *permstr)
|
||
{
|
||
negate = true;
|
||
permstr++;
|
||
}
|
||
|
||
if (!strcmp(reinterpret_cast<char *>(permstr), "any"))
|
||
{
|
||
fbe->handler = fh_any;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "dark"))
|
||
{
|
||
if (negate)
|
||
{
|
||
fbe->listperm &= ~CA_GOD;
|
||
}
|
||
else
|
||
{
|
||
fbe->listperm |= CA_GOD;
|
||
}
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "hidden"))
|
||
{
|
||
if (negate)
|
||
{
|
||
fbe->listperm &= ~CA_WIZARD;
|
||
}
|
||
else
|
||
{
|
||
fbe->listperm |= CA_WIZARD;
|
||
}
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "royalty"))
|
||
{
|
||
fbe->handler = fh_wizroy;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "wizard"))
|
||
{
|
||
fbe->handler = fh_wiz;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "god"))
|
||
{
|
||
fbe->handler = fh_god;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "restrict_player"))
|
||
{
|
||
fbe->handler = fh_restrict_player;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "privileged"))
|
||
{
|
||
fbe->handler = fh_privileged;
|
||
}
|
||
else if (!strcmp(reinterpret_cast<char *>(permstr), "staff"))
|
||
{
|
||
fbe->handler = fh_staff;
|
||
}
|
||
else
|
||
{
|
||
cf_log_notfound(player, cmd, T("Flag access"), permstr);
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * convert_flags: convert a list of flag letters into its bit pattern.
|
||
* * Also set the type qualifier if specified and not already set.
|
||
*/
|
||
|
||
bool convert_flags(dbref player, UTF8 *flaglist, FLAGSET *fset, FLAG *p_type)
|
||
{
|
||
FLAG type = NOTYPE;
|
||
FLAGSET flagmask;
|
||
memset(&flagmask, 0, sizeof(flagmask));
|
||
int i;
|
||
|
||
UTF8 *s;
|
||
bool handled;
|
||
for (s = flaglist; *s; s++)
|
||
{
|
||
handled = false;
|
||
|
||
// Check for object type.
|
||
//
|
||
for (i = 0; i <= 7 && !handled; i++)
|
||
{
|
||
if ( object_types[i].lett == *s
|
||
&& !( ( (object_types[i].perm & CA_STAFF)
|
||
&& !Staff(player))
|
||
|| ( (object_types[i].perm & CA_ADMIN)
|
||
&& !WizRoy(player))
|
||
|| ( (object_types[i].perm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (object_types[i].perm & CA_GOD)
|
||
&& !God(player))))
|
||
{
|
||
if ( type != NOTYPE
|
||
&& type != i)
|
||
{
|
||
UTF8 *p = tprintf(M_("%c: Conflicting type specifications."),
|
||
*s);
|
||
notify(player, p);
|
||
return false;
|
||
}
|
||
type = i;
|
||
handled = true;
|
||
}
|
||
}
|
||
|
||
// Check generic flags.
|
||
//
|
||
if (handled)
|
||
{
|
||
continue;
|
||
}
|
||
FLAGNAMEENT *fp;
|
||
for (fp = gen_flag_names; fp->flagname && !handled; fp++)
|
||
{
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
if ( !fp->bPositive
|
||
|| fbe->flaglett == ' ')
|
||
{
|
||
continue;
|
||
}
|
||
if ( fbe->flaglett == *s
|
||
&& !( ( (fbe->listperm & CA_STAFF)
|
||
&& !Staff(player))
|
||
|| ( (fbe->listperm & CA_ADMIN)
|
||
&& !WizRoy(player))
|
||
|| ( (fbe->listperm & CA_WIZARD)
|
||
&& !Wizard(player))
|
||
|| ( (fbe->listperm & CA_GOD)
|
||
&& !God(player))))
|
||
{
|
||
flagmask.word[fbe->flagflag] |= fbe->flagvalue;
|
||
handled = true;
|
||
}
|
||
}
|
||
|
||
if (!handled)
|
||
{
|
||
notify(player,
|
||
tprintf(M_("%c: Flag unknown or not valid for specified object type"),
|
||
*s));
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Return flags to search for and type.
|
||
//
|
||
*fset = flagmask;
|
||
*p_type = type;
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
* ---------------------------------------------------------------------------
|
||
* * decompile_flags: Produce commands to set flags on target.
|
||
*/
|
||
|
||
void decompile_flags(dbref player, dbref thing, UTF8 *thingname)
|
||
{
|
||
// Report generic flags.
|
||
//
|
||
FLAGNAMEENT *fp;
|
||
for (fp = gen_flag_names; fp->flagname; fp++)
|
||
{
|
||
FLAGBITENT *fbe = fp->fbe;
|
||
|
||
// Only handle positive-sense entries.
|
||
// Skip if we shouldn't decompile this flag.
|
||
// Skip if this flag isn't set.
|
||
// Skip if we can't see this flag.
|
||
//
|
||
if ( !fp->bPositive
|
||
|| (fbe->listperm & CA_NO_DECOMP)
|
||
|| (db[thing].fs.word[fbe->flagflag] & fbe->flagvalue) == 0
|
||
|| !check_access(player, fbe->listperm))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// Report this flag.
|
||
//
|
||
notify(player, tprintf(T("@set %s=%s"), thingname, fp->flagname));
|
||
}
|
||
}
|
||
|
||
// do_flag: Rename flags or remove flag aliases.
|
||
// Based on RhostMUSH code.
|
||
//
|
||
static bool flag_rename(UTF8 *existing_flag_name, UTF8 *new_flag_name)
|
||
{
|
||
int existing_flag_name_length;
|
||
bool valid;
|
||
UTF8 *canonical_existing_flag_name = MakeCanonicalFlagName(existing_flag_name, &existing_flag_name_length, &valid);
|
||
if (valid)
|
||
{
|
||
const vector<UTF8> existing_name(canonical_existing_flag_name, canonical_existing_flag_name + existing_flag_name_length);
|
||
const auto it_existing = mudstate.flag_names_map.find(existing_name);
|
||
if (it_existing != mudstate.flag_names_map.end())
|
||
{
|
||
int new_flag_name_length;
|
||
UTF8* canonical_new_flag_name = MakeCanonicalFlagName(new_flag_name, &new_flag_name_length, &valid);
|
||
if (valid)
|
||
{
|
||
vector<UTF8> new_name(canonical_new_flag_name, canonical_new_flag_name + new_flag_name_length);
|
||
const auto it_new = mudstate.flag_names_map.find(new_name);
|
||
if ( it_new != mudstate.flag_names_map.end()
|
||
&& it_new->second == it_existing->second)
|
||
{
|
||
// New name is an alias for the same flag.
|
||
// Remove the alias so the rename can proceed.
|
||
//
|
||
mudstate.flag_names_map.erase(it_new);
|
||
}
|
||
|
||
if (mudstate.flag_names_map.find(new_name) == mudstate.flag_names_map.end())
|
||
{
|
||
FLAGNAMEENT* flag_name_entity = it_existing->second;
|
||
mudstate.flag_names_map.insert(make_pair(new_name, flag_name_entity));
|
||
if (flag_name_entity->flagname != flag_name_entity->pOrigName)
|
||
{
|
||
MEMFREE(flag_name_entity->flagname);
|
||
}
|
||
flag_name_entity->flagname = StringCloneLen(canonical_new_flag_name, new_flag_name_length);
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void do_flag(dbref executor, dbref caller, dbref enactor, int eval, int key, int nargs,
|
||
UTF8 *existing_flag_name, UTF8 *new_flag_name, const UTF8 *cargs[], int ncargs)
|
||
{
|
||
UNUSED_PARAMETER(caller);
|
||
UNUSED_PARAMETER(enactor);
|
||
UNUSED_PARAMETER(eval);
|
||
UNUSED_PARAMETER(cargs);
|
||
UNUSED_PARAMETER(ncargs);
|
||
|
||
if (key & FLAG_REMOVE)
|
||
{
|
||
if (nargs == 2)
|
||
{
|
||
notify(executor, M_("Extra argument ignored."));
|
||
}
|
||
int flag_name_length;
|
||
bool valid;
|
||
UTF8 *canonical_flag_name = MakeCanonicalFlagName(existing_flag_name, &flag_name_length, &valid);
|
||
if (valid)
|
||
{
|
||
const vector<UTF8> name(canonical_flag_name, canonical_flag_name + flag_name_length);
|
||
const auto it = mudstate.flag_names_map.find(name);
|
||
if (it != mudstate.flag_names_map.end())
|
||
{
|
||
FLAGNAMEENT* flag_name_entity = it->second;
|
||
|
||
if ( flag_name_entity->flagname != flag_name_entity->pOrigName
|
||
&& mux_stricmp(flag_name_entity->flagname, canonical_flag_name) == 0)
|
||
{
|
||
MEMFREE(flag_name_entity->flagname);
|
||
flag_name_entity->flagname = const_cast<UTF8*>(flag_name_entity->pOrigName);
|
||
mudstate.flag_names_map.erase(it);
|
||
notify(executor, tprintf(M_("Flag name ‘%s’ removed from the hash table."), canonical_flag_name));
|
||
}
|
||
else
|
||
{
|
||
notify(executor, M_("Error: You can’t remove the present flag name from the hash table."));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
notify(executor, M_("Error: Bad flagname given or flag not found."));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
notify(executor, M_("Error: Bad flagname given or flag not found."));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (nargs < 2)
|
||
{
|
||
notify(executor, M_("You must specify a flag and a name."));
|
||
return;
|
||
}
|
||
if (flag_rename(existing_flag_name, new_flag_name))
|
||
{
|
||
notify(executor, M_("Flag name changed."));
|
||
}
|
||
else
|
||
{
|
||
notify(executor, M_("Error: Bad flagname given or flag not found."));
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------
|
||
* cf_flag_name: Rename a flag. Counterpart to @flag.
|
||
*/
|
||
|
||
CF_HAND(cf_flag_name)
|
||
{
|
||
UNUSED_PARAMETER(vp);
|
||
UNUSED_PARAMETER(pExtra);
|
||
UNUSED_PARAMETER(nExtra);
|
||
UNUSED_PARAMETER(player);
|
||
UNUSED_PARAMETER(cmd);
|
||
|
||
string_token st(str, T(" \t=,"));
|
||
UTF8 *flagstr = st.parse();
|
||
UTF8 *namestr = st.parse();
|
||
|
||
if ( !flagstr
|
||
|| !*flagstr
|
||
|| !namestr
|
||
|| !*namestr)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (flag_rename(flagstr, namestr))
|
||
{
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|