From: Ari Johnson Date: Wed, 21 Feb 2007 00:19:23 +0000 (+0000) Subject: Players may have multiple aliases; added alias() and fullalias() functions X-Git-Tag: 0.73~160 X-Git-Url: https://git.theari.com/?a=commitdiff_plain;h=fc461e484c3a6fd983a341507584ff95facdadf7;p=cobramush.git Players may have multiple aliases; added alias() and fullalias() functions --- diff --git a/game/mushcnf.dst b/game/mushcnf.dst index 17a83b6..39801bb 100644 --- a/game/mushcnf.dst +++ b/game/mushcnf.dst @@ -399,6 +399,11 @@ log_wipe_passwd zap! # actual maximum length you want. player_name_len 16 +# The maximum number of aliases a player may have simultaneously. +# Setting this to 0 disables aliases. To allow an unlimited number +# of aliases, set this to 4000 or so. +max_aliases 3 + # Limit the number of objects players can own. use_quota yes diff --git a/game/txt/hlp/cobra_cmd.hlp b/game/txt/hlp/cobra_cmd.hlp index 21fc1c6..b2da387 100644 --- a/game/txt/hlp/cobra_cmd.hlp +++ b/game/txt/hlp/cobra_cmd.hlp @@ -267,19 +267,29 @@ See also: leave, @leave, @oleave, ACTION LISTS See also: leave, @lfail, @olfail, ACTION LISTS & @alias - @alias = - - @alias is a special attribute. When a player sets an @alias, he is - effectively giving himself a secondary name; he can be paged by his - @alias, and matched with *, and all other game functions which - look up player names will also accept the alias. The attribute is - visible to all players. - - Aliases cannot be longer than the limit allowed for player names, + @alias =;[;[;[...]]] + + @alias is a special attribute that lists a player's names; players + can be paged by their aliases, matched with *, and all other game + functions which look up player names will also accept an alias. + The attribute is visible to all players. + + A list of aliases, separated by semicolons, may be provided. + Players should include their usual @name in the alias list, because + the @name command allows setting name to any alias in the list. + The number of aliases allowed in the list may be limited by + the game's administrators through the 'max_aliases' @config parameter. + + If the page_aliases config directive is on, the first alias in the + list is returned along with the player's name. + + Each alias cannot be longer than the limit allowed for player names, cannot contain spaces, and must be unique -- no other player may have the same alias or name as any other player's alias or name. @alias has no effect on non-players. + + See also: @name, alias(), fullalias() & @allhalt @allhalt @@ -2202,9 +2212,15 @@ See also: go, @omove, @oxmove, @amove names, the name should be enclosed in quotes: @name me = "James Bond" + Players can change their name to any name not in use by another + player; players may "reserve" a set of names for their use by + setting them in their @alias. + Changing the name of will cause object to execute its ONAME and ANAME. The old name will be passed at %0 to these; the new name will be passed as %1. + + See also: @alias & @newpassword @newpassword = @@ -2802,6 +2818,10 @@ See also: @wall, @wizwall See "help @search3" for more. & @search3 + If =MINDB, only objects with dbrefs of or + higher will be listed. If =MAXDB, only objects with dbrefs + of or lower will be listed. + For the class TYPE=PLAYER, and for PLAYER=, anyone may obtain information on any player. In all other cases, only Directors may obtain information about other players. This is computationally @@ -2814,7 +2834,7 @@ See also: @wall, @wizwall @search Joe eval=1,100,200 <-- list objects from #100-#200 owned by Joe. @search eval=gt(money(##),10) <-- list all objects owned by me worth more than 10 coins. - + See also: lsearch, lsearchr & @select @select =,[,,]...[,] diff --git a/hdrs/conf.h b/hdrs/conf.h index 65361d9..24b3299 100644 --- a/hdrs/conf.h +++ b/hdrs/conf.h @@ -52,6 +52,8 @@ /* delimiter for lists of exit aliases */ #define EXIT_DELIMITER ';' +/* delimiter for lists of player name aliases */ +#define ALIAS_DELIMITER ';' #define QUIT_COMMAND "QUIT" #define WHO_COMMAND "WHO" @@ -221,6 +223,7 @@ struct options_table { char ip_addr[64]; /**< What ip address should the server bind to? */ char ssl_ip_addr[64]; /**< What ip address should the server bind to? */ int player_name_spaces; /**< Can players have multiword names? */ + int max_aliases; /**< Maximum allowed aliases per player */ int forking_dump; /**< Should we fork to dump? */ int restrict_building; /**< Is the builder power required to build? */ int free_objects; /**< If builder power is required, can you create without it? */ @@ -403,6 +406,7 @@ int cf_time(const char *opt, const char *val, void *loc, int maxval, #define RESTRICTED_BUILDING (options.restrict_building) #define NO_FORK (!options.forking_dump) #define PLAYER_NAME_SPACES (options.player_name_spaces) +#define MAX_ALIASES (options.max_aliases) #define SAFER_UFUN (options.safer_ufun) #define NOISY_WHISPER (options.noisy_whisper) #define POSSESSIVE_GET (options.possessive_get) diff --git a/hdrs/externs.h b/hdrs/externs.h index d7567e6..408a4b8 100644 --- a/hdrs/externs.h +++ b/hdrs/externs.h @@ -304,6 +304,7 @@ extern char *mush_crypt(const char *key); /* From player.c */ extern int password_check(dbref player, const char *password); extern dbref lookup_player(const char *name); +extern dbref lookup_player_name(const char *name); /* from player.c */ extern dbref create_player(const char *name, const char *password, const char *host, const char *ip); @@ -319,8 +320,11 @@ extern int is_strict_integer(const char *str); /* From plyrlist.c */ void clear_players(void); -void add_player(dbref player, const char *alias); +void add_player(dbref player); +void add_player_alias(dbref player, const char *alias); void delete_player(dbref player, const char *alias); +void reset_player_list(dbref player, const char *oldname, const char *oldalias, + const char *name, const char *alias); /* From predicat.c */ extern int pay_quota(dbref, int); @@ -354,7 +358,8 @@ extern int get_current_quota(dbref who); extern void change_quota(dbref who, int payment); extern int ok_name(const char *name); extern int ok_command_name(const char *name); -extern int ok_player_name(const char *name, dbref player); +extern int ok_player_name(const char *name, dbref player, dbref thing); +extern int ok_player_alias(const char *alias, dbref player, dbref thing); extern int ok_password(const char *password); extern int ok_tag_attribute(dbref player, char *params); extern dbref parse_match_possessor(dbref player, const char **str); @@ -561,6 +566,8 @@ extern int safe_ansi_string2(ansi_string *as, size_t start, size_t len, char *bu const char *check) __attribute_malloc__; extern void mush_free(Malloc_t RESTRICT ptr, const char *RESTRICT check); extern long get_random_long(long low, long high); + extern char *fullalias(dbref it); + extern char *shortalias(dbref it); extern char *shortname(dbref it); extern dbref absolute_room(dbref it); int can_interact(dbref from, dbref to, int type); diff --git a/src/attrib.c b/src/attrib.c index 9300272..5ca7050 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1711,20 +1711,18 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, upcasestr(name); if (!strcmp(name, "ALIAS") && IsPlayer(thing)) { old = atr_get_noparent(thing, "ALIAS"); + tbuf1[0] = '\0'; if (old) { /* Old alias - we're allowed to change to a different case */ strcpy(tbuf1, atr_value(old)); - if (s - && (!*s - || (strcasecmp(s, tbuf1) && !ok_player_name(s, player)))) { + if (s && (!*s || (strcasecmp(s, tbuf1) + && !ok_player_alias(s, player, thing)))) { notify(player, T("That is not a valid alias.")); return -1; } - if (Can_Write_Attr(player, thing, old)) - delete_player(thing, tbuf1); } else { /* No old alias */ - if (s && *s && !ok_player_name(s, player)) { + if (s && *s && !ok_player_alias(s, player, thing)) { notify(player, T("That is not a valid alias.")); return -1; } @@ -1794,12 +1792,11 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, return 0; } if (!strcmp(name, "ALIAS") && IsPlayer(thing)) { - if (s && *s) { - add_player(thing, s); + reset_player_list(thing, NULL, tbuf1, NULL, s); + if (s && *s) notify(player, T("Alias set.")); - } else { + else notify(player, T("Alias removed.")); - } return 1; } else if (!strcmp(name, "LISTEN")) { if (IsRoom(thing)) diff --git a/src/conf.c b/src/conf.c index 2d49958..fe5a59a 100644 --- a/src/conf.c +++ b/src/conf.c @@ -247,6 +247,8 @@ COBRA_CONF conftable[] = { {"player_name_spaces", cf_bool, &options.player_name_spaces, 2, 0, "cosmetic"} , + {"max_aliases", cf_int, &options.max_aliases, -1, 0, "limits"} + , {"ansi_names", cf_bool, &options.ansi_names, 2, 0, "cosmetic"} , {"only_ascii_in_names", cf_bool, &options.ascii_names, 2, 0, "cosmetic"} @@ -1166,6 +1168,7 @@ conf_default_set(void) strcpy(options.ip_addr, ""); strcpy(options.ssl_ip_addr, ""); options.player_name_spaces = 0; + options.max_aliases = 3; options.forking_dump = 1; options.restrict_building = 0; options.free_objects = 1; diff --git a/src/db.c b/src/db.c index 3334175..2ddd94b 100644 --- a/src/db.c +++ b/src/db.c @@ -1588,7 +1588,7 @@ db_read_oldstyle(FILE * f) } /* check to see if it's a player */ if (IsPlayer(i)) { - add_player(i, NULL); + add_player(i); clear_flag_internal(i, "CONNECTED"); } break; @@ -1937,7 +1937,7 @@ db_read(FILE * f) i); } if (IsPlayer(i)) { - add_player(i, NULL); + add_player(i); clear_flag_internal(i, "CONNECTED"); } } @@ -2122,7 +2122,7 @@ create_minimal_db(void) add_folder_name(god, 0, "inbox"); #endif PUSH(god, Contents(start_room)); - add_player(god, NULL); + add_player(god); s_Pennies(god, START_BONUS); local_data_create(god); current_state.players++; diff --git a/src/function.c b/src/function.c index 8ed66b2..8184a30 100644 --- a/src/function.c +++ b/src/function.c @@ -273,6 +273,7 @@ FUNTAB flist[] = { {"ACCNAME", fun_accname, 1, 1, FN_REG}, {"ADD", fun_add, 2, INT_MAX, FN_REG}, {"AFTER", fun_after, 2, 2, FN_REG}, + {"ALIAS", fun_alias, 1, 2, FN_REG}, {"ALIGN", fun_align, 2, INT_MAX, FN_REG}, {"ALLOF", fun_allof, 2, INT_MAX, FN_NOPARSE}, {"ALPHAMAX", fun_alphamax, 1, INT_MAX, FN_REG}, @@ -378,6 +379,7 @@ FUNTAB flist[] = { {"FOREACH", fun_foreach, 2, 4, FN_REG}, {"FRACTION", fun_fraction, 1, 1, FN_REG}, {"FUNCTIONS", fun_functions, 0, 0, FN_REG}, + {"FULLALIAS", fun_fullalias, 1, 1, FN_REG}, {"FULLNAME", fun_fullname, 1, 1, FN_REG}, {"GET", fun_get, 1, 1, FN_REG}, {"GET_EVAL", fun_get_eval, 1, 1, FN_REG}, diff --git a/src/fundb.c b/src/fundb.c index 5cc8e04..1ff3d5b 100644 --- a/src/fundb.c +++ b/src/fundb.c @@ -1419,6 +1419,42 @@ FUNCTION(fun_owner) } } +/* ARGSUSED */ +FUNCTION(fun_alias) +{ + dbref it; + + it = match_thing(executor, args[0]); + if (!GoodObject(it)) + safe_str(T(e_notvis), buff, bp); + + /* Support changing alias via function if side-effects are enabled */ + if (nargs == 2) { + if (!command_check_byname(executor, "ATTRIB_SET") + || fun->flags & FN_NOSIDEFX) { + safe_str(T(e_perm), buff, bp); + return; + } + if (!FUNCTION_SIDE_EFFECTS) + safe_str(T(e_disabled), buff, bp); + else + do_set_atr(it, "ALIAS", args[1], executor, 0); + return; + } else { + safe_str(shortalias(it), buff, bp); + } +} + +/* ARGSUSED */ +FUNCTION(fun_fullalias) +{ + dbref it = match_thing(executor, args[0]); + if (GoodObject(it)) + safe_str(fullalias(it), buff, bp); + else + safe_str(T(e_notvis), buff, bp); +} + /* ARGSUSED */ FUNCTION(fun_name) { diff --git a/src/funmisc.c b/src/funmisc.c index df20f50..bb317fe 100644 --- a/src/funmisc.c +++ b/src/funmisc.c @@ -54,7 +54,7 @@ FUNCTION(fun_valid) else if (!strcasecmp(args[0], "attrname")) safe_boolean(good_atr_name(upcasestr(args[1])), buff, bp); else if (!strcasecmp(args[0], "playername")) - safe_boolean(ok_player_name(args[1], executor), buff, bp); + safe_boolean(ok_player_name(args[1], executor, executor), buff, bp); else if (!strcasecmp(args[0], "password")) safe_boolean(ok_password(args[1]), buff, bp); else if (!strcasecmp(args[0], "command")) diff --git a/src/game.c b/src/game.c index 316dc02..20b57df 100644 --- a/src/game.c +++ b/src/game.c @@ -695,7 +695,7 @@ do_restart(void) bp = buf; safe_str(atr_value(s), buf, &bp); *bp = '\0'; - add_player(thing, buf); + add_player_alias(thing, buf); } } } diff --git a/src/player.c b/src/player.c index e904b5c..112264d 100644 --- a/src/player.c +++ b/src/player.c @@ -201,7 +201,7 @@ dbref create_guest(const char *host, const char *ip) { gst_id = NOTHING; strncpy(guest_name, T(GUEST_PREFIX), BUFFER_LEN-1); strcat(guest_name, GUEST_NUMBER(i+1)); - if(ok_player_name(guest_name, NOTHING)) + if(ok_player_name(guest_name, NOTHING, NOTHING)) break; else if((gst_id = lookup_player(guest_name)) != NOTHING && !Connected(gst_id)) break; @@ -247,7 +247,7 @@ create_player(const char *name, const char *password, const char *host, const char *ip) { dbref player; - if (!ok_player_name(name, NOTHING)) { + if (!ok_player_name(name, NOTHING, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed creation (bad name) from %s"), host); return NOTHING; } @@ -301,7 +301,7 @@ email_register_player(const char *name, const char *email, const char *host, dbref player; FILE *fp; - if (!ok_player_name(name, NOTHING)) { + if (!ok_player_name(name, NOTHING, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed registration (bad name) from %s"), host); return NOTHING; } @@ -450,7 +450,7 @@ make_player(const char *name, const char *password, const char *host, /* link him to PLAYER_START */ PUSH(player, Contents(PLAYER_START)); - add_player(player,NULL); + add_player(player); add_lock(GOD, player, Basic_Lock, parse_boolexp(player, "=me", Basic_Lock), -1); add_lock(GOD, player, Enter_Lock, parse_boolexp(player, "=me", Basic_Lock), diff --git a/src/plyrlist.c b/src/plyrlist.c index 5e13d50..c941715 100644 --- a/src/plyrlist.c +++ b/src/plyrlist.c @@ -19,6 +19,7 @@ #include "mushdb.h" #include "dbdefs.h" #include "flags.h" +#include "attrib.h" #include "htab.h" #include "confmagic.h" @@ -49,19 +50,45 @@ clear_players(void) /** Add a player to the player list htab. * \param player dbref of player to add. - * \param alias name to use as hash table key for player, if given. */ void -add_player(dbref player, const char *alias) +add_player(dbref player) { long tmp; tmp = player; if (!hft_initialized) init_hft(); - if (alias) - hashadd(strupper(alias), (void *) tmp, &htab_player_list); - else - hashadd(strupper(Name(player)), (void *) tmp, &htab_player_list); + hashadd(strupper(Name(player)), (void *) tmp, &htab_player_list); +} + +/** Add a player's alias list to the player list htab. + * \param player dbref of player to add. + * \param alias list of names ot use as hash table keys for player, + * semicolon-separated. + */ +void +add_player_alias(dbref player, const char *alias) +{ + long tmp; + char tbuf1[BUFFER_LEN], *s, *sp; + if (!hft_initialized) + init_hft(); + if (!alias) { + add_player(player); + return; + } + strncpy(tbuf1, alias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + s = trim_space_sep(tbuf1, ALIAS_DELIMITER); + while (s) { + sp = split_token(&s, ALIAS_DELIMITER); + while (sp && *sp && *sp == ' ') + sp++; + if (sp && *sp) { + tmp = player; + hashadd(strupper(sp), (void *) tmp, &htab_player_list); + } + } } /** Look up a player in the player list htab (or by dbref). @@ -72,8 +99,6 @@ dbref lookup_player(const char *name) { int p; - void *hval; - long tmp; if (!name || !*name) return NOTHING; @@ -86,6 +111,18 @@ lookup_player(const char *name) } if (*name == LOOKUP_TOKEN) name++; + return lookup_player_name(name); +} + +/** Look up a player in the player list htab only. + * \param name name of player to find. + * \return dbref of player, or NOTHING. + */ +dbref +lookup_player_name(const char *name) +{ + long tmp; + void *hval; hval = hashfind(strupper(name), &htab_player_list); if (!hval) return NOTHING; @@ -100,6 +137,7 @@ lookup_player(const char *name) */ } + /** Remove a player from the player list htab. * \param player dbref of player to remove. * \param alias key to remove if given. @@ -107,8 +145,75 @@ lookup_player(const char *name) void delete_player(dbref player, const char *alias) { - if (alias) - hashdelete(strupper(alias), &htab_player_list); - else + if (!hft_initialized) { + init_hft(); + return; + } + if (alias) { + /* This could be a compound alias, in which case we need to delete + * them all, but we shouldn't delete the player's own name! + */ + char tbuf1[BUFFER_LEN], *s, *sp; + strncpy(tbuf1, alias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + s = trim_space_sep(tbuf1, ALIAS_DELIMITER); + while (s) { + sp = split_token(&s, ALIAS_DELIMITER); + while (sp && *sp && *sp == ' ') + sp++; + if (sp && *sp && strcasecmp(sp, Name(player))) + hashdelete(strupper(sp), &htab_player_list); + } + } else hashdelete(strupper(Name(player)), &htab_player_list); } + +/** Reset all of a player's player list entries (names/aliases). + * This is called when a player changes name or alias. + * We remove all their old entries, and add back their new ones. + * \param player dbref of player + * \param oldname player's former name (NULL if not changing) + * \param oldalias player's former aliases (NULL if not changing) + * \param name player's new name + * \param alias player's new aliases + */ +void +reset_player_list(dbref player, const char *oldname, const char *oldalias, + const char *name, const char *alias) +{ + char tbuf1[BUFFER_LEN]; + char tbuf2[BUFFER_LEN]; + if (!oldname) { + oldname = Name(player); + name = Name(player); + } + if (oldalias) { + strncpy(tbuf1, oldalias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + if (alias) { + strncpy(tbuf2, alias, BUFFER_LEN - 1); + tbuf2[BUFFER_LEN - 1] = '\0'; + } else { + tbuf2[0] = '\0'; + } + } else { + /* We are not changing aliases, just name, but we need to get the + * aliases anyway, since we may change name to something that's + * in the alias, and thus must not be deleted. + */ + ATTR *a = atr_get_noparent(player, "ALIAS"); + if (a) { + strncpy(tbuf1, atr_value(a), BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + } else { + tbuf1[0] = '\0'; + } + strcpy(tbuf2, tbuf1); + } + /* Delete all the old stuff */ + delete_player(player, tbuf1); + delete_player(player, NULL); + /* Add in the new stuff */ + add_player_alias(player, name); + add_player_alias(player, tbuf2); +} diff --git a/src/predicat.c b/src/predicat.c index b5f4721..5e66ba6 100644 --- a/src/predicat.c +++ b/src/predicat.c @@ -785,21 +785,23 @@ ok_name(const char *n) && strcasecmp((char *) name, "here")); } -/** Is a name a valid player name? +/** Is a name a valid player name when applied by player to thing? * Player names must be valid object names, but also not forbidden (unless * the player is a wizard). They are * subject to a different length limit, and subject to more stringent * restrictions on valid characters. Finally, it can't be the same as - * an existing player name or alias. + * an existing player name or alias unless it's one of theirs. * \param name name to check. * \param player player for permission checks. + * \param thing player who will get the name. * \retval 1 name is valid for players. * \retval 0 name is not valid for players. */ int -ok_player_name(const char *name, dbref player) +ok_player_name(const char *name, dbref player, dbref thing) { const unsigned char *scan, *good; + dbref lookup; if (!ok_name(name) || (forbidden_name(name) && !(GoodObject(player) && Director(player))) @@ -816,9 +818,47 @@ ok_player_name(const char *name, dbref player) return 0; } - return (lookup_player(name) == NOTHING); + lookup = lookup_player(name); + return ((lookup == NOTHING) || (lookup == thing)); } + +/** Is a alias a valid player alias-list for thing? + * It must be a semicolon-separated list of valid player names + * with no more than than MAX_ALIASES names, if the player isn't + * a wizard. + * \param alias list to check. + * \param player player for permission checks. + * \param thing player who is being aliased. + * \retval 1 alias is valid for players. + * \retval 0 alias is not valid for players. + */ +int +ok_player_alias(const char *alias, dbref player, dbref thing) +{ + char tbuf1[BUFFER_LEN], *s, *sp; + int cnt = 0; + + if (!alias || !*alias) + return 0; + + strncpy(tbuf1, alias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + s = trim_space_sep(tbuf1, ALIAS_DELIMITER); + while (s) { + sp = split_token(&s, ALIAS_DELIMITER); + while (sp && *sp && *sp == ' ') + sp++; + if (!sp || !*sp) + return 0; /* No null aliases */ + if (!ok_player_name(sp, player, thing)) + return 0; + cnt++; + } + return ((cnt <= MAX_ALIASES) || Director(player)); +} + + /** Is a password acceptable? * Acceptable passwords must be non-null and must contain only * printable characters and no whitespace. diff --git a/src/set.c b/src/set.c index 53780a1..d06ec83 100644 --- a/src/set.c +++ b/src/set.c @@ -114,9 +114,7 @@ do_name(dbref player, const char *name, char *newname) password++; } } - if (strcasecmp(newname, Name(thing)) - && !ok_player_name(newname, thing)) { - /* strcasecmp allows changing foo to Foo, etc. */ + if (!ok_player_name(newname, player, thing)) { notify(player, T("You can't give a player that name.")); return; } @@ -141,7 +139,7 @@ do_name(dbref player, const char *name, char *newname) myenv[i] = NULL; if (IsPlayer(thing)) - delete_player(thing, NULL); + reset_player_list(thing, Name(thing), NULL, newname, NULL); set_name(thing, newname); if(!IsPlayer(thing)) { char lmbuf[1024]; @@ -151,7 +149,7 @@ do_name(dbref player, const char *name, char *newname) set_lmod(thing, lmbuf); } if (IsPlayer(thing)) - add_player(thing, NULL); + add_player(thing); if (!AreQuiet(player, thing)) notify(player, T("Name set.")); diff --git a/src/speech.c b/src/speech.c index 92f49ee..ad3ca0c 100644 --- a/src/speech.c +++ b/src/speech.c @@ -638,6 +638,7 @@ do_page(dbref player, const char *arg1, const char *arg2, dbref cause, int fails_lock; int is_haven; ATTR *a; + char *alias; tp2 = tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string"); if (!tbuf2) @@ -866,8 +867,8 @@ do_page(dbref player, const char *arg1, const char *arg2, dbref cause, } /* Figure out the 'name' of the player */ - if (PAGE_ALIASES && (a = atr_get_noparent(player, "ALIAS"))) - current = tprintf("%s (%s)", Name(player), atr_value(a)); + if (PAGE_ALIASES && (alias = shortalias(player)) && *alias) + current = tprintf("%s (%s)", Name(player), alias); else current = (char *) Name(player); diff --git a/src/utils.c b/src/utils.c index 12efcc7..0304238 100644 --- a/src/utils.c +++ b/src/utils.c @@ -533,6 +533,48 @@ get_random_long(long low, long high) return low + (n % x); } +/** Return an object's alias. We expect a valid object. + * \param it dbref of object. + * \return object's complete alias. + */ +char * +fullalias(dbref it) +{ + static char n[BUFFER_LEN]; /* STATIC */ + ATTR *a = atr_get_noparent(it, "ALIAS"); + + if (!a) + return '\0'; + + strncpy(n, atr_value(a), BUFFER_LEN - 1); + n[BUFFER_LEN - 1] = '\0'; + + return n; +} + +/** Return only the first component of an object's alias. We expect + * a valid object. + * \param it dbref of object. + * \return object's short alias. + */ +char * +shortalias(dbref it) +{ + static char n[BUFFER_LEN]; /* STATIC */ + char *s; + + s = fullalias(it); + if (!(s && *s)) + return '\0'; + + strncpy(n, s, BUFFER_LEN - 1); + n[BUFFER_LEN - 1] = '\0'; + if ((s = strchr(n, ';'))) + *s = '\0'; + + return n; +} + /** Return an object's name, but for exits, return just the first * component. We expect a valid object. * \param it dbref of object. diff --git a/win32/funs.h b/win32/funs.h index 0210388..b90c957 100644 --- a/win32/funs.h +++ b/win32/funs.h @@ -5,6 +5,7 @@ FUNCTION_PROTO(fun_accname); FUNCTION_PROTO(fun_acos); FUNCTION_PROTO(fun_add); FUNCTION_PROTO(fun_after); +FUNCTION_PROTO(fun_alias); FUNCTION_PROTO(fun_align); FUNCTION_PROTO(fun_allof); FUNCTION_PROTO(fun_alphamax); @@ -113,6 +114,7 @@ FUNCTION_PROTO(fun_followers); FUNCTION_PROTO(fun_following); FUNCTION_PROTO(fun_foreach); FUNCTION_PROTO(fun_fraction); +FUNCTION_PROTO(fun_fullalias); FUNCTION_PROTO(fun_fullname); FUNCTION_PROTO(fun_functions); FUNCTION_PROTO(fun_get);