Skip to content

Commit

Permalink
Merge pull request #713 from wyld-sw/unified-locking
Browse files Browse the repository at this point in the history
Unifies setting and clearing lock properties.
  • Loading branch information
tanabi authored Jan 8, 2024
2 parents 71f9d41 + b2d4ae2 commit 4748f06
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 107 deletions.
24 changes: 12 additions & 12 deletions include/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,25 +303,27 @@ extern char match_cmdname[BUFFER_LEN];
* A thin wrappera round @see get_property_lock
*
* @param x the object to look up
* @param y the lock to look up
* @return the struct boolexp object or TRUE_BOOLEXP
*/
#define GETLOCK(x) (get_property_lock(x, MESGPROP_LOCK))
#define GETLOCK(x,y) (get_property_lock(x, y))

/**
* Sets a lock from a boolexp structure
*
* Typically you would take the return value from @see parse_boolexp
* and then use it as the 'y' parameter here. The object modification
* and then use it as the 'z' parameter here. The object modification
* timestamp is updated.
*
* @param x the object to set the lock on
* @param y the struct boolexp to use as the lock value.
* @param y the lock to modify
* @param z the struct boolexp to use as the lock value.
*/
#define SETLOCK(x,y) { \
#define SETLOCK(x,y,z) { \
PData mydat; \
mydat.flags = PROP_LOKTYP; \
mydat.data.lok = y; \
set_property(x, MESGPROP_LOCK, &mydat); \
mydat.data.lok = z; \
set_property(x, y, &mydat); \
ts_modifyobject(x); \
}

Expand All @@ -331,14 +333,12 @@ extern char match_cmdname[BUFFER_LEN];
* Also updates object modification timestamp.
*
* @param x the object to clear the lock on
* @param y the lock to clear
*/
#define CLEARLOCK(x) { \
PData mydat; \
mydat.flags = PROP_LOKTYP; \
mydat.data.lok = TRUE_BOOLEXP; \
set_property(x, MESGPROP_LOCK, &mydat); \
DBDIRTY(x); \
#define CLEARLOCK(x,y) { \
remove_property(x, y); \
ts_modifyobject(x); \
DBDIRTY(x); \
}

/**
Expand Down
24 changes: 21 additions & 3 deletions include/props.h
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,25 @@ void remove_property_list(dbref player, int all);
*/
void remove_property_nofetch(dbref player, const char *type);

/**
* This helper function 'compiles' the lock and, if valid, sets the
* property on the propname. Otherwise, an error is emitted to the user.
*
* The last parameter controls if messages should be displayed.
*
* @param descr The player's descriptor
* @param player The player receiving any messages
* @param object The object we are locking or unlocking
* @param propname The name of the prop to set
* @param proplabel This is used for messaging and is the type of lock.
* The first letter should be capitalized. For instance, "Lock",
* "Ownership Lock", etc.
* @param keyvalue The lock itself or "" to clear the lock.
* @param silent boolean if true, do not display anything.
*/
int _set_lock(int descr, dbref player, dbref object, const char *propname,
const char *proplabel, const char *keyvalue, int silent);

