#include <kernel/kernel.h> #include <kernel/access.h> #include <kernel/rsrc.h> #include <kernel/user.h> #include <phantasmal/log.h> #include <phantasmal/exit.h> #include <phantasmal/lpc_names.h> #include <type.h> #include <status.h> #include <limits.h> inherit access API_ACCESS; /* prototypes */ static void cmd_list_exit(object user, string cmd, string str); #define SPACE10 " " #define SPACE40 (SPACE10 + SPACE10 + SPACE10 + SPACE10) private object room_dtd; /* DTD for room def'n */ static void upgraded(varargs int clone); private string ralign10(mixed num, int width) { string str; str = SPACE10 + (string) num; return str[strlen(str) - width ..]; } private string ralign40(mixed num, int width) { string str; str = SPACE40 + (string) num; return str[strlen(str) - width ..]; } static string read_entire_file(string file) { string ret; ret = read_file(file); if (ret == nil) { return nil; } if(strlen(ret) > MAX_STRING_SIZE - 3) { error("File '" + file + "' is too large!"); } return ret; } /* * NAME: create() * DESCRIPTION: initialize variables */ static void create(varargs int clone) { if(!find_object(US_MAKE_ROOM)) compile_object(US_MAKE_ROOM); } static void upgraded(varargs int clone) { string dtd_file; /* Set up room DTD */ if(room_dtd) room_dtd->clear(); else room_dtd = ::clone_object(UNQ_DTD); dtd_file = read_entire_file(MAPD_ROOM_DTD); room_dtd->load(dtd_file); } static void destructed(varargs int clone) { if(!clone && room_dtd) { destruct_object(room_dtd); } } /********** Room Functions *****************************************/ /* List MUD rooms */ static void cmd_list_room(object user, string cmd, string str) { int* rooms; int ctr, zone; string tmp; object room, phr; if(str) { str = STRINGD->trim_whitespace(str); str = STRINGD->to_lower(str); } else { str = ""; } if(str == "all" || str == "world" || str == "mud") { user->message("Rooms in MUD (" + ZONED->num_zones() + " zones):\n"); rooms = ({ }); for(zone = 0; zone < ZONED->num_zones(); zone++) { rooms += MAPD->rooms_in_zone(zone); } } else if(str == "" || str == "zone") { user->message("Rooms in zone:\n"); room = user->get_location(); zone = ZONED->get_zone_for_room(room); if(zone == -1) zone = 0; /* Unzoned rooms */ rooms = MAPD->rooms_in_zone(zone); } else { user->message("Usage: " + cmd + "\n" + " " + cmd + " world\n"); return; } tmp = ""; for(ctr = 0; ctr < sizeof(rooms); ctr++) { room = MAPD->get_room_by_num(rooms[ctr]); phr = room->get_brief(); tmp += ralign10("" + rooms[ctr], 6) + " "; if (room->get_mobile()) { tmp += "(body) "; } else if (room->get_detail_of()) { tmp += "(det) "; } else if (room->get_location() && room->get_location()!=MAPD->get_room_by_num(0)) { tmp += "(port) "; } else { tmp += "(room) "; } tmp += phr->to_string(user); tmp += "\n"; } tmp += "-----\n"; user->message_scroll(tmp); } static void cmd_new_room(object user, string cmd, string str) { object room; int roomnum, zonenum; string segown; if(!str || STRINGD->is_whitespace(str)) { roomnum = -1; } else if(sscanf(str, "%*s %*s") == 2 || sscanf(str, "#%d", roomnum) != 1) { user->message("Usage: " + cmd + " [#room num]\n"); return; } if(MAPD->get_room_by_num(roomnum)) { user->message("There is already a room with that number!\n"); return; } segown = OBJNUMD->get_segment_owner(roomnum / 100); if(roomnum >= 0 && segown && segown != MAPD) { user->message("Room number " + roomnum + " is in a segment reserved for non-rooms!\n"); return; } room = clone_object(SIMPLE_ROOM); zonenum = -1; if(roomnum < 0) { zonenum = ZONED->get_zone_for_room(user->get_location()); if(zonenum < 0) { LOGD->write_syslog("Odd, zone is less than 0 when making new room...", LOG_WARN); zonenum = 0; } } MAPD->add_room_to_zone(room, roomnum, zonenum); zonenum = ZONED->get_zone_for_room(room); user->message("Added room #" + room->get_number() + " to zone #" + zonenum + " (" + ZONED->get_name_for_zone(zonenum) + ")" + ".\n"); } static void cmd_delete_room(object user, string cmd, string str) { int roomnum; object room; if(!str || STRINGD->is_whitespace(str) || sscanf(str, "%*s %*s") == 2 || !sscanf(str, "#%d", roomnum)) { user->message("Usage: " + cmd + " #<room num>\n"); return; } room = MAPD->get_room_by_num(roomnum); if(!room) { user->message("No such room as #" + roomnum + ".\n"); return; } EXITD->clear_all_exits(room); if(room->get_detail_of()) { room->get_detail_of()->remove_detail(room); } if(room->get_location()) { room->get_location()->remove_from_container(room); } destruct_object(room); user->message("Room/Portable #" + roomnum + " destroyed.\n"); } static void cmd_save_rooms(object user, string cmd, string str) { string unq_str, argstr; mixed* rooms, *args; object room; int ctr; if(!str || STRINGD->is_whitespace(str)) { user->message("Usage: " + cmd + " <file to write>\n"); user->message(" or " + cmd + " <file to write> #<num> #<num> #<num>...\n"); return; } str = STRINGD->trim_whitespace(str); remove_file(str + ".old"); rename_file(str, str + ".old"); /* Try to remove & rename, just in case */ if(sizeof(get_dir(str)[0])) { user->message("Couldn't make space for file -- can't overwrite!\n"); return; } if(sscanf(str, "%*s %*s") != 2) { rooms = MAPD->rooms_in_zone(0) - ({ 0 }); } else { int roomnum; rooms = ({ }); sscanf(str, "%s %s", str, argstr); args = explode(argstr, " "); for(ctr = 0; ctr < sizeof(args); ctr++) { if(sscanf(args[ctr], "#%d", roomnum)) { rooms += ({ roomnum }); } else { user->message("'" + args[ctr] + "' is not a valid room number.\n"); return; } } } if(!rooms || !sizeof(rooms)) { user->message("No rooms to save!\n"); return; } user->message("Saving rooms: "); for(ctr = 0; ctr < sizeof(rooms); ctr++) { room = MAPD->get_room_by_num(rooms[ctr]); unq_str = room->to_unq_text(); if(!write_file(str, unq_str)) error("Couldn't write rooms to file " + str + "!"); user->message("."); } user->message("\nDone!\n"); } mixed* parse_to_room(string room_file) { if(!SYSTEM()) return nil; return UNQ_PARSER->unq_parse_with_dtd(room_file, room_dtd); } static void cmd_load_rooms(object user, string cmd, string str) { string room_file, argstr; mixed* unq_data, *tmp, *args, *rooms; int iter, roomnum; if(!access(user->query_name(), "/", FULL_ACCESS)) { user->message("Currently only those with full administrative access " + "may load rooms.\n"); return; } if(!str || STRINGD->is_whitespace(str)) { user->message("Usage: " + cmd + " <file to load>\n"); return; } /* If it looks like the admin specified rooms, parse them */ if(sscanf(str, "%s %s", str, argstr) == 2) { rooms = ({ }); args = explode(argstr, " "); for(iter = 0; iter < sizeof(args); iter++) { if(sscanf(args[iter], "#%d", roomnum)) { rooms += ({ roomnum }); } else { user->message("'" + args[iter] + "' doesn't look like a room number!\n"); return; } } } /* Check validity of file */ str = STRINGD->trim_whitespace(str); if(!sizeof(get_dir(str)[0])) { user->message("Can't find file: " + str + "\n"); return; } room_file = read_file(str); if(!room_file || !strlen(room_file)) { user->message("Error reading room file, or file is empty.\n"); return; } if(strlen(room_file) > MAX_STRING_SIZE - 3) { user->message("Room file is too big! " + "See Angelbob to increase current limit."); return; } tmp = UNQ_PARSER->basic_unq_parse(room_file); if(!tmp) { user->message("Cannot parse text as UNQ adding UNQ rooms!\n"); return; } tmp = SYSTEM_WIZTOOL->parse_to_room(room_file); if(!tmp) { user->message("Cannot parse UNQ as rooms adding UNQ rooms!\n"); return; } if(rooms) { unq_data = ({ }); for(iter = 0; iter < sizeof(tmp); iter += 2) { if(tmp[iter + 1][1][0] == "number") { roomnum = tmp[iter + 1][1][1]; if( sizeof(({ roomnum }) & rooms) ) { unq_data += tmp[iter..iter + 1]; rooms -= ({ roomnum }); } } } } else { unq_data = tmp[..]; } if(rooms && sizeof(rooms)) { string tmp; tmp = "No match loading room numbers: "; for(iter = 0; iter < sizeof(rooms); iter++) { tmp += "#" + rooms[iter] + " "; } tmp += "\n"; user->message(tmp); if(sizeof(unq_data)) { user->message("Attempting remaining rooms:\n\n"); } else { user->message("No specified rooms found, ignoring.\n"); return; } } user->message("Registering rooms...\n"); MAPD->add_dtd_unq_rooms(unq_data, str); user->message("Resolving exits...\n"); EXITD->add_deferred_exits(); user->message("Done.\n"); } static void cmd_goto_room(object user, string cmd, string str) { int roomnum; object exit, room, mob; if(str && sscanf(str, "#%d", roomnum)==1) { room = MAPD->get_room_by_num(roomnum); if(!room) { /* Not a room, maybe an exit? */ exit = EXITD->get_exit_by_num(roomnum); room = exit->get_from_location(); } if(!room) { user->message("Can't locate room #" + roomnum + "\n"); return; } } else { user->message("Usage: " + cmd + " #<location num>\n"); return; } /* Do we really want people teleporting into a details? */ if(room->get_detail_of()) { user->message("Can't teleport to a detail.\n"); return; } mob = user->get_body()->get_mobile(); user->message("You teleport to " + room->get_brief()->to_string(user) + ".\n"); mob->teleport(room, 1); user->show_room_to_player(user->get_location()); } /****** Exit Functions ****************************************/ static void cmd_new_exit(object user, string cmd, string str) { int roomnum, dir, retcode; object room; string dirname; string type; if(str) retcode = sscanf(str, "%s #%d %s", dirname, roomnum, type); if (str && retcode == 2) type = "twoway"; if(str && (retcode == 3 || retcode == 2)) { room = MAPD->get_room_by_num(roomnum); if(!room) { user->message("Can't locate room #" + roomnum + "\n"); return; } dir = EXITD->direction_by_string(dirname); if(dir == -1) { user->message("Don't recognize " + dirname + " as direction.\n"); return; } } else { user->message("Usage: " + cmd + " <direction> #<room number> <type>\n"); return; } if(!user->get_location()) { user->message("You aren't standing anywhere so you can't make" + " an exit!\n"); return; } if(user->get_location()->get_exit(dir)) { user->message("There already appears to be an exit in that" + " direction.\n"); return; } if (roomnum == 0) { user->message("Cannot link to void.\n"); return; } if (type=="oneway" || type=="one-way" || type=="1") { user->message("You begin creating a one-way exit to '" + room->get_brief()->to_string(user) + "'.\n"); EXITD->add_oneway_exit_between(user->get_location(), room, dir, -1); } else if (type=="twoway" || type=="two-way" || type=="2") { if (room->get_exit(EXITD->opposite_direction(dir))) { user->message("There appears to be an exit in the other room.\n"); return; } user->message("You begin creating a two-way exit to '" + room->get_brief()->to_string(user) + "'.\n"); EXITD->add_twoway_exit_between(user->get_location(), room, dir, -1, -1); } user->message("You create the exit successfully.\n"); } static void cmd_clear_exits(object user, string cmd, string str) { if(str && !STRINGD->is_whitespace(str)) { user->message("Usage: " + cmd + "\n"); return; } if(!user->get_location()) { user->message("You aren't anywhere, so you can't " + cmd + "!\n"); return; } EXITD->clear_all_exits(user->get_location()); } static void cmd_remove_exit(object user, string cmd, string str) { int dir; object exit, exit2; if(!str || STRINGD->is_whitespace(str) || sscanf(str, "%*s %*s") == 2) { user->message("Usage: " + cmd + " <direction>\n"); return; } str = STRINGD->trim_whitespace(str); dir = EXITD->direction_by_string(str); if(dir == -1) { user->message("'" + str + "' is not a direction.\n"); return; } if(!user->get_location()) { user->message("You aren't anywhere, so you can't " + cmd + "!\n"); return; } exit = user->get_location()->get_exit(dir); if(!exit) { user->message("No exit found going " + str + ".\n"); return; } EXITD->clear_exit(exit); user->message("Exit " + str + " destroyed.\n"); } static void cmd_list_exits(object user, string cmd, string str) { int *tmp, *segs, *exits; int ctr; string tmpstr; if(str && !STRINGD->is_whitespace(str)) { user->message("Usage: " + cmd + "\n"); return; } /* Ignore cmd, str for the moment */ segs = EXITD->get_exit_segments(); if(!segs) { user->message("Can't get segments for exits!\n"); return; } tmp = ({ }); exits = ({ }); for(ctr = 0; ctr < sizeof(segs); ctr++) { tmp = EXITD->exits_in_segment(segs[ctr]); if(tmp && sizeof(tmp)) exits += tmp; } user->message("Exits:\n"); tmpstr = ""; for(ctr = 0; ctr < sizeof(exits); ctr++) { object exit; exit = EXITD->get_exit_by_num(exits[ctr]); tmpstr = "#"; tmpstr += exit->get_number(); cmd_list_exit(user, "cmd_list_exit", tmpstr); } ctr = EXITD->num_deferred_exits(); if(ctr) user->message(ctr + " deferred exits pending.\n"); } static void cmd_list_exit(object user, string cmd, string str) { int objnum, dir, type; string tmpstr; object exit, dest, phr, from; if(!str || sscanf(str, "#%d", objnum) != 1) { user->message("Usage: " + cmd + " #<exit num>\n"); return; } /* Ignore cmd, str for the moment */ tmpstr = ""; exit = EXITD->get_exit_by_num(objnum); if(!exit) { user->message("Can't find exit #" + objnum + " \n"); return; } dest = exit->get_destination(); from = exit->get_from_location(); tmpstr += "Exit #" + exit->get_number(); if(exit->get_brief()) tmpstr += " (" + exit->get_brief()->to_string(user) + ") "; else tmpstr += " (no desc) "; dir = exit->get_direction(); if(dir != -1) { phr = EXITD->get_name_for_dir(dir); if(!phr) tmpstr += "undef direction " + dir; else tmpstr += phr->to_string(user); } else tmpstr += "no direction"; /* Show "from" location as number or commentary */ tmpstr += " from #"; if (!from) tmpstr += "<none>"; else if (from->get_number() == -1) tmpstr += "<unregistered room>"; else tmpstr += from->get_number(); /* Show "to" location as number or commentary */ tmpstr += " to #"; if(!dest) tmpstr += "<none>"; else if (dest->get_number() == -1) tmpstr += "<unregistered room>"; else tmpstr += dest->get_number(); /* Show type: one-way, two-way, other */ tmpstr += " type: "; type = exit->get_exit_type(); switch (type) { case 1: /* one-way */ tmpstr += "one-way"; break; case 2: /* two-way */ tmpstr += "two-way"; break; default: /* unknown */ tmpstr += type; break; } /* Show "link" location as number or commentary */ tmpstr += " link #"; tmpstr += exit->get_link(); if (exit->is_open()) tmpstr += " Open"; else tmpstr += " Closed"; if (exit->is_openable()) tmpstr += " Openable"; if (exit->is_container()) tmpstr += " Container"; if (exit->is_locked()) tmpstr += " Locked"; if (exit->is_lockable()) tmpstr += " Lockable"; tmpstr += "\n"; user->message(tmpstr); } static void cmd_add_deferred_exits(object user, string cmd, string str) { int num; num = EXITD->num_deferred_exits(); user->message("Deferred exits: " + num + ".\n"); if(!access(user->query_name(), "/", FULL_ACCESS)) { user->message("Currently only those with full administrative access " + "may resolve deferred exits and rooms.\n"); return; } EXITD->add_deferred_exits(); MAPD->do_room_resolution(0); /* Don't fully resolve, so no errors */ num = EXITD->num_deferred_exits(); user->message(num + " deferred exits still pending.\n"); user->message(sizeof(MAPD->get_deferred_rooms()) + " deferred rooms still pending.\n"); } static void cmd_check_deferred_exits(object user, string cmd, string str) { int num; if(str) str = STRINGD->trim_whitespace(str); if(str && str != "") { user->message("Usage: " + cmd + "\n"); return; } num = EXITD->num_deferred_exits(); user->message(num + " deferred exits still pending.\n"); user->message(sizeof(MAPD->get_deferred_rooms()) + " deferred rooms still pending.\n"); }