bool ok_player_name(const char *name) { const char *scan; if (!ok_name(name) || strlen(name) > (size_t)PLAYER_NAME_LIMIT) return 0; for (scan = name; *scan; scan++) { if ( tp_spaces_in_playernames ) { if ( !isprint(*scan) || *scan == '"' ) { return 0; } } else { if ( !isprint(*scan) || isspace(*scan) ) /* was isgraph(*scan) */ return 0; } } if (name_is_bad(name)) return 0; /* lookup name to avoid conflicts */ return (lookup_player_noalias(name) == NOTHING); }
/** 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 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, dbref thing) { const char *scan, *good; dbref lookup; if (!ok_name(name, 0) || strlen(name) > (size_t) PLAYER_NAME_LIMIT) return 0; good = (PLAYER_NAME_SPACES || Wizard(player) ? " `$_-.,'" : "`$_-.,'"); /* Make sure that the name contains legal characters only */ for (scan = name; scan && *scan; scan++) { if (isalnum(*scan)) continue; if (!strchr(good, *scan)) return 0; } lookup = lookup_player(name); /* A player may only change to a forbidden name if they're already using that name. */ if (forbidden_name(name)) { if (!((GoodObject(player) && Wizard(player)) || (GoodObject(thing) && lookup == thing))) { return 0; } } return ((lookup == NOTHING) || (lookup == thing)); }
int ok_player_name(const char *name) { const char *scan; if (!ok_name(name) || strlen(name) > PLAYER_NAME_LIMIT) return 0; for (scan = name; *scan; scan++) { if (!(isprint(*scan) && !isspace(*scan)) && *scan != '(' && *scan != ')' && *scan != '\'' && *scan != ',') { /* was isgraph(*scan) */ return 0; } } /* Check the name isn't reserved */ if (*tp_reserved_player_names && equalstr((char*)tp_reserved_player_names, (char*)name)) return 0; /* lookup name to avoid conflicts */ return (lookup_player(name) == NOTHING); }
void prim_name_okp(PRIM_PROTOTYPE) { CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING) abort_interp("Object name string expected."); if (!oper1->data.string) abort_interp("Cannot be an empty string."); result = ok_ascii_other(oper1->data.string->data) && ok_name(oper1->data.string->data); CLEAR(oper1); PushInt(result); }
/* ----> Create an alarm <---- */ dbref create_alarm(CONTEXT) { dbref alarm,owner = (!in_command && (Uid(player) != player)) ? Uid(player):Owner(player); setreturn(ERROR,COMMAND_FAIL); if(Level3(Owner(player))) { if(!Blank(arg1)) { if(strlen(arg1) <= 128) { if(ok_name(arg1)) { if(adjustquota(player,owner,ALARM_QUOTA)) { /* ----> Create and initialise alarm <---- */ alarm = new_object(); db[alarm].destination = NOTHING; db[alarm].location = player; db[alarm].flags = OBJECT; db[alarm].owner = owner; db[alarm].type = TYPE_ALARM; if(!in_command && (Uid(player) == owner) && friendflags_set(owner,player,NOTHING,FRIEND_SHARABLE)) db[alarm].flags |= SHARABLE; ansi_code_filter((char *) arg1,arg1,1); initialise_data(alarm); setfield(alarm,NAME,arg1,1); setfield(alarm,DESC,arg2,0); stats_tcz_update_record(0,0,0,1,0,0,0); PUSH(alarm,db[player].fuses); if(!in_command) output(getdsc(player),player,0,1,0,ANSI_LGREEN"Alarm "ANSI_LWHITE"%s"ANSI_LGREEN" created with ID "ANSI_LYELLOW"#%d"ANSI_LGREEN".",getfield(alarm,NAME),alarm); else writelog(HACK_LOG,1,"HACK","Alarm %s(%d) created within compound command %s(%d) owned by %s(%d).",getname(alarm),alarm,getname(current_command),current_command,getname(Owner(current_command)),Owner(current_command)); setreturn(getnameid(player,alarm,NULL),COMMAND_SUCC); return(alarm); } else warnquota(player,owner,"to build an alarm"); } else output(getdsc(player),player,0,1,0,ANSI_LGREEN"Sorry, an alarm can't have that name."); } else output(getdsc(player),player,0,1,0,ANSI_LGREEN"Sorry, the maximum length of an alarm's name is 128 characters."); } else output(getdsc(player),player,0,1,0,ANSI_LGREEN"Please specify a name for the new alarm."); } else output(getdsc(player),player,0,1,0,ANSI_LGREEN"Sorry, only Wizards/Druids and above can create an alarm."); return(NOTHING); }
/** Clone an object. * \verbatim * This is the top-level function for @clone, which creates a duplicate * of a (non-player) object. * \endverbatim * \param player the enactor. * \param name the name of the object to clone. * \param newname the name to give the duplicate. * \param preserve if 1, preserve ownership and privileges on duplicate. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of the duplicate, or NOTHING. */ dbref do_clone(dbref player, char *name, char *newname, int preserve, char *newdbref) { dbref clone, thing; char dbnum[BUFFER_LEN]; thing = noisy_match_result(player, name, NOTYPE, MAT_EVERYTHING); if ((thing == NOTHING)) return NOTHING; if (newname && *newname && !ok_name(newname, IsExit(thing))) { notify(player, T("That is not a reasonable name.")); return NOTHING; } if (!controls(player, thing) || IsPlayer(thing) || (IsRoom(thing) && !command_check_byname(player, "@dig")) || (IsExit(thing) && !command_check_byname(player, "@open")) || (IsThing(thing) && !command_check_byname(player, "@create"))) { notify(player, T("Permission denied.")); return NOTHING; } /* don't allow cloning of destructed things */ if (IsGarbage(thing)) { notify(player, T("There's nothing left of it to clone!")); return NOTHING; } if (preserve && !Wizard(player)) { notify(player, T("You cannot @CLONE/PRESERVE. Use normal @CLONE instead.")); return NOTHING; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } /* make sure owner can afford it */ switch (Typeof(thing)) { case TYPE_THING: if (can_pay_fees(player, Pennies(thing))) { clone = clone_object(player, thing, newname, preserve); notify_format(player, T("Cloned: Object %s."), unparse_dbref(clone)); if (IsRoom(player)) moveto(clone, player, player, "cloned"); else moveto(clone, Location(player), player, "cloned"); current_state.things++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_ROOM: if (can_pay_fees(player, ROOM_COST)) { clone = clone_object(player, thing, newname, preserve); Exits(clone) = NOTHING; notify_format(player, T("Cloned: Room #%d."), clone); current_state.rooms++; local_data_clone(clone, thing); real_did_it(player, clone, NULL, NULL, NULL, NULL, "ACLONE", NOTHING, global_eval_context.wenv, 0); return clone; } return NOTHING; break; case TYPE_EXIT: /* For exits, we don't want people to be able to link it to a location they can't with @open. So, all this stuff. */ switch (Location(thing)) { case NOTHING: strcpy(dbnum, "#-1"); break; case HOME: strcpy(dbnum, "home"); break; case AMBIGUOUS: strcpy(dbnum, "variable"); break; default: strcpy(dbnum, unparse_dbref(Location(thing))); } if (newname && *newname) clone = do_real_open(player, newname, dbnum, NOTHING); else clone = do_real_open(player, Name(thing), dbnum, NOTHING); if (!GoodObject(clone)) { return NOTHING; } else { atr_cpy(clone, thing); clone_locks(player, thing, clone); Zone(clone) = Zone(thing); Parent(clone) = Parent(thing); Flags(clone) = clone_flag_bitmask("FLAG", Flags(thing)); if (!preserve) { clear_flag_internal(clone, "WIZARD"); clear_flag_internal(clone, "ROYALTY"); Warnings(clone) = 0; /* zap warnings */ Powers(clone) = new_flag_bitmask("POWER"); /* zap powers */ } else { Warnings(clone) = Warnings(thing); Powers(clone) = clone_flag_bitmask("POWER", Powers(thing)); } if (Wizard(clone) || Royalty(clone) || Warnings(clone) || !null_flagmask("POWER", Powers(clone))) notify(player, T ("Warning: @CLONE/PRESERVE on an object with WIZ, ROY, @powers, or @warnings.")); notify_format(player, T("Cloned: Exit #%d."), clone); local_data_clone(clone, thing); return clone; } } return NOTHING; }
/** Create a thing. * \verbatim * This is the top-level function for @create. * \endverbatim * \param player the enactor. * \param name name of thing to create. * \param cost pennies spent in creation. * \paran newdbref the (unparsed) dbref to give the object, or NULL to use the next free * \return dbref of new thing, or NOTHING. */ dbref do_create(dbref player, char *name, int cost, char *newdbref) { dbref loc; dbref thing; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; if (*name == '\0') { notify(player, T("Create what?")); return NOTHING; } else if (!ok_name(name, 0)) { notify(player, T("That's a silly name for a thing!")); return NOTHING; } else if (cost < OBJECT_COST) { cost = OBJECT_COST; } if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } if (can_pay_fees(player, cost)) { /* create the object */ thing = new_object(); /* initialize everything */ set_name(thing, name); if (!IsExit(player)) /* Exits shouldn't have contents! */ Location(thing) = player; else Location(thing) = Source(player); Owner(thing) = Owner(player); Zone(thing) = Zone(player); s_Pennies(thing, cost); Type(thing) = TYPE_THING; Flags(thing) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.thing_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", thing, flagname, 0); } } /* home is here (if we can link to it) or player's home */ if ((loc = Location(player)) != NOTHING && (controls(player, loc) || Abode(loc))) { Home(thing) = loc; /* home */ } else { Home(thing) = Home(player); /* home */ } /* link it in */ if (!IsExit(player)) PUSH(thing, Contents(player)); else PUSH(thing, Contents(Source(player))); /* and we're done */ notify_format(player, T("Created: Object %s."), unparse_dbref(thing)); current_state.things++; local_data_create(thing); queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(thing)); return thing; } return NOTHING; }
/** Create a room. * \verbatim * This is the top-level interface for @dig. * \endverbatim * \param player the enactor. * \param name the name of the room to create. * \param argv array of additional arguments to command * (exit forward,exit back,newdbref) * \param tport if 1, teleport the player to the new room. * \return dbref of new room, or NOTHING. */ dbref do_dig(dbref player, const char *name, char **argv, int tport) { dbref room; char *flaglist, *flagname; char flagbuff[BUFFER_LEN]; char *newdbref = NULL; if (argv[3] && *argv[3]) { newdbref = argv[3]; } /* we don't need to know player's location! hooray! */ if (*name == '\0') { notify(player, T("Dig what?")); } else if (!ok_name(name, 0)) { notify(player, T("That's a silly name for a room!")); } else if (can_pay_fees(player, ROOM_COST)) { if (!make_first_free_wrapper(player, newdbref)) { return NOTHING; } room = new_object(); /* Initialize everything */ set_name(room, name); Owner(room) = Owner(player); Zone(room) = Zone(player); Type(room) = TYPE_ROOM; Flags(room) = new_flag_bitmask("FLAG"); strcpy(flagbuff, options.room_flags); flaglist = trim_space_sep(flagbuff, ' '); if (*flaglist != '\0') { while (flaglist) { flagname = split_token(&flaglist, ' '); twiddle_flag_internal("FLAG", room, flagname, 0); } } notify_format(player, T("%s created with room number %d."), name, room); if (argv[1] && *argv[1]) { char nbuff[MAX_COMMAND_LEN]; sprintf(nbuff, "#%d", room); do_real_open(player, argv[1], nbuff, NOTHING); } if (argv[2] && *argv[2]) { do_real_open(player, argv[2], "here", room); } current_state.rooms++; local_data_create(room); if (tport) { /* We need to use the full command, because we need NO_TEL * and Z_TEL checking */ char roomstr[MAX_COMMAND_LEN]; sprintf(roomstr, "#%d", room); do_teleport(player, "me", roomstr, 0, 0); /* if flag, move the player */ } queue_event(player, "OBJECT`CREATE", "%s", unparse_objid(room)); return room; } return NOTHING; }
/** Rename something. * \verbatim * This implements @name. * \endverbatim * \param player the enactor. * \param name current name of object to rename. * \param newname_ new name for object. */ void do_name(dbref player, const char *name, char *newname_) { dbref thing; char oldname[BUFFER_LEN]; char *newname = NULL; char *alias = NULL; PE_REGS *pe_regs; if ((thing = match_controlled(player, name)) == NOTHING) return; /* check for bad name */ if ((*newname_ == '\0') || strchr(newname_, '[')) { notify(player, T("Give it what new name?")); return; } switch (Typeof(thing)) { case TYPE_PLAYER: switch (ok_object_name (newname_, player, thing, TYPE_PLAYER, &newname, &alias)) { case OPAE_INVALID: case OPAE_NULL: notify(player, T("You can't give a player that name or alias.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; case OPAE_TOOMANY: notify(player, T("Too many aliases.")); mush_free(newname, "name.newname"); return; case OPAE_SUCCESS: break; } break; case TYPE_EXIT: if (ok_object_name(newname_, player, thing, TYPE_EXIT, &newname, &alias) != OPAE_SUCCESS) { notify(player, T("That is not a reasonable name.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; } break; case TYPE_THING: case TYPE_ROOM: if (!ok_name(newname_, 0)) { notify(player, T("That is not a reasonable name.")); return; } newname = mush_strdup(trim_space_sep(newname_, ' '), "name.newname"); break; default: /* Should never occur */ notify(player, T("I don't see that here.")); return; } /* Actually change it */ mush_strncpy(oldname, Name(thing), BUFFER_LEN); if (IsPlayer(thing)) { do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s", Name(thing), thing, newname); if (Suspect(thing) && strcmp(Name(thing), newname) != 0) flag_broadcast("WIZARD", 0, T("Broadcast: Suspect %s changed name to %s."), Name(thing), newname); reset_player_list(thing, Name(thing), NULL, newname, NULL); } set_name(thing, newname); if (alias) { if (*alias == ALIAS_DELIMITER) { do_set_atr(thing, "ALIAS", NULL, player, 0); } else { /* New alias to set */ do_set_atr(thing, "ALIAS", alias, player, 0); } mush_free(alias, "name.newname"); } queue_event(player, "OBJECT`RENAME", "%s,%s,%s", unparse_objid(thing), newname, oldname); if (!AreQuiet(player, thing)) notify(player, T("Name set.")); pe_regs = pe_regs_create(PE_REGS_ARG, "do_name"); pe_regs_setenv_nocopy(pe_regs, 0, oldname); pe_regs_setenv_nocopy(pe_regs, 1, newname); real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING, pe_regs, NA_INTER_PRESENCE, AN_SYS); pe_regs_free(pe_regs); mush_free(newname, "name.newname"); }
/** Is name a valid new name for thing, when set by player? * \verbatim * Parses names and aliases for players/exits, validating each. If everything is valid, * the new name and alias are set into newname and newalias, with memory malloc'd as necessary. * For things/rooms, no parsing is done, and ok_name is called on the entire string to validate. * For players and exits, if name takes the format <name>; then newname is set to <name> and * newalias to ";", to signify that the existing alias should be cleared. If name contains a name and * valid aliases, newname and newalias are set accordingly. * \endverbatim * \param name the new name to set * \param player the player setting the name, for permission checks * \param thing object getting the name, or NOTHING for new objects * \param type type of object getting the name (necessary for new exits) * \param newname pointer to place the new name, once validated * \param newalias pointer to place the alias in, if any * \retval OPAE_SUCCESS name and any given aliases are valid * \retval OPAE_INVALID invalid name or aliases * \retval OPAE_TOOMANY too many aliases for player */ enum opa_error ok_object_name(char *name, dbref player, dbref thing, int type, char **newname, char **newalias) { char *bon, *eon; char nbuff[BUFFER_LEN], abuff[BUFFER_LEN]; char *ap = abuff; int aliases = 0; int empty = 0; strncpy(nbuff, name, BUFFER_LEN - 1); nbuff[BUFFER_LEN - 1] = '\0'; memset(abuff, 0, BUFFER_LEN); /* First, check for a quoted player name */ if (type == TYPE_PLAYER && *name == '"') { /* Quoted player name, no aliases allowed */ bon = nbuff; bon++; eon = bon; while (*eon && *eon != '"') eon++; if (*eon) *eon = '\0'; if (!ok_player_name(bon, player, thing)) return OPAE_INVALID; *newname = mush_strdup(bon, "name.newname"); return OPAE_SUCCESS; } if (type & (TYPE_THING | TYPE_ROOM)) { /* No aliases in the name */ if (!ok_name(nbuff, 0)) return OPAE_INVALID; *newname = mush_strdup(nbuff, "name.newname"); return OPAE_SUCCESS; } /* A player or exit name, with aliases allowed. * Possible things to parse: * <name> - just a new name * <name>; - new name with trailing ; to clear alias * <name>;<alias1>[;<aliasN>] - name with one or more aliases, separated by ; */ /* Validate name first */ bon = nbuff; if ((eon = strchr(bon, ALIAS_DELIMITER))) { *eon++ = '\0'; aliases++; } if (! (type == TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon, 1))) return OPAE_INVALID; *newname = mush_strdup(bon, "name.newname"); if (aliases) { /* We had aliases, so parse them */ while (eon) { if (empty) return OPAE_NULL; /* Null alias only valid as a single, final alias */ bon = eon; if ((eon = strchr(bon, ALIAS_DELIMITER))) { *eon++ = '\0'; } while (*bon && *bon == ' ') bon++; if (!*bon) { empty = 1; /* empty alias, should only happen if we have no proper aliases */ continue; } if (! (type == TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon, 1))) { *newalias = mush_strdup(bon, "name.newname"); /* So we can report the invalid alias */ return OPAE_INVALID; } if (aliases > 1) { safe_chr(ALIAS_DELIMITER, abuff, &ap); } safe_str(bon, abuff, &ap); aliases++; } } *ap = '\0'; if (aliases) { if (!Wizard(player) && type == TYPE_PLAYER && aliases > MAX_ALIASES) return OPAE_TOOMANY; if (*abuff) { /* We have actual aliases */ *newalias = mush_strdup(abuff, "name.newname"); } else { ap = abuff; safe_chr(ALIAS_DELIMITER, abuff, &ap); *ap = '\0'; /* We just want to clear the existing alias */ *newalias = mush_strdup(abuff, "name.newname"); } } return OPAE_SUCCESS; }
/* * do_create * * Use this to create an object. */ void do_create(dbref player, char *name, char *acost) { dbref loc; dbref thing; int cost; static char buf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char *rname, *qname; if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } if (!tp_building || tp_db_readonly) { anotify_nolisten2(player, CFAIL NOBUILD_MESG); return; } strcpy(buf2, acost); for (rname = buf2; (*rname && (*rname != '=')); rname++) ; qname = rname; if (*rname) *(rname++) = '\0'; while ((qname > buf2) && (isspace(*qname))) *(qname--) = '\0'; qname = buf2; for (; *rname && isspace(*rname); rname++) ; cost = atoi(qname); if (*name == '\0') { anotify_nolisten2(player, CINFO "Create what?"); return; } else if (!ok_name(name)) { anotify_nolisten2(player, CINFO "That's a silly name for a thing!"); return; } else if (cost < 0) { anotify_nolisten2(player, CINFO "You can't create an object for less than nothing!"); return; } else if (cost < tp_object_cost) { cost = tp_object_cost; } if (!payfor(player, cost)) { anotify_fmt(player, CFAIL "You don't have enough %s.", tp_pennies); return; } else { /* create the object */ thing = new_object(player); /* initialize everything */ NAME(thing) = alloc_string(name); DBFETCH(thing)->location = player; OWNER(thing) = OWNER(player); DBFETCH(thing)->sp.thing.value = OBJECT_ENDOWMENT(cost); DBFETCH(thing)->exits = NOTHING; FLAGS(thing) = TYPE_THING; /* endow the object */ if (DBFETCH(thing)->sp.thing.value > tp_max_object_endowment) { DBFETCH(thing)->sp.thing.value = tp_max_object_endowment; } if ((loc = DBFETCH(player)->location) != NOTHING && controls(player, loc)) { DBFETCH(thing)->sp.thing.home = loc; /* home */ } else { DBFETCH(thing)->sp.thing.home = player; /* set thing's home to player instead */ } /* link it in */ PUSH(thing, DBFETCH(player)->contents); DBDIRTY(player); /* and we're done */ sprintf(buf, CSUCC "Object %s created.", unparse_object(player, thing)); anotify_nolisten2(player, buf); DBDIRTY(thing); } if (*rname) { PData pdat; sprintf(buf, CINFO "Registered as $%s", rname); anotify_nolisten2(player, buf); sprintf(buf, "_reg/%s", rname); pdat.flags = PROP_REFTYP; pdat.data.ref = thing; set_property(player, buf, &pdat); } }
/* * do_dig * * Use this to create a room. */ void do_dig(int descr, dbref player, const char *name, const char *pname) { char *rname, *qname; dbref newparent; char rbuf[BUFFER_LEN]; char qbuf[BUFFER_LEN]; char buf[BUFFER_LEN]; dbref room; struct match_data md; dbref parent; if (!Builder(player) && !tp_all_can_build_rooms) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } if (!tp_building || tp_db_readonly) { anotify_nolisten2(player, CFAIL NOBUILD_MESG); return; } if (*name == '\0') { anotify_nolisten2(player, CINFO "You need name for the room."); return; } if (!ok_name(name)) { anotify_nolisten2(player, CINFO "That's a silly name for a room!"); return; } if (!payfor(player, tp_room_cost)) { anotify_fmt(player, CFAIL "You don't have enough %s to dig a room.", tp_pennies); return; } room = new_object(player); /* Initialize everything */ newparent = DBFETCH(DBFETCH(player)->location)->location; while ((OkObj(newparent)) && !(FLAGS(newparent) & ABODE) && !(FLAG2(newparent) & F2PARENT)) newparent = DBFETCH(newparent)->location; if (!OkObj(newparent)) { if (OkObj(tp_default_parent)) newparent = tp_default_parent; else newparent = GLOBAL_ENVIRONMENT; } NAME(room) = alloc_string(name); DBFETCH(room)->location = newparent; OWNER(room) = OWNER(player); DBFETCH(room)->exits = NOTHING; DBFETCH(room)->sp.room.dropto = NOTHING; FLAGS(room) = TYPE_ROOM | (FLAGS(player) & JUMP_OK); PUSH(room, DBFETCH(newparent)->contents); DBDIRTY(room); DBDIRTY(newparent); sprintf(buf, CSUCC "Room %s created.", unparse_object(player, room)); anotify_nolisten2(player, buf); strcpy(buf, pname); for (rname = buf; (*rname && (*rname != '=')); rname++) ; qname = rname; if (*rname) *(rname++) = '\0'; while ((qname > buf) && (isspace(*qname))) *(qname--) = '\0'; qname = buf; for (; *rname && isspace(*rname); rname++) ; rname = strcpy(rbuf, rname); qname = strcpy(qbuf, qname); if (*qname) { anotify_nolisten2(player, CNOTE "Trying to set parent..."); init_match(descr, player, qname, TYPE_ROOM, &md); match_absolute(&md); match_registered(&md); match_here(&md); if ((parent = noisy_match_result(&md)) == NOTHING || parent == AMBIGUOUS) { anotify_nolisten2(player, CINFO "Parent set to default."); } else { if ((!can_link_to(player, Typeof(room), parent) && !(FLAG2(parent) & F2PARENT)) || room == parent) { anotify_nolisten2(player, CFAIL "Permission denied. Parent set to default."); } else { moveto(room, parent); sprintf(buf, CSUCC "Parent set to %s.", unparse_object(player, parent)); anotify_nolisten2(player, buf); } } } if (*rname) { PData pdat; sprintf(buf, "_reg/%s", rname); pdat.flags = PROP_REFTYP; pdat.data.ref = room; set_property(player, buf, &pdat); sprintf(buf, CINFO "Room registered as $%s", rname); anotify_nolisten2(player, buf); } }
/* * do_action() * * This routine attaches a new existing action to a source object, * where possible. * The action will not do anything until it is LINKed. * */ void do_action(int descr, dbref player, const char *action_name, const char *source_name) { dbref action, source; static char buf[BUFFER_LEN]; char buf2[BUFFER_LEN]; char *rname, *qname; if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } if (!tp_building || tp_db_readonly) { anotify_nolisten2(player, CFAIL NOBUILD_MESG); return; } strcpy(buf2, source_name); for (rname = buf2; (*rname && (*rname != '=')); rname++) ; qname = rname; if (*rname) *(rname++) = '\0'; while ((qname > buf2) && (isspace(*qname))) *(qname--) = '\0'; qname = buf2; for (; *rname && isspace(*rname); rname++) ; if (!*action_name || !*qname) { anotify_nolisten2(player, CINFO "You must specify an action name and a source object."); return; } else if (!ok_name(action_name)) { anotify_nolisten2(player, CINFO "That's a strange name for an action!"); return; } if (((source = parse_source(descr, player, qname)) == NOTHING)) return; if (!payfor(player, tp_exit_cost)) { anotify_fmt(player, SYSRED "You don't have enough %s to make an action.", tp_pennies); return; } action = new_object(player); NAME(action) = alloc_string(action_name); DBFETCH(action)->location = NOTHING; OWNER(action) = OWNER(player); DBFETCH(action)->sp.exit.ndest = 0; DBFETCH(action)->sp.exit.dest = NULL; FLAGS(action) = TYPE_EXIT; set_source(player, action, source); sprintf(buf, CSUCC "Action %s created and attached to %s.", unparse_object(player, action), NAME(source)); anotify_nolisten2(player, buf); DBDIRTY(action); if (*rname) { PData pdat; sprintf(buf, CINFO "Registered as $%s", rname); anotify_nolisten2(player, buf); sprintf(buf, "_reg/%s", rname); pdat.flags = PROP_REFTYP; pdat.data.ref = action; set_property(player, buf, &pdat); } if (tp_autolinking) { DBFETCH(action)->sp.exit.ndest = 1; DBFETCH(action)->sp.exit.dest = (dbref *) malloc(sizeof(dbref)); (DBFETCH(action)->sp.exit.dest)[0] = NIL; sprintf(buf, CINFO "Linked to NIL."); anotify_nolisten2(player, buf); } }
/* use this to create an exit */ void do_open(int descr, dbref player, const char *direction, const char *linkto) { char *rname, *qname; dbref loc, exit = NOTHING; char buf2[BUFFER_LEN]; if (!Builder(player)) { anotify_nolisten2(player, CFAIL NOBBIT_MESG); return; } if (!tp_building || tp_db_readonly) { anotify_nolisten2(player, CFAIL NOBUILD_MESG); return; } strcpy(buf2, linkto); for (rname = buf2; (*rname && (*rname != '=')); rname++) ; qname = rname; if (*rname) rname++; qname = '\0'; while (((qname--) > buf2) && (isspace(*qname))) *qname = '\0'; qname = buf2; for (; *rname && isspace(*rname); rname++) ; if ((loc = getloc(player)) == NOTHING) return; if (!*direction) { anotify_nolisten2(player, CINFO "You must specify a direction or action name to open."); return; } else if (!ok_name(direction)) { anotify_nolisten2(player, CINFO "That's a strange name for an exit!"); return; } if (!controls(player, loc) && !(POWERS(player) & POW_OPEN_ANYWHERE)) { anotify_fmt(player, CFAIL "%s", tp_noperm_mesg); return; } else if (!payfor(player, tp_exit_cost)) { anotify_fmt(player, CFAIL "You don't have enough %s to open an exit.", tp_pennies); return; } else { char buf[BUFFER_LEN]; /* create the exit */ exit = new_object(player); /* initialize everything */ NAME(exit) = alloc_string(direction); DBFETCH(exit)->location = loc; OWNER(exit) = OWNER(player); FLAGS(exit) = TYPE_EXIT; DBFETCH(exit)->sp.exit.ndest = 0; DBFETCH(exit)->sp.exit.dest = NULL; /* link it in */ PUSH(exit, DBFETCH(loc)->exits); DBDIRTY(loc); /* and we're done */ sprintf(buf, CSUCC "Exit %s created and opened.", unparse_object(player, exit)); anotify_nolisten2(player, buf); /* check second arg to see if we should do a link */ if (*qname != '\0') { anotify_nolisten2(player, CNOTE "Trying to link..."); if (!payfor(player, tp_link_cost)) { anotify_fmt(player, CFAIL "You don't have enough %s to link.", tp_pennies); } else { dbref good_dest[MAX_LINKS]; int i; int ndest = link_exit(descr, player, exit, (char *) qname, good_dest); DBFETCH(exit)->sp.exit.ndest = ndest; DBFETCH(exit)->sp.exit.dest = (dbref *) malloc(sizeof(dbref) * ndest); for (i = 0; i < ndest; i++) { (DBFETCH(exit)->sp.exit.dest)[i] = good_dest[i]; } DBDIRTY(exit); } } } if (*rname && (exit != NOTHING)) { char buf[BUFFER_LEN]; PData pdat; sprintf(buf, CSUCC "Registered as $%s", rname); anotify_nolisten2(player, buf); snprintf(buf, sizeof(buf), "_reg/%s", rname); pdat.flags = PROP_REFTYP; pdat.data.ref = exit; set_property(player, buf, &pdat); } }