/**
* This command is the underpinning of \@lock, \@flock, \@linklock and \@chlock.
* Please note that part of this function's functionality relies on the
Expand All @@ -1128,10 +1147,9 @@ void remove_property_nofetch(dbref player, const char *type);
* If there is an = but no string after the equals (i.e. '\@lock x='),
* then it clears the lock
*
* Otherwise, the lock is 'compiled' and, if valid, set on the property
* propname. Otherwise, an error is emitted to the user.
* Otherwise, this hands off the actual lock-setting to _set_lock.
*
* @param descr Descriptor
* @param descr The player's descriptor
* @param player The player doing the command
* @param objname The name of the object we are locking or ""
* @param propname The name of the prop to set
Expand Down
4 changes: 2 additions & 2 deletions src/boolexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ test_lock(int descr, dbref player, dbref thing, const char *lockprop)
{
struct boolexp *lokptr;

lokptr = get_property_lock(thing, lockprop);
lokptr = GETLOCK(thing, lockprop);
return (eval_boolexp(descr, player, lokptr, thing));
}

Expand All @@ -907,7 +907,7 @@ test_lock_false_default(int descr, dbref player, dbref thing, const char *lockpr
{
struct boolexp *lok;

lok = get_property_lock(thing, lockprop);
lok = GETLOCK(thing, lockprop);

if (lok == TRUE_BOOLEXP)
return 0;
Expand Down
14 changes: 7 additions & 7 deletions src/look.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,25 +763,25 @@ do_examine(int descr, dbref player, const char *name, const char *dir)
if (GETDESC(thing))
notify(player, GETDESC(thing));

if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_LOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_LINKLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_LINKLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Link_OK Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_CHLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_CHLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Chown_OK Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_CONLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_CONLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Container Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_FLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_FLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Force Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_READLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_READLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Read Key: %s", temp);

if (strcmp(temp = unparse_boolexp(player, get_property_lock(thing, MESGPROP_OWNLOCK), 1), PROP_UNLOCKED_VAL))
if (strcmp(temp = unparse_boolexp(player, GETLOCK(thing, MESGPROP_OWNLOCK), 1), PROP_UNLOCKED_VAL))
notifyf(player, "Ownership Key: %s", temp);

if (GETSUCC(thing)) {
Expand Down
2 changes: 1 addition & 1 deletion src/mfuns2.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ mfn_testlock(MFUNARGS)
ABORT_MPI("TESTLOCK", "Permission denied. (arg2)");
}

lok = get_property_lock(obj, argv[1]);
lok = GETLOCK(obj, argv[1]);

if (argc > 3 && lok == TRUE_BOOLEXP)
return (argv[3]);
Expand Down
41 changes: 3 additions & 38 deletions src/p_db.c
Original file line number Diff line number Diff line change
Expand Up @@ -2416,49 +2416,14 @@ prim_recycle(PRIM_PROTOTYPE)
recycle(fr->descr, player, result);
}

/**
* Sets a lock (with the given key) on an object.
*
* Returns 0 if the key is not well-formed, otherwise 1.
*
* @private
* @param descr the player's descriptor
* @param player the player requesting the change
* @param thing dbref of the target object
* @param keyname string that represents the pass condition
*/
static int
setlockstr(int descr, dbref player, dbref thing, const char *keyname)
{
/**
* @TODO Should this logic be exposed to the various lock
* commands?
*/
struct boolexp *key;

if (*keyname != '\0') {
key = parse_boolexp(descr, player, keyname, 0);
if (key == TRUE_BOOLEXP) {
return 0;
} else {
/* everything ok, do it */
SETLOCK(thing, key);
return 1;
}
} else {
CLEARLOCK(thing);
return 1;
}
}

/**
* Implementation of MUF SETLOCKSTR
*
* Consumes a dbref and a string, sets the lock accordingly, and returns
* a boolean representing success or failure. Needs MUCKER level 4 to
* bypass basic ownership checks.
*
* @see setlockstr
* @see _set_lock
*
* @param player the player running the MUF program
* @param program the program being run
Expand All @@ -2485,7 +2450,7 @@ prim_setlockstr(PRIM_PROTOTYPE)
if ((mlev < 4) && !permissions(ProgUID, ref))
abort_interp("Permission denied.");

result = setlockstr(fr->descr, player, ref, DoNullInd(oper1->data.string));
result = _set_lock(fr->descr, player, ref, MESGPROP_LOCK, "Lock", DoNullInd(oper1->data.string), 1);

CLEAR(oper1);
CLEAR(oper2);
Expand Down Expand Up @@ -2526,7 +2491,7 @@ prim_getlockstr(PRIM_PROTOTYPE)
abort_interp("Permission denied.");

{
const char *tmpstr = (char *) unparse_boolexp(player, GETLOCK(ref), 0);
const char *tmpstr = (char *) unparse_boolexp(player, GETLOCK(ref, MESGPROP_LOCK), 0);

CLEAR(oper1);
PushString(tmpstr);
Expand Down
4 changes: 2 additions & 2 deletions src/predicates.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ could_doit(int descr, dbref player, dbref thing)
dest = *(DBFETCH(thing)->sp.exit.dest);

if (dest == NIL)
return (eval_boolexp(descr, player, GETLOCK(thing), thing));
return (eval_boolexp(descr, player, GETLOCK(thing, MESGPROP_LOCK), thing));

if (Typeof(dest) == TYPE_PLAYER) {
/* Check for additional restrictions related to player dests */
Expand Down Expand Up @@ -208,7 +208,7 @@ could_doit(int descr, dbref player, dbref thing)
}

/* Check the @lock on the thing, as a final test. */
return (eval_boolexp(descr, player, GETLOCK(thing), thing));
return (eval_boolexp(descr, player, GETLOCK(thing, MESGPROP_LOCK), thing));
}

