#include #include "db.h" #include "defs.h" #include "prims.h" #include "money.h" #include "property.h" PRIM(copyobj) { struct inst *v; dbref old; dbref new; struct object *o; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(1); v = TOS(0); if (! valid_object(v)) ABORT_INTERP("Invalid object."); old = v->data.objref; if (Typeof(old) != TYPE_THING) ABORT_INTERP("Invalid object type."); if (! PWIZARD) { if (! quota_room(DBFETCH(old)->owner,1,1)) { ABORT_INTERP("Would-be owner has insufficient building quota."); } if (! payfor(UID,OBJECT_DEPOSIT(DBFETCH(old)->sp.thing.value),"copyobj #%d",(int)program)) { ABORT_INTERP(OUT_ERR); /* defined in money.h */ } } new = new_object(Typeof(old)); o = DBFETCH(new); o->name = dup_string(NAME(old)); o->description = copy_str(DBFETCH(old)->description); o->fail_message = copy_str(DBFETCH(old)->fail_message); o->succ_message = copy_str(DBFETCH(old)->succ_message); o->drop_message = copy_str(DBFETCH(old)->drop_message); o->ofail = copy_str(DBFETCH(old)->ofail); o->osuccess = copy_str(DBFETCH(old)->osuccess); o->odrop = copy_str(DBFETCH(old)->odrop); o->location = NOTHING; o->owner = DBFETCH(old)->owner; o->contents = NOTHING; o->next = NOTHING; o->nextowned = NOTHING; o->backlinks = 0; o->backlocks = 0; o->sleepers = 0; o->key = copy_bool(DBFETCH(old)->key); copy_plist_to(DBFETCH(old)->properties,new); o->flags = DBFETCH(old)->flags; #ifdef TIMESTAMPS o->time_created = curtm(); o->time_modified = o->time_created; o->time_used = o->time_created; #endif o->sp.thing.home = DBFETCH(old)->sp.thing.home; o->sp.thing.actions = NOTHING; o->sp.thing.value = DBFETCH(old)->sp.thing.value; add_ownerlist(new); add_backlink(new,DBFETCH(new)->sp.thing.home); moveto(new,UID); DBDIRTY(new); POP(1); MPUSH(PROG_OBJECT,new); } static int prims_recycle_checkcallers(struct dbref_list *drl, dbref object) { for (;drl;drl=drl->next) { if (drl->object == object) return(1); } return(0); } PRIM(recycle) { struct inst *v; dbref obj; NARGS(1); v = TOS(0); if (! valid_object(v)) ABORT_INTERP("Invalid argument."); obj = v->data.objref; if (OWNER(obj) != UID) ABORT_INTERP("Permission denied."); if (obj == program) ABORT_INTERP("Can't recycle this program."); switch (Typeof(obj)) { case TYPE_EXIT: case TYPE_ROOM: case TYPE_THING: case TYPE_PROGRAM: if (FLAGS(obj) & KEEP) ABORT_INTERP("Can't recycle this dbref."); break; } if (prims_recycle_checkcallers(fr->caller,obj)) ABORT_INTERP("Can't recycle a caller."); switch (Typeof(obj)) { case TYPE_ROOM: if ((obj == PLAYER_START) || (obj == GLOBAL_ENVIRONMENT)) ABORT_INTERP("Can't recycle that room."); break; case TYPE_EXIT: if (!unset_source(player,DBFETCH(player)->location,obj)) ABORT_INTERP("GAK! FATAL ERROR!"); break; case TYPE_THING: case TYPE_PROGRAM: break; default: fprintf(stderr,"MUF recycle: bad object type %d in #%d: %.*s%s(#%d%s %s)", Typeof(obj),(int)program, 200,NAME(obj),(strlen(NAME(obj))>200)?"...":"", (int)obj,unparse_flags(obj),unparse_owner(obj) ); ABORT_INTERP("Can't recycle that kind of object."); break; } muf_recycle(player,obj); POP(1); } PRIM(create) { struct inst *vname; struct inst *vcost; char *name; int value; dbref obj; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(2); vcost = TOS(0); vname = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument. (1)"); if (vcost->type != PROG_INTEGER) ABORT_INTERP("Non-integer argument. (2)"); name = vname->data.string; if (! ok_name(name)) ABORT_INTERP("Invalid object name."); value = vcost->data.number; if (value < OBJECT_COST) value = OBJECT_COST; if (! PWIZARD) { if (! quota_room(UID,1,1)) ABORT_INTERP("Insufficient building quota."); if (! payfor(UID,value,"create #%d",(int)program)) ABORT_INTERP(NOT_ERR); } value = OBJECT_ENDOWMENT(value); #if MAX_OBJECT_ENDOWMENT > 0 if (value > MAX_OBJECT_ENDOWMENT) value = MAX_OBJECT_ENDOWMENT; #endif obj = new_object(TYPE_THING); DBSTORE(obj,name,dup_string(name)); DBSTORE(obj,location,UID); DBSTORE(obj,owner,UID); DBSTORE(obj,sp.thing.home,UID); DBSTORE(obj,sp.thing.value,value); DBSTORE(obj,sp.thing.actions,NOTHING); FLAGS(obj) = TYPE_THING; add_ownerlist(obj); PUSH(obj,DBFETCH(UID)->contents); add_backlink(obj,UID); DBDIRTY(obj); DBDIRTY(UID); POP(2); MPUSH(PROG_OBJECT,obj); } PRIM(dig) { struct inst *vname; struct inst *vparent; dbref parent; dbref room; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(2); vparent = TOS(0); vname = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument. (1)"); if (vparent->type != PROG_OBJECT) ABORT_INTERP("Non-object argument. (2)"); parent = vparent->data.objref; if (parent == NOTHING) parent = DBFETCH(DBFETCH(UID)->location)->location; if (parent == NOTHING) parent = DBFETCH(UID)->location; if ((parent < 0) || (parent >= db_top)) ABORT_INTERP("Invalid object. (2)"); if (Typeof(parent) != TYPE_ROOM) ABORT_INTERP("Parent not a room."); if (! can_link_to(UID,TYPE_ROOM,parent)) parent = GLOBAL_ENVIRONMENT; if (! ok_name(vname->data.string)) ABORT_INTERP("Invalid room name."); if (! PWIZARD) { if (! quota_room(UID,1,1)) ABORT_INTERP("Insufficient building quota."); if (! payfor(UID,ROOM_COST,"dig #%d",(int)program)) ABORT_INTERP(NOT_ERR); } room = new_object(TYPE_ROOM); FLAGS(room) = TYPE_ROOM | (FLAGS(UID) & JUMP_OK); DBSTORE(room,name,dup_string(vname->data.string)); DBSTORE(room,location,parent); DBSTORE(room,owner,UID); DBSTORE(room,sp.room.exits,NOTHING); DBSTORE(room,sp.room.dropto,NOTHING); DBSTORE(room,sp.room.useval,0); DBSTORE(room,sp.room.stamp,curtm()); add_ownerlist(room); PUSH(room,DBFETCH(parent)->contents); DBDIRTY(room); DBDIRTY(parent); POP(2); MPUSH(PROG_OBJECT,room); MPUSH(PROG_OBJECT,parent); } PRIM(open) { struct inst *vname; struct inst *vattach; dbref x; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(2); vattach = TOS(0); vname = TOS(1); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument. (1)"); if (! valid_object(vattach)) ABORT_INTERP("Invalid object. (2)"); if (! ok_name(vname->data.string)) ABORT_INTERP("Invalid exit name."); if (!PWIZARD) { if (UID != OWNER(vattach->data.objref)) ABORT_INTERP("Permission denied."); } switch (Typeof(vattach->data.objref)) { case TYPE_ROOM: case TYPE_THING: case TYPE_PLAYER: break; default: ABORT_INTERP("Invalid attach-to object type."); break; } if (! PWIZARD) { if (! quota_room(UID,1,1)) ABORT_INTERP("Insufficient building quota."); if (! payfor(UID,EXIT_COST,"open #%d",(int)program)) ABORT_INTERP(NOT_ERR); } x = new_object(TYPE_EXIT); DBSTORE(x,name,dup_string(vname->data.string)); DBSTORE(x,location,vattach->data.objref); DBSTORE(x,sp.exit.ndest,0); DBSTORE(x,sp.exit.dest,0); DBSTORE(x,owner,UID); FLAGS(x) = TYPE_EXIT; set_source(UID,x,vattach->data.objref); add_ownerlist(x); DBDIRTY(x); POP(2); MPUSH(PROG_OBJECT,x); } PRIM(program) { struct inst *vname; dbref prog; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(1); vname = TOS(0); if (vname->type != PROG_STRING) ABORT_INTERP("Non-string argument. (1)"); if (! PWIZARD) ABORT_INTERP("Permission denied."); if (! ok_name(vname->data.string)) ABORT_INTERP("Invalid name."); prog = new_object(TYPE_PROGRAM); FLAGS(prog) = TYPE_PROGRAM; DBSTORE(prog,name,dup_string(vname->data.string)); DBSTORE(prog,description,store_str(vname->data.string)); DBSTORE(prog,location,UID); DBSTORE(prog,owner,UID); DBSTORE(prog,sp.program.first,0); DBSTORE(prog,sp.program.curr_line,0); DBSTORE(prog,sp.program.codesiz,0); DBSTORE(prog,sp.program.codevec,0); DBSTORE(prog,sp.program.stabsiz,0); DBSTORE(prog,sp.program.start,0); DBSTORE(prog,sp.program.proglocks,0); add_ownerlist(prog); PUSH(prog,DBFETCH(UID)->contents); DBDIRTY(prog); DBDIRTY(UID); POP(1); MPUSH(PROG_OBJECT,prog); } PRIM(unlink) { struct inst *vexit; dbref x; int i; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(1); vexit = TOS(0); if (! valid_object(vexit)) ABORT_INTERP("Invalid object."); x = vexit->data.objref; if (!PWIZARD && (UID != OWNER(x))) ABORT_INTERP("Permission denied."); switch (Typeof(x)) { case TYPE_EXIT: if (DBFETCH(x)->sp.exit.ndest != 0) { for (i=DBFETCH(x)->sp.exit.ndest-1;i>=0;i--) { remove_backlinks(x,DBFETCH(x)->sp.exit.dest[i]); } if (!Wizard(UID)) { add_pennies(OWNER(x),LINK_COST,"MUF unlink"); } } DBSTORE(x,sp.exit.ndest,0); if (DBFETCH(x)->sp.exit.dest) { free(DBFETCH(x)->sp.exit.dest); DBSTORE(x,sp.exit.dest,0); } break; case TYPE_ROOM: remove_backlinks(x,DBFETCH(x)->sp.room.dropto); DBSTORE(x,sp.room.dropto,NOTHING); break; default: ABORT_INTERP("Invalid object type"); break; } POP(1); } /* addlink_check -> checks to make sure there isn't already a link to something other than an exit */ static int prims_addlink_check(dbref xit) { int i; for (i=DBFETCH(xit)->sp.exit.ndest-1;i>=0;i--) { switch (Typeof(DBFETCH(xit)->sp.exit.dest[i])) { case TYPE_PLAYER: case TYPE_ROOM: case TYPE_PROGRAM: case TYPE_DAEMON: return(1); break; } } return(0); } /* addlink_sub -> checks to see if a link is valid, and links it */ static int prims_addlink_sub(dbref player, dbref program, dbref xit, dbref destination, struct frame *fr) { #ifndef TELEPORT_TO_PLAYER if (Typeof(destination) == TYPE_PLAYER) return(0); #endif if (DBFETCH(xit)->sp.exit.ndest == MAX_LINKS) return(0); if (! PWIZARD) { if (!can_link(UID,xit)) return(0); if (!can_link_to(UID,TYPE_EXIT,destination)) return(0); } switch (Typeof(destination)) { case TYPE_PLAYER: case TYPE_ROOM: case TYPE_PROGRAM: case TYPE_DAEMON: if (prims_addlink_check(xit)) return(0); break; case TYPE_EXIT: if (exit_loop_check(xit,destination)) return(0); break; } add_backlink(xit,destination); DBSTORE(xit,sp.exit.ndest,DBFETCH(xit)->sp.exit.ndest+1); DBSTORE(xit,sp.exit.dest, (dbref *)realloc(DBFETCH(xit)->sp.exit.dest,sizeof(dbref)*DBFETCH(xit)->sp.exit.ndest)); DBSTORE(xit,sp.exit.dest[DBFETCH(xit)->sp.exit.ndest-1],destination); return(1); } PRIM(addlink) { struct inst *vthing; struct inst *vlinkto; dbref thing; dbref linkto; if (! PBUILD) ABORT_INTERP("Not able to build."); NARGS(2); vlinkto = TOS(0); vthing = TOS(1); if (! valid_object(vthing)) ABORT_INTERP("Invalid object. (1)"); if (vlinkto->type != PROG_OBJECT) ABORT_INTERP("Invalid object. (2)"); thing = vthing->data.objref; linkto = vlinkto->data.objref; if (!( (linkto == HOME) || ( (linkto >= 0) && (linkto < db_top) && (Typeof(linkto) != TYPE_GARBAGE) ) )) { ABORT_INTERP("Invalid object. (2)"); } switch (Typeof(thing)) { case TYPE_EXIT: if (! PWIZARD) { if (DBFETCH(thing)->sp.exit.ndest) { if (UID != OWNER(thing)) ABORT_INTERP("Permission denied."); } else { if (!payfor(UID,LINK_COST,"link #%d",(int)program)) ABORT_INTERP(NOT_ERR); } } if (!prims_addlink_sub(player,program,thing,linkto,fr)) { ABORT_INTERP("Can't link."); } break; case TYPE_PLAYER: case TYPE_THING: case TYPE_ROOM: if ( (linkto == HOME) || (!PWIZARD && !controls(UID,thing)) || !can_link_to( PWIZARD ? OWNER(linkto) : UID, Typeof(thing), linkto ) ) { ABORT_INTERP("Permission denied."); } switch (Typeof(thing)) { case TYPE_THING: remove_backlinks(thing,DBFETCH(thing)->sp.thing.home); add_backlink(thing,linkto); DBSTORE(thing,sp.thing.home,linkto); break; case TYPE_PLAYER: remove_backlinks(thing,DBFETCH(thing)->sp.player.home); add_backlink(thing,linkto); DBSTORE(thing,sp.player.home,linkto); break; case TYPE_ROOM: if (!PWIZARD && (Typeof(linkto) == TYPE_PROGRAM)) ABORT_INTERP("Permission denied."); remove_backlinks(thing,DBFETCH(thing)->sp.room.dropto); add_backlink(thing,linkto); DBSTORE(thing,sp.room.dropto,linkto); break; } break; default: ABORT_INTERP("Can't link that kind of object."); break; } POP(2); } PRIM(quotap) { struct inst *vplayer; struct inst *vamt; int rv; NARGS(2); vplayer = TOS(1); vamt = TOS(2); if (!valid_object(vplayer) || (Typeof(vplayer->data.objref) != TYPE_PLAYER)) ABORT_INTERP("Not a player."); if (vamt->type != PROG_INTEGER) ABORT_INTERP("Non-integer argument. (2)"); if (vamt->data.number < 0) ABORT_INTERP("Negative argument."); rv = quota_room(vplayer->data.objref,vamt->data.number,1); POP(2); MPUSH(PROG_INTEGER,rv); }