/**
Expand Down
115 changes: 74 additions & 41 deletions src/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -2271,7 +2271,7 @@ reflist_find(dbref obj, const char *propname, dbref tofind)
* should be somethinglike "Object Description", "Drop Message", etc.
* and is used to emit messages.
*
* @param descr Descriptor
* @param descr The player's descriptor
* @param player The player doing the action
* @param objname The object name to match, or "" for the player.
* @param propname The property we are going to set, like "_/de"
Expand Down Expand Up @@ -2306,6 +2306,61 @@ set_standard_property(int descr, dbref player, const char *objname,
}
}

/**
* This helper function 'compiles' the lock and, if valid, sets the
* property on the propname. Otherwise, an error is emitted to the user.
*
* The last parameter controls if messages should be displayed.
*
* @param descr The player's descriptor
* @param player The player receiving any messages
* @param object The object we are locking or unlocking
* @param propname The name of the prop to set
* @param proplabel This is used for messaging and is the type of lock.
* The first letter should be capitalized. For instance, "Lock",
* "Ownership Lock", etc.
* @param keyvalue The lock itself or "" to clear the lock.
* @param silent boolean if true, do not display anything.
*/
int
_set_lock(int descr, dbref player, dbref object, const char *propname,
const char *proplabel, const char *keyvalue, int silent) {
struct boolexp *key;

/* If there is no key value, clear the lock. You can see this
* if you type: @lock whatever=
*/
if (!*keyvalue) {
CLEARLOCK(object, propname);

if (!silent) {
notifyf_nolisten(player, "%s cleared.", proplabel);
}

return 1;
}

/* Parse the lock */
key = parse_boolexp(descr, player, keyvalue, 0);

if (key == TRUE_BOOLEXP) {
if (!silent) {
notifyf_nolisten(player, "I don't understand that key.");
}

return 0;
}

/* If it all works out, set the property */
SETLOCK(object, propname, key);

if (!silent) {
notifyf_nolisten(player, "%s set.", proplabel);
}

return 1;
}

/**
* This command is the underpinning of @lock, @flock, @linklock and @chlock.
* Please note that part of this function's functionality relies on the
Expand All @@ -2322,8 +2377,9 @@ set_standard_property(int descr, dbref player, const char *objname,
* If there is an = but no string after the equals (i.e. '@lock x='),
* then it clears the lock
*
* Otherwise, the lock is 'compiled' and, if valid, set on the property
* propname. Otherwise, an error is emitted to the user.
* Otherwise, this hands off the actual lock-setting to _set_lock.
*
* @see _set_lock
*
* @param descr Descriptor
* @param player The player doing the command
Expand All @@ -2340,7 +2396,6 @@ set_standard_lock(int descr, dbref player, const char *objname,
const char *keyvalue)
{
dbref object;
PData property;
struct boolexp *key;

/* The presence of '=' (ARG_DELIMITER) in the arguments indicates if
Expand All @@ -2354,49 +2409,27 @@ set_standard_lock(int descr, dbref player, const char *objname,
if (!*objname) {
object = player;
} else {
/* I believe this emits the error message if there is no match.
*/
/* This emits the error message if there is no match. */
object = match_controlled(descr, player, objname);
}

if (object != NOTHING) { /* If we found an object */
if (!set) { /* If there was no =, then display lock status.
* You can see this message if you just type '@lock'
* by itself.
*/
notifyf_nolisten(
player, "%s: %s", proplabel,
unparse_boolexp(player, get_property_lock(object, propname), 1)
);

return;
}

/* If there is no key value, clear the lock. You can see this
* if you type: @lock whatver=
*/
if (!*keyvalue) {
remove_property(object, propname);
ts_modifyobject(object);
notifyf_nolisten(player, "%s cleared.", proplabel);
return;
}

/* Parse the lock */
key = parse_boolexp(descr, player, keyvalue, 0);
if (object == NOTHING) { /* if we didn't find an object */
return;
}

if (key == TRUE_BOOLEXP) {
notifyf_nolisten(player, "I don't understand that key.");
return;
}
if (!set) { /* If there was no =, then display lock status.
* You can see this message if you just type '@lock'
* by itself.
*/
notifyf_nolisten(
player, "%s: %s", proplabel,
unparse_boolexp(player, GETLOCK(object, propname), 1)
);

/* If it all works out, set the property */
property.flags = PROP_LOKTYP;
property.data.lok = key;
set_property(object, propname, &property);
ts_modifyobject(object);
notifyf_nolisten(player, "%s set.", proplabel);
return;
}

(void) _set_lock(descr, player, object, propname, proplabel, keyvalue, 0);
}

/**
Expand Down
Loading

0 comments on commit 4748f06

Please sign in to comment.