new obj Inserting changelog.cdc... new object $changelog: $file; var $root manager = $changelog; var $root managed = [$changelog]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 906983169; var $dmi_data descriptions = #[]; var $root inited = 1; public method .log() { arg entry; if (!($changelog_group.includes(caller()))) (> .perms(sender()) <); // just silently die if logs/ isn't there catch any { .fopen("logs/changelog", ">>"); .fwrite((("[" + time()) + "] ") + entry); .fclose(); } }; new obj Inserting mail_list_tracebacks.cdc... new object $mail_list_tracebacks: $mail_list; var $root manager = $mail_list_tracebacks; var $root managed = [$mail_list_tracebacks]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904830832; var $dmi_data descriptions = #[]; var $has_name name = ['prop, "tracebacks", "tracebacks"]; var $mail_list mail = []; var $mail_list senders = [$no_one]; var $mail_list readers = 0; var $mail_list notify = []; var $root inited = 1; var $mail_list last_received_on = 0; new obj Inserting character.cdc... new object $character: $thing; var $root manager = $character; var $root managed = [$character]; var $root flags = ['variables, 'methods, 'code, 'core, 'fertile]; var $root created_on = 890933084; var $dmi_data descriptions = #[]; var $has_commands shortcuts = #[]; var $has_commands remote = #[]; var $has_commands local = #[]; var $has_name name = ['prop, "Generic Character", "Generic Character"]; var $described prose = []; var $located location = $lost_and_found; var $located obvious = 1; var $thing gender = $gender_neuter; var $root inited = 1; var $character dead = 0; var $character identity = 0; var $character affiliation = 0; var $character deaths = 0; var $character str = 0; var $character agl = 0; var $character app = 0; var $character itg = 0; var $character int = 0; var $character per = 0; var $character cha = 0; var $character wil = 0; var $character cra = 0; var $character awr = 0; var $character dmg = 0; var $character rea = 0; var $character cmb = 0; var $character npc = 0; var $character lrn = 0; var $character end = 0; var $character lif = 0; var $character hum = 0; var $character kno = 0; var $character src = 0; var $character csrc = 0; public method .fmta() { arg stat; var base, cur; [base, cur] = get_var(stat) || [10, 10]; if (base == cur) return pad(tostr(cur), -2) + " "; return strfmt("%2r/%2l", cur, base) + " "; }; public method .fmts() { arg score; var v; v = get_var(score); switch (score) { case 'hum: if (v > 0) return pad("+" + v, 6); } return pad(tostr(v), 6); }; public method .format_sheet() { var out, line; line = ((" Strength: " + (.fmta('str))) + " Intellect: ") + (.fmta('int)); line += ((" Craft: " + (.fmta('cra))) + " STR DMG: ") + (.fmts('dmg)); out = [line]; line = ((" Agility: " + (.fmta('agl))) + "Perception: ") + (.fmta('per)); line += (("Awareness: " + (.fmta('awr))) + " CMB REA: ") + (.fmts('cmb)); out += [line]; line = (("Appearance: " + (.fmta('app))) + " Charisma: ") + (.fmta('cha)); line += " ------- NPC REA: " + (.fmts('npc)); out += [line]; line = ((" Integrity: " + (.fmta('itg))) + " Willpower: ") + (.fmta('wil)); line += ((" Humanity: " + (.fmta('hum))) + " Learn: ") + (.fmts('lrn)); out += [line, ""]; line = ((((((" Endurance: " + (.fmts('end))) + " Knowledge: ") + (.fmts('kno))) + " Source: ") + (.fmts('src))) + " Cur Src: ") + (.fmts('csrc)); out += [line]; line = (" ** Life: " + (.fmts('lif))) + " DAMAGE: x/x CRITICAL: x/x HEALTH: x/x"; return out + [line]; }; public method .lower_attr() { arg attribute, difference; var new; new = (get_var(attribute)[1]) - difference; set_var(attribute, get_var(attribute).replace(1, new)); }; public method .raise_attr() { arg attribute, difference; var new; new = (get_var(attribute)[1]) + difference; if (new > (get_var(attribute)[2])) new = get_var(attribute)[2]; set_var(attribute, get_var(attribute).replace(1, new)); }; public method .attribute() { arg attribute; if (caller() != definer()) (> .perms(sender(), 'trusts) <); if (!(attribute in (.attributes()))) throw(~invattr, "Invalid Attribute: " + attribute); return get_var(attribute) || [10, 10]; }; public method .dead() { return dead; }; public method .ok_to_raise_initial() { arg attr, amt; var a, tot, phys, ment, meta, list, i, end; phys = .physical_attributes(); ment = .mental_attributes(); meta = .meta_attributes(); for a in ((phys + ment) + meta) { if ((a = get_var(a))) tot += a[1]; else tot += 10; } if (tot > 110) return "No initial points left, try reducing another attribute."; end = ((get_var(attr) || [10])[1]) + amt; if (end > 16) return "Initial Attributes may not be more than 16"; if (attr in phys) { list = phys; i = [56, "Physical"]; } else if (attr in ment) { list = ment; i = [56, "Mental"]; } else if (attr in meta) { list = meta; i = [30, "Meta-Physical"]; } else { throw(~invattr, "Invalid Attribute: " + attr); } tot = 0; for a in (list) { if ((a = get_var(a))) tot += a[1]; else tot += 10; } if ((tot + amt) > (i[1])) return ((("This would go beyond the max (" + (i[1])) + ") for ") + (i[2])) + " Attributes"; return end; }; public method .init_character() { str = (agl = (app = (itg = (int = (per = (cha = (wil = (cra = (awr = [10, 10]))))))))); }; public method .ok_to_lower_initial() { arg attr, amt; var end; end = ((get_var(attr) || [10])[1]) - amt; if (end < 6) return "Initial Attributes may not be less than 6"; return end; }; public method .meta_attributes() { return ['cra, 'awr]; }; public method .physical_attributes() { return ['str, 'agl, 'app, 'itg]; }; public method .mental_attributes() { return ['int, 'per, 'cha, 'wil]; }; public method .attributes() { return ((.physical_attributes()) + (.mental_attributes())) + (.meta_attributes()); }; public method .set_attribute() { arg attribute, base; var cur; (> .perms(caller(), $player) <); if (!(attribute in (.attributes()))) throw(~invattr, "Invalid Attribute: " + attribute); cur = get_var(attribute) || [10, 10]; cur = replace(cur, 1, base); if ((cur[2]) > base) cur = replace(cur, 2, base); set_var(attribute, cur); }; new obj Inserting introtut_path1.cdc... new object $introtut_path1: $path; var $root manager = $introtut_path1; var $path ways = #[[$introtut_moving, $introtut_moving_1], [$introtut_moving_1, $introtut_moving]]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 882834737; var $dmi_data descriptions = #[]; var $has_commands shortcuts = #[]; var $has_commands remote = #[]; var $has_commands local = #[]; var $has_name name = ['prop, "path_140", "path_140"]; var $described prose = []; var $path names = #[[$introtut_moving, ['prop, "east", "", []]], [$introtut_moving_1, ['prop, "west", "", []]]]; var $root inited = 1; var $root managed = [$introtut_path1]; new obj Inserting introtut_path2.cdc... new object $introtut_path2: $path; var $root manager = $introtut_path2; var $path ways = #[[$introtut_moving_1, $introtut_moving_2], [$introtut_moving_2, $introtut_moving_1]]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 882834737; var $dmi_data descriptions = #[]; var $has_commands shortcuts = #[]; var $has_commands remote = #[]; var $has_commands local = #[]; var $has_name name = ['prop, "path_142", "path_142"]; var $described prose = []; var $path names = #[[$introtut_moving_1, ['prop, "stairs", "", ["d?own"]]], [$introtut_moving_2, ['prop, "stairs", "", ["u?p"]]]]; var $root inited = 1; var $root managed = [$introtut_path2]; new obj Inserting help_obj_motd.cdc... new object $help_obj_motd: $help_obj; var $root manager = $help_obj_motd; var $root managed = [$help_obj_motd]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 906679568; var $dmi_data descriptions = #[]; var $has_name name = ['prop, "motd", "motd"]; var $help_node links = #[]; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "$motd is an object which controls the display which users receive upon connecting, as well as the web page which the HTTP server returns. This object allows administrators to easily change and customize this information. This can be done via the following settings:", <$format, ["p", [], [], 'do_p]>, <$format, ["dl", [], [<$format, ["dt", [], ["$motd:login-sequence:"], 'do_dt]>, <$format, ["dd", [], ["Sets the sequence of items to be displayed on the login screen"], 'do_dd]>, <$format, ["dt", [], ["$motd:server-name:"], 'do_dt]>, <$format, ["dd", [], ["Sets the default server name for MOTD displays"], 'do_dd]>, <$format, ["dt", [], ["$motd:server-title:"], 'do_dt]>, <$format, ["dd", [], ["Sets the default server title for MOTD displays"], 'do_dd]>], 'do_dl]>, <$format, ["p", [], [], 'do_p]>, "$motd:login-sequence is a list of items which can be passed to $motd.build() to construct the login display. The list of valid arguments are as follows:", <$format, ["p", [], [], 'do_p]>, <$format, ["dl", [], [<$format, ["dt", [], ["'admins:"], 'do_dt]>, <$format, ["dd", [], ["Displays a list of administrators"], 'do_dd]>, <$format, ["dt", [], ["'connected:"], 'do_dt]>, <$format, ["dd", [], ["Displays the number of currently connected users"], 'do_dd]>, <$format, ["dt", [], ["'core_version:"], 'do_dt]>, <$format, ["dd", [], ["Displays the current core version"], 'do_dd]>, <$format, ["dt", [], ["'default:"], 'do_dt]>, <$format, ["dd", [], ["Constructs a default login display"], 'do_dd]>, <$format, ["dt", [], ["'driver_version:"], 'do_dt]>, <$format, ["dd", [], ["Displays the version of the driver currently in use"], 'do_dd]>, <$format, ["dt", [], ["'help:"], 'do_dt]>, <$format, ["dd", [], ["Displays a help message"], 'do_dd]>, <$format, ["dt", [], ["'long:"], 'do_dt]>, <$format, ["dd", [], ["Displays the server's title, then its name"], 'do_dd]>, <$format, ["dt", [], ["'name:"], 'do_dt]>, <$format, ["dd", [], ["Displays the server name"], 'do_dd]>, <$format, ["dt", [], ["'notes:"], 'do_dt]>, <$format, ["dd", [], ["Displays the contents of the notes variable on $motd"], 'do_dd]>, <$format, ["dt", [], ["'short:"], 'do_dt]>, <$format, ["dd", [], ["Displays only the server's title"], 'do_dd]>, <$format, ["dt", [], ["'title:"], 'do_dt]>, <$format, ["dd", [], ["Displays the server title"], 'do_dd]>, <$format, ["dt", [], ["'quote:"], 'do_dt]>, <$format, ["dd", [], ["Displays a random quote"], 'do_dd]>], 'do_dl]>], #[]]>; var $root inited = 1; var $help_node index = $help_index_objects; new obj Inserting chargen_parser.cdc... new object $chargen_parser: $user_parsers; var $root manager = $chargen_parser; var $user_parsers priority = 700; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 863732681; var $dmi_data descriptions = #[]; var $root inited = 1; var $root managed = [$chargen_parser]; public method .parse() { arg user, str, next_parser, @other_parsers; var m, cmd, args; str = str.trim(); // direct drop-through if (str && ((str[1]) == ">")) return next_parser.parse(user, substr(str, 2), @other_parsers); // shortcut? if ((m = regexp(str, "^(\+|-)([0-9a-z]+) *(.*)$"))) { if ((m[1]) == "-") str = (("lower " + (m[3])) + " ") + (m[2]); else str = (("raise " + (m[3])) + " ") + (m[2]); } cmd = explode(str); if (cmd && ((cmd[1]) in ["help", "lower", "raise", "sheet", "done", "abort"])) { args = sublist(cmd, 2); cmd = lowercase(cmd[1]); return ['command, user, tosym(cmd + "_charcmd")] + args; } return next_parser.parse(user, str, @other_parsers); }; new obj Inserting group.cdc... new object $group: $root; var $root manager = $group; var $root managed = [$group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904653573; var $root inited = 1; var $root defined_settings = #[["group", #[['get, ['get_group]], ['set, ['set_group]], ['parse, ['parse_group]], ['format, ['format_group]]]]]; var $group group = #[]; public method .get_group() { arg @args; return group; }; protected method .set_group() { arg name, definer, value; if (this() == definer()) throw(~invgroup, "You cannot change the base group " + definer()); switch (value[1]) { case 'set: group = value[2]; case 'add: group = dict_add(group, value[2], 1); case 'del: group = dict_del(group, value[2]); default: throw(~type, "Unknown action: " + (value[1])); } }; public method .del_from_group() { arg target; (> .perms(sender()) <); group = dict_del(group, target); }; root method .init_group() { group = #[]; }; public method .includes() { arg target; if (!dict_contains(group, target)) { if (this() == definer()) return 0; // if (this() == definer()) // return $sys.is_system(target); return (parents()[1]).includes(target); } return 1; }; public method .add_to_group() { arg target; (> .perms(sender()) <); group = dict_add(group, target, 1); }; root method .uninit_group() { if (sender() != definer()) clear_var('group); else group = #[]; }; public method .parse_group() { arg value, @args; var action, list, item, out; if (value && ((value[1]) in ["+", "-"])) { if ((value[1]) == "-") action = 'del; else action = 'add; list = [substr(value, 2)]; } else { action = 'set; list = value.explode_english_list(); } out = hash item in (list) to ([(> $object_lib.to_dbref(item) <), 1]); if (action == 'set) return [action, out]; else return [action, dict_keys(out)[1]]; }; public method .format_group() { arg data; return join(dict_keys(data), ", "); }; public method .parse_grouplist() { arg value, method, @args; var action, list, item, out; if (value && ((value[1]) in ["+", "-"])) { if ((value[1]) == "-") action = 'del; else action = 'add; list = [substr(value, 2)]; } else { action = 'set; list = value.explode_english_list(); } out = #[]; for item in (list) { if (method) { catch ~methodnf item = (> sender().(method)(item, action, @args) <); with item = (> .(method)(item, action, @args) <); } out = dict_add(out, item, 1); } if (action == 'set) return [action, out]; else return [action, out[1]]; }; public method .is_group() { return 1; }; new obj Inserting core_group.cdc... new object $core_group: $group; var $root manager = $core_group; var $root managed = [$core_group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904657222; var $root inited = 1; var $group group = #[]; new obj Inserting create_for_others_group.cdc... new object $create_for_others_group: $core_group; var $root manager = $create_for_others_group; var $root managed = [$create_for_others_group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904657034; var $root inited = 1; var $group group = #[]; new obj Inserting create_for_sender_group.cdc... new object $create_for_sender_group: $create_for_others_group; var $root manager = $create_for_sender_group; var $root managed = [$create_for_sender_group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904657041; var $root inited = 1; var $group group = #[]; new obj Inserting syslog_group.cdc... new object $syslog_group: $core_group; var $root manager = $syslog_group; var $root managed = [$syslog_group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904656992; var $root inited = 1; var $group group = #[[$daemon, 1], [$connection, 1], [$dns, 1], [$guest, 1], [$user, 1], [$body, 1], [$sys, 1], [$root, 1], [$login_interface, 1], [$http_interface, 1], [$connection_interface, 1]]; new obj Inserting changelog_group.cdc... new object $changelog_group: $core_group; var $root manager = $changelog_group; var $root managed = [$changelog_group]; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 906983574; var $group group = #[[$root, 1]]; var $root inited = 1; new obj Inserting staff_group.cdc... new object $staff_group: $group; var $root manager = $staff_group; var $root flags = ['variables, 'methods, 'code, 'core]; var $root created_on = 904657230; var $root inited = 1; var $root managed = [$staff_group]; var $group group = #[]; new obj Inserting building_group.cdc... new object $building_group: $staff_group; var $root manager = $building_group; var $root flags = ['variables, 'methods, 'code, 'fertile, 'core]; var $root created_on = 904655977; var $group group = #[]; var $root inited = 1; var $root managed = [$building_group]; new obj Inserting programming_group.cdc... new object $programming_group: $staff_group; var $root manager = $programming_group; var $root managed = [$programming_group]; var $root flags = ['variables, 'methods, 'code, 'fertile, 'core]; var $root created_on = 904657855; var $root inited = 1; var $group group = #[]; new obj Inserting conditional_group.cdc... new object $conditional_group: $group; var $root manager = $conditional_group; var $root flags = ['variables, 'methods, 'code, 'fertile, 'core]; var $root created_on = 904657262; var $root inited = 1; var $root managed = [$conditional_group]; var $group group = #[]; public method .includes() { arg target; if (!((.get_group()).try(target))) { if (this() == definer()) return $sys.is_system(target); return (parents()[1]).includes(target); } return 1; }; protected method .set_group() { arg name, definer, value; var list; // just ignore any itemlist stuff value = value[2]; if ((type(value) != 'frob) || (!(frob_class(value).is($logic_frob)))) throw(~invlogic, "Conditional groups must be set as $logic_frobs"); pass(name, definer, ['set, value]); }; public method .del_from_group() { arg target; // do something, quick... perhaps throw an error throw(~invlogic, "You can only set conditional groups with @set group:group=..."); }; public method .add_to_group() { arg target; // do something, quick... perhaps throw an error throw(~invlogic, "You can only set conditional groups with @set group:group=..."); }; root method .init_conditional_group() { .set_group(0, 0, ['set, $false_lock_frob.new()]); }; public method .parse_group() { arg value, @args; if (value in ["none", "nobody"]) value = "no"; else if (value in ["anybody", "everybody"]) value = "yes"; return ['set, (> $lock_frob.parse(value, user() || this()) <)]; }; root method .format_group() { arg value; var unparse; unparse = value.unparse(); if (unparse == "yes") return "anybody"; else if (unparse == "no") return "nobody"; return unparse; }; maintenance public method $root.__upgrade_handle_var() { arg handle, vref, old, current, new; if (current != old) { // if (handle == 1) { if (type(old) != type(current)) { dblog("ERROR: datatype inconsistency for " + vref + " " + type(old) + " != " + type(current)); } switch (type(current)) { case 'dictionary: return dict_union(new, current); case 'list: return union(new, current); default: return new; } // } } return new; }; new method Replacing public method $root.has_ancestor(): nooverride public method $root.has_ancestor(): nooverride { arg obj; return has_ancestor(obj); }; new method Replacing public method $root.will_spawn(): nooverride public method $root.will_spawn(): nooverride { arg who; if (!(.has_flag('fertile, who))) throw(~perm, (.namef('ref)) + " is not fertile or readable."); // available quota? if (!(who.quota_valid())) throw(~quota, "Sender does not have the available quota"); }; new method Adding public method $root.is_writable_by2(): nooverride public method $root.is_writable_by2(): nooverride { arg obj; var o; for o in (.writers()) { if (o.has_ancestor($group)) { if (o.includes(obj)) return 1; } else if (o == obj) { return 1; } } return $sys.is_system(obj); }; new method Adding public method $root.is_writable_by3(): nooverride public method $root.is_writable_by3(): nooverride { arg obj; var o; for o in (.writers()) { if (o.has_ancestor($group)) { if (o.includes(obj)) return 1; } else if (o == obj) { return 1; } } return $sys.is_system(obj); }; new method Replacing public method $root.writers(): nooverride public method $root.writers(): nooverride { arg @literal; if (literal) return writers || []; if (manager != this()) return [manager, this()] + (writers || []); return [manager] + (writers || []); }; new method Replacing public method $root.set_quota_exempt(): nooverride public method $root.set_quota_exempt(): nooverride { arg bool; (> .perms(sender(), $user, @$sys.system(), $root) <); if (bool) quota_exempt = 1; else (| clear_var('quota_exempt) |); }; new method Replacing public method $root.uninitialize(): nooverride public method $root.uninitialize(): nooverride { arg @destroyed; var a, v, d, definer, method, descendants, str, tb; (> .perms(caller(), $root, $sys) <); destroyed = destroyed ? 1 : 0; descendants = (.descendants()) + [this()]; // call [ancestors...].uninit_ancestor() on the object being destroyed for a in (ancestors()) { method = tosym("uninit_" + (a.objname())); if ((definer = (| find_method(method) |))) { if (definer != a) { // scream madly and run around--everybody should know this str = "UNINIT ERROR: uninit method for " + a; str += (" in wrong place (" + definer) + ")"; (| (definer.manager()).tell(str) |); (| (a.manager()).tell(str) |); (| sender().tell(str) |); continue; } catch any { .(method)(); } with { // try and let somebody know they made a boo-boo somewhere tb = traceback().fmt_tb(); str = ((("UNINIT ERROR " + this()) + "<") + definer) + ">:"; if (definer) { (| (definer.manager()).tell(str) |); (| (definer.manager()).tell(tb) |); } (| sender().tell(str) |); (| sender().tell(tb) |); (| sender().tell("Continuing uninit..") |); (| $sys.log_traceback(tb, "** " + str) |); } } refresh(); } // if we have descendants, clean anything from the object being dested method = tosym("uninit_" + (.objname())); if ((definer = (| find_method(method) |))) { if (definer != this()) { // scream madly and run around--everybody should know this str = "UNINIT ERROR: uninit method for " + a; str += (" in wrong place (" + definer) + ")"; (| (definer.manager()).tell(str) |); (| (.manager()).tell(str) |); (| sender().tell(str) |); } else { for d in (descendants) { catch any { d.(method)(); } with { // try and let somebody know they made a boo-boo somewhere str = ((("UNINIT ERROR " + d) + "<") + this()) + ">:"; tb = traceback().fmt_tb(); (| (.manager()).tell(str) |); (| (.manager()).tell(tb) |); if ((.manager()) != sender()) { (| sender().tell(str) |); (| sender().tell(tb) |); } (| sender().tell("Continuing uninit..") |); (| $sys.log_traceback(tb, "** " + str) |); } refresh(); } } } // clear vars if ((!destroyed) && descendants) $sys.clear_definer_vars(this(), descendants); }; new method Replacing public method $root.credit() public method $root.credit() { var line; if ('core in (flags || [])) { line = "Created "; if ((.created_on()) > 0) line += ($time.format("%d-%h-%Y", .created_on())) + " "; line = [line + "as a part of ColdCore, see: @help Credit"]; } else { line = []; } if (credit) return credit + line; return line; }; new method Replacing public method $root.del_var(): nooverride public method $root.del_var(): nooverride { arg name; var n, obj; (caller() == definer()) || (> .perms(sender()) <); (> $sys.touch() <); // try and clear the variable on all of the descendants, before // deleting the variable... (> .clear_variable(name) <); // now delete the variable (> del_var(name) <); if ('core in (.flags())) $changelog.log((((("DEL-VAR: " + this()) + ",") + name) + " by ") + sender()); }; new method Replacing public method $root.add_method() public method $root.add_method() { arg code, name, @evalonly; var l, m, line, errs; (> .perms(sender()) <); if (evalonly && (caller() in [$root, $sys, $programmer])) (> $sys.touch('lockok) <); else (> $sys.touch() <); // check for a few things only admins can do if (!(sender().is($admin))) { for l in [1 .. listlen(code)] { line = code[l]; if ((m = line.match_regexp("[^a-z0-9_.]anticipate_assignment\("))) { (> sender().tell($code_lib.point_to_line("ERROR: call to anticipate_assignment()", ((m[1])[1]) + 2, ((m[1])[2]) - 2, l, line)) <); throw(~perm, "anticipate_assignment() may only be used by an administrator."); } } } errs = (> add_method(code, name) <); if ('core in (.flags())) $changelog.log((((("ADD-METHOD: " + this()) + ".") + name) + " by ") + sender()); for l in [1 .. listlen(errs)] { line = errs[l]; if (match_regexp(line, "Line [0-9]+: Unknown function length.")) { line = substr(line, 1, strlen(line) - 1); errs = replace(errs, l, line + "(), try listlen(), strlen() or buflen()"); } } return errs; }; new method Replacing public method $root.add_var(): nooverride public method $root.add_var(): nooverride { arg name, @args; var tmp, kid; (> .perms(sender()) <); (> $sys.touch() <); if (!(tostr(name).valid_ident())) throw(~invident, name + " is not a valid ident."); (> add_var(name) <); if ('core in (.flags())) $changelog.log((((("ADD-VAR: " + this()) + ",") + name) + " by ") + sender()); // The following code is a kludge as we can't send a default value // to the primitive. if (args) { tmp = tosym((("__set_" + tostr(name)) + "_") + time()); catch any { add_method([((tostr(name) + " = ") + toliteral(args[1])) + ";"], tmp); .(tmp)(); if (((args.length()) > 1) && ((args[2]) == 'inherit)) { for kid in (.descendants()) kid.(tmp)(); } del_method(tmp); } with { del_method(tmp); rethrow(error()); } } }; new method Replacing public method $root.set_flags(): nooverride public method $root.set_flags(): nooverride { arg new_flags; (> .perms(sender(), 'manager) <); (> $sys.touch() <); if (type(new_flags) != 'list) throw(~invflags, "Flags must be submitted as a list of symbols."); if ((!new_flags) && flags) return clear_var('flags); if ((('core in new_flags) && (!('core in (.flags())))) && (!($sys.is_system(sender())))) throw(~perm, "Only system objects can set the 'core flag."); if (('fertile in new_flags) && (!('fertile in flags))) (> .perms(sender(), 'manager) <); flags = new_flags; }; new method Replacing public method $root.set_setting(): nooverride public method $root.set_setting(): nooverride { arg name, definer, value; var i, args; (> .perms(sender()) <); i = (> definer.setting_info(name) <); if (dict_contains(i, 'parse)) { args = sublist(i['parse], 2); if ((| find_method((i['parse])[1]) |)) value = (> .((i['parse])[1])(value, @args) <); else value = (> $settings.((i['parse])[1])(value, @args) <); } if (dict_contains(i, 'set)) (> .((i['set])[1])(name, definer, value, @sublist(i['set], 2)) <); else settings = dict_add(settings || #[], name, value); }; new method Replacing public method $root.initialize(): nooverride public method $root.initialize(): nooverride { var ancestors, pos, len, method, a, def, str, tb; if ((caller() != $sys) && (sender() != this())) throw(~perm, "Caller is not $sys and sender is not this."); if (inited) throw(~perm, "Already initialized."); ancestors = ancestors(); len = ancestors.length(); for pos in [0 .. len - 1] { refresh(); a = ancestors[len - pos]; if (!(method = (| tosym("init_" + tostr(a.objname())) |))) continue; if ((def = (| find_method(method) |))) { if (def != a) { (| (def.manager()).tell(((("Initialization method for " + a) + " in wrong place (") + find_method(method)) + ")") |); } else { catch any { .(method)(); } with { // try and let somebody know they made a boo-boo somewhere str = ((("UNINIT ERROR " + this()) + "<") + def) + ">:"; tb = traceback().fmt_tb(); if (def) { (| (def.manager()).tell(str) |); (| (def.manager()).tell(tb) |); } if ((.manager()) != sender()) { (| sender().tell(str) |); (| sender().tell(tb) |); } (| sender().tell("Continuing init..") |); (| $sys.log_traceback(tb, "** " + str) |); } } } } inited = 1; }; new method Replacing public method $root.del_method() public method $root.del_method() { arg name; (> .perms(sender()) <); (> del_method(name) <); if ('core in (.flags())) $changelog.log((((("DEL-METHOD: " + this()) + ",") + name) + " by ") + sender()); }; new method Replacing public method $root.debug() public method $root.debug() { arg @stuff; var x, line, mngr, meth, stack, out, ref; stack = stack(); meth = (| (((stack[2])[3]) + "() line ") + ((stack[2])[4]) |); if (sender() != caller()) ref = ((sender() + "<") + caller()) + ">"; else ref = sender(); if (meth) line = ((("DEBUG " + ref) + ".") + meth) + ":"; else line = ("DEBUG " + ref) + ":"; out = [line]; for x in (stuff) out += ($data_lib.unparse_indent(x)).prefix("DEBUG "); (| (.manager()).tell(out) |); }; new method Adding public method $root.write_check(): nooverride public method $root.write_check(): nooverride { arg obj; if (.is($group)) return .includes(obj); else return this() == obj; }; new method Replacing public method $root.is_writable_by(): nooverride public method $root.is_writable_by(): nooverride { arg obj; var o; return (| obj in (.writers()) |) || ($sys.is_system(obj)); for o in (.writers()) { if (o.has_ancestor($group)) { if (o.includes(obj)) return 1; } else if (o == obj) { return 1; } } return $sys.is_system(obj); }; new method Replacing root method $root.change_parents(): nooverride root method $root.change_parents(): nooverride { arg parents; var old_a, old_p, a, obj, new_a, definer, branch, method, str; if (!parents) throw(~noparents, "Objects must have at least 1 parent"); // remember a few things old_a = setremove(ancestors(), this()); old_p = .parents(); branch = (.descendants()) + [this()]; // build the new ancestors list by hand, so we can figure out what is // changing, and uninitialize those ancestors that are going away new_a = []; for obj in (parents) new_a = new_a.union(obj.ancestors()); // uninit any ancestors going away for a in (old_a.set_difference(new_a)) { // call this ancestor's uninit on the obj and all its children method = tosym("uninit_" + (a.objname())); if ((definer = (| find_method(method) |))) { if (definer != a) { // scream madly and run around--everybody should know this str = "UNINIT ERROR: uninit method for " + a; str += (" in wrong place (" + definer) + ")"; (| (definer.manager()).tell(str) |); (| (a.manager()).tell(str) |); (| sender().tell(str) |); continue; } // call the uninit method on this object only catch any { .(method)(); } with { // try and let somebody know they made a boo-boo somewhere str = ((("UNINIT ERROR " + obj) + "<") + this()) + ">:"; (| (.manager()).tell(str) |); (| (.manager()).tell_traceback(traceback()) |); (| sender().tell(str) |); (| sender().tell_traceback(traceback()) |); (| sender().tell("Continuing chparent..") |); } } // cleanup any old obj vars left lying around // if (branch) // $sys.clear_definer_vars(a, branch); $sys.clear_definer_vars(a, [this()]); refresh(); } // make the change (> chparents(parents) <); if ('core in (.flags())) $changelog.log(((((("CHANGE-PARENTS: " + this()) + " from ") + old_p) + " to ") + parents()) + " by "); new_a = setremove(ancestors(), this()); // init anybody new to the family for a in (new_a.set_difference(old_a)) { method = tosym("init_" + (a.objname())); if ((definer = (| find_method(method) |))) { if (definer != a) { // scream madly and run around--everybody should know this // (damn inlaws, can't ever get things right) str = "INIT ERROR: uninit method for " + a; str += (" in wrong place (" + definer) + ")"; (| (definer.manager()).tell(str) |); (| (a.manager()).tell(str) |); (| sender().tell(str) |); continue; } // introduce the new ancestor catch any { .(method)(); } with { // try and let somebody know they made a boo-boo somewhere str = ((("INIT ERROR " + obj) + "<") + this()) + ">:"; (| (.manager()).tell(str) |); (| (.manager()).tell_traceback(traceback()) |); (| sender().tell(str) |); (| sender().tell_traceback(traceback()) |); (| sender().tell("Continuing chparent..") |); } } refresh(); } }; update objvar Updating objvar $sys<$sys>,core_version object $sys; var $sys core_version = "3.0.1998-10-20"; update objvar Updating objvar $sys<$sys>,loggers public method $sys.__upgrade_set_var() { var old, new; old = [$daemon, $user, $connection, $dns]; new = [$daemon, $user, $connection, $dns, $guest]; catch any { dblog("__upgrade_handle_var(1, loggers)"); loggers = .__upgrade_handle_var(1, "$sys<$sys>,loggers", old, loggers, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $sys; eval { .__upgrade_set_var(); }; object $sys; eval { del_method('__upgrade_set_var); }; // old public method $sys.__upgrade_set_var(); add objvar Adding objvar $sys<$root>,settings object $sys; var $root settings = #[["traceback-for", $builder]]; update objvar Updating objvar $sys<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["loggers", #[['get, ['loggers]], ['set, ['set_loggers]], ['parse, ['parse_itemlist, 'parse_object]], ['format, ['format_itemlist]]]], ["deny-hosts", #[['get, ['deny_hosts]], ['set, ['set_deny_hosts]], ['parse, ['parse_itemlist, 'parse_deny_host]], ['format, ['format_itemlist]]]], ["deny-users", #[['get, ['deny_users]], ['set, ['set_deny_users]], ['parse, ['parse_itemlist, 'parse_deny_user]], ['format, ['format_itemlist]]]], ["backup-interval", #[['get, ['get_backup_interval]], ['set, ['set_backup_interval]], ['parse, ['parse_backup_interval]], ['format, ['fmt_backup_interval]]]], ["validate-email-addresses", #[['parse, ['is_boolean]], ['format, ['format_boolean]], ['get, ['validate_email_addresses]], ['set, ['set_validate_email_addresses]]]], ["initial-quota", #[['get, ['get_initial_quota]], ['set, ['set_initial_quota]], ['parse, ['parse_initial_quota]], ['format, ['fmt_initial_quota]]]], ["new-user-class", #[['get, ['get_new_user_class]], ['set, ['set_new_user_class]], ['parse, ['parse_new_user_class]], ['format, ['format_object]]]], ["anonymous-user-class", #[['get, ['get_anon_user_class]], ['set, ['set_anon_user_class]], ['parse, ['parse_anon_user_class]], ['format, ['format_object]]]], ["startup-objects", #[['get, ['get_startup_objects]], ['set, ['set_startup_objects]], ['parse, ['parse_itemlist, 'parse_startup_object]], ['format, ['format_itemlist]]]], ["writable-core", #[['get, ['writable_core]], ['set, ['set_writable_core]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["valid-genders", #[['parse, ['parse_itemlist, 'parse_valid_genders]], ['get, ['get_valid_genders]], ['set, ['set_valid_genders]], ['format, ['format_itemlist]]]], ["heartbeat-interval", #[['get, ['get_heartbeat_interval]], ['set, ['set_heartbeat_interval]], ['parse, ['parse_heartbeat_interval]], ['format, ['fmt_heartbeat_interval]]]]]; new = #[["loggers", #[['get, ['loggers]], ['set, ['set_loggers]], ['parse, ['parse_itemlist, 'parse_object]], ['format, ['format_itemlist]]]], ["deny-hosts", #[['get, ['deny_hosts]], ['set, ['set_deny_hosts]], ['parse, ['parse_itemlist, 'parse_deny_host]], ['format, ['format_itemlist]]]], ["deny-users", #[['get, ['deny_users]], ['set, ['set_deny_users]], ['parse, ['parse_itemlist, 'parse_deny_user]], ['format, ['format_itemlist]]]], ["backup-interval", #[['get, ['get_backup_interval]], ['set, ['set_backup_interval]], ['parse, ['parse_backup_interval]], ['format, ['fmt_backup_interval]]]], ["validate-email-addresses", #[['parse, ['is_boolean]], ['format, ['format_boolean]], ['get, ['validate_email_addresses]], ['set, ['set_validate_email_addresses]]]], ["initial-quota", #[['get, ['get_initial_quota]], ['set, ['set_initial_quota]], ['parse, ['parse_initial_quota]], ['format, ['fmt_initial_quota]]]], ["new-user-class", #[['get, ['get_new_user_class]], ['set, ['set_new_user_class]], ['parse, ['parse_new_user_class]], ['format, ['format_object]]]], ["anonymous-user-class", #[['get, ['get_anon_user_class]], ['set, ['set_anon_user_class]], ['parse, ['parse_anon_user_class]], ['format, ['format_object]]]], ["startup-objects", #[['get, ['get_startup_objects]], ['set, ['set_startup_objects]], ['parse, ['parse_itemlist, 'parse_startup_object]], ['format, ['format_itemlist]]]], ["writable-core", #[['get, ['writable_core]], ['set, ['set_writable_core]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["valid-genders", #[['parse, ['parse_itemlist, 'parse_valid_genders]], ['get, ['get_valid_genders]], ['set, ['set_valid_genders]], ['format, ['format_itemlist]]]], ["heartbeat-interval", #[['get, ['get_heartbeat_interval]], ['set, ['set_heartbeat_interval]], ['parse, ['parse_heartbeat_interval]], ['format, ['fmt_heartbeat_interval]]]], ["traceback-for", #[['parse, ['parse_traceback_for_setting]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$sys<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $sys; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); new method Replacing protected method $sys.set_valid_genders() protected method $sys.set_valid_genders() { arg name, definer, value; switch (value[1]) { case 'set: valid_genders = value[2]; case 'add: valid_genders = setadd(valid_genders, value[2]); case 'del: valid_genders = setremove(valid_genders, value[2]); default: throw(~type, "Unknown action: " + (value[1])); } }; new method Adding private method $sys._logstr() private method $sys._logstr() { arg str; dblog((("[" + ($time.format("%d %h %y %H:%M"))) + "] ") + str); }; new method Replacing public method $sys.parse_valid_genders() public method $sys.parse_valid_genders() { arg value, action, @args; var obj, kids, i; if (!(| (obj = $object_lib.to_dbref("gender_" + value)) |)) (> (obj = $object_lib.to_dbref(value)) <); if (action == 'del) { if (!(obj in (.get_valid_genders()))) throw(~set, ("The object '" + value) + "' is not set, and thus cannot be removed"); return obj; } if (!(obj in ($gender.children()))) throw(~set, ("The object '" + value) + "' is not a child of $gender"); return obj; }; new method Adding public method $sys.slog() public method $sys.slog() { arg msg; var l; if ((!($syslog_group.includes(caller()))) && (!(.is_writable_by(sender())))) throw(~perm, "Only objects in the $syslog_group can log."); if (type(msg) == 'list) { for l in (msg) .slog(l); } else { $channel_ui._broadcast('System, msg); ._logstr(msg); } }; new method Replacing private method $sys.finish_core() private method $sys.finish_core() { var i; // cleanup heartbeat set_heartbeat(1); .add_method(TMP_HEARTBEAT_CODE, 'heartbeat); .del_var('TMP_HEARTBEAT_CODE); // ok, finish up catch any { dblog("** Verifying all non-core objects were destroyed"); for i in ($root.descendants()) { refresh(); if (!(i.has_flag('core))) dblog(("** !!!!! " + i) + " was not destroyed !!!!!"); } .del_var('__making_core); dblog("** corifying remaining objects"); $root.corify(); dblog("** cleaning database.."); .clean_database(); dblog("** shutting down.."); shutdown(); } with { dblog("traceback: " + traceback()); } }; new method Replacing public method $sys.parse_heartbeat_interval() public method $sys.parse_heartbeat_interval() { arg value, @args; value = (> $time.from_english(value) <); if (value < 1) throw(~set, "You cannot set the system heartbeat interval to less than 1 second"); return value; }; new method Adding public method $sys.log_traceback(): forked public method $sys.log_traceback(): forked { arg traceback, @command; var user, log, mail, l, s; if ((!($syslog_group.includes(caller()))) && (!(.is_writable_by(sender())))) throw(~perm, "Permission denied."); [(command ?= "")] = command; user = user() || sender(); log = "Last Command: " + command; log = [log, ("User: " + user()) || sender()]; if (type(traceback[1]) != 'string) traceback = $parse_lib.traceback(traceback); s = (user() || sender()) + ": received traceback"; log += traceback; if ('__making_core in (.variables())) .log(log); else $no_one.mail_as(0, 0, s, log, $mail_list_tracebacks); }; new method Replacing public method $sys.do_backup() public method $sys.do_backup() { arg @args; var line, who, how, name, dirty; (> .perms(sender(), 'system) <); if (dict_contains(backup, 'started)) { .log("BACKUP CONFLICT"); line = "BACKUP CONFLICT at " + ($time.format("%r")); line += ", Current backup started at " + ($time.format("%r", backup['started])); $channel_ui._broadcast('System, line); return; } dirty = .dirty(); [(who ?= sender()), (how ?= 'request)] = args; if (!valid(who)) who = sender(); backup = backup.add('next, time() + (backup['interval])); backup = backup.add('last, time()); if ((how == 'interval) && (!dirty)) return; catch any { name = who.namef('ref); .log(("BACKUP (" + name) + ") "); line = (("Backup started at " + ($time.format("%r"))) + " by ") + name; $channel_ui._broadcast('System, line); } // double pause will hopefully let people know about it before it happens pause(); pause(); backup = backup.add('started, time()); (> backup() <); }; new method Replacing public method $sys.configure_core() public method $sys.configure_core() { var list, l, x, t, err, s; if (caller() != $admin) (> .perms(sender()) <); s = sender(); // if there is nothing left to config, leave.. if (configured) { if (!(list = config_set.set_difference(configured.keys()))) return; } else { configured = #[]; } .add_to_system(s); // wait for other things to finish printing messages to them pause(); pause(); // expand on this as we go s.tell(["*" * 78, strfmt("%78{*}c", " Welcome to ColdCore "), "*" * 78]); s.tell(("This is an interactive configuration system which any admin who connects (until it is completed) is sent through. You must complete this configuration before you can do anything else. You can skip a specific question at any time by typing '@skip'. Suggested default values will be enclosed in square brackets. Pressing enter without any value will use the default value.".wrap_lines(78)).mmap('center, 78)); s.tell("*" * 78); // first question please if (!(configured.contains('new_user_class))) { s.tell("What class should new users be created as? Available classes:"); list = filter x in ($user.descendants()) where ('general_cache in (x.flags())); t = .get_new_user_class(); list = map x in (list) to ((list == t) ? (x + " (current class)") : x); s.tell(list.prefix(" ")); while (!l) { refresh(); l = s.prompt(("New User Class [" + t) + "] "); if (l == "@skip") { s.tell("Skipping.."); break; } if (l) { catch any { l = $object_lib.to_dbref(l); if (!(l in list)) s.tell("Invalid selection, try again."); } with { s.tell(("Invalid selection '" + l) + "'"); continue; } } else { l = t; } .set_setting("new-user-class", $sys, l); configured = configured.add('new_user_class, 1); s.tell("New User Class set to: " + l); } s.tell(["", "You can set this at any time, with the command:"]); s.tell(" @set $sys:new-user-class=" + l); } refresh(); // server name/title if (!(configured.contains('server_name))) { s.tell(["", "---"]); t = $motd.server_name(); l = (s.prompt(("What is your server name? [" + t) + "] ")) || t; if (l == "@skip") { s.tell("Skipping.."); } else { $motd.set_setting("server-name", $motd, l); configured = configured.add('server_name, 1); s.tell("Server name set to: " + l); } s.tell(["", "You can set this at any time, with the command:"]); s.tell(" @set $motd:server-name=" + l); } refresh(); if (!(configured.contains('server_title))) { s.tell(["", "---"]); t = $motd.server_title(); l = (s.prompt(("What is your server title? [" + t) + "] ")) || t; if (l == "@skip") { s.tell("Skipping.."); } else { $motd.set_setting("server-title", $motd, l); configured = configured.add('server_title, 1); s.tell("Server title set to: " + l); } s.tell(["", "You can set this at any time, with the command:"]); s.tell(" @set $motd:server-title=" + l); } refresh(); if (!(configured.contains('daemons))) { s.tell(["", "---"]); while (1) { refresh(); list = ($daemon.children()).setremove($login_daemon); s.tell("Which network daemons do you want to have automatically startup,"); s.tell("Other than $login_daemon. Available daemons:"); t = filter l in (startup['objects]) where (l.is($daemon)); for l in (list) { if (l in t) s.tell(strfmt(" %20s (auto starting)", l)); else s.tell(" " + l); } l = s.prompt(("Auto-Start: [" + (t.join(", "))) + "] "); if (l == "@skip") { s.tell("Skipping.."); break; } else if (!l) { s.tell("Using existing daemons: " + (t.join(", "))); configured = configured.add('daemons, 1); break; } else { err = 0; for x in (l.explode_english_list()) { catch any { .set_setting("startup-objects", $sys, "+" + x); s.tell(("Added " + x) + " as a startup daemon."); } with { s.tell(("Unable to add '" + x) + "' as a daemon:"); s.tell("=> " + ((traceback()[1])[2])); err++; } } if (!err) { configured = configured.add('daemons, 1); break; } s.tell("Errors occurred..."); } } s.tell(["", "You can set this at any time, with the command:"]); s.tell(" @set $motd:startup-objects=OBJECTS..."); } // Other things to add: HTTP Virtual Hosting info, // Let them know, if they actually saw anything.. s.tell(["", strfmt("%79{*}c", " Configuration Complete ")]); }; new method Replacing public method $sys.log() public method $sys.log() { arg msg; var l; if ((!($syslog_group.includes(caller()))) && (!(.is_writable_by(sender())))) throw(~perm, "Only objects in the $syslog_group can log."); if (type(msg) == 'list) { for l in (msg) .log(l); } else { ._logstr(msg); } }; new method Adding public method $sys.parse_traceback_for_setting() public method $sys.parse_traceback_for_setting() { arg value, @args; var obj; obj = (> $object_lib.to_dbref(value) <); if (!(obj.is($user))) throw(~invset, "Setting must be a user type class"); if (!('general_cache in (obj.flags()))) throw(~invset, "Setting must be a user class"); return obj; }; new method Replacing private method $sys.make_core() private method $sys.make_core() { arg ver; var obj, obj2, d, o, top, x, admin, tmp, name; // core rooms should be +core, and cant be destroyed // traverse the list inverseley, less unseen heirarchial shuffling .add_var('__making_core); dblog("** Starting Core Extraction " + ctime()); d = $root.descendants(); top = listlen(d); core_version = ver; dblog(("** " + top) + " objects total, tidying up core objects..."); // tidy up core objects first for obj in (d) { refresh(); if (obj.has_flag('core)) { tmp++; catch any { obj.change_manager(obj); for o in (obj.writers('literal)) { refresh(); obj.del_writer(o); } } with { dblog(("** TIDY " + obj) + " traceback: "); for o in ($parse_lib.traceback(traceback())) dblog("** " + o); } } } // nuke anything not core dblog(("** " + tmp) + " core objects, destroying non-core objects..."); for x in [1 .. top] { pause(); obj = d[(top - x) + 1]; if (!valid(obj)) { // dblog(".. Skipping invalid object " + obj); continue; } if (!(obj.has_flag('core))) { if (obj.children()) { for obj2 in (obj.children()) { if (obj2.has_flag('core)) { dblog("** ABORTING: A NON CORE OBJECT HAS CORE CHILDREN: "); dblog((("** " + obj) + " => ") + (obj.children())); shutdown(); } } } catch any { // dblog(".. Destroying " + obj); obj.destroy(); } with { dblog(("** " + obj) + ".destroy() traceback: "); for o in ($parse_lib.traceback(traceback())) dblog("** " + o); } } } // shutdown this task so that references can have // a chance to clear out, on destroyed objects. dblog("** done, suspending for new task **"); // do this the hard way, to be secure--wait a little while for // things to wrapup, five seconds should be fine. pause(); set_heartbeat(5); .add_var('TMP_HEARTBEAT_CODE, .list_method('heartbeat)); .add_method([".finish_core();"], 'heartbeat); }; new method Adding public method $dictionary.to_dict() public method $dictionary.to_dict() { arg dict; return dict; }; new method Adding public method $string.is_negative() public method $string.is_negative() { arg str; if (match_regexp(str, "^(no|n|false|f|none|nobody|nowhere|0)$")) return 1; return 0; }; new method Replacing public method $string.decode64() public method $string.decode64() { arg enc_chars; var i, j, k, ints, out_buf, len, num, ob; i = 1; out_buf = `[]; len = enc_chars.length(); while (i < len) { refresh(); ints = [0, 0, 0, 0]; for j in [1 .. 4] { for k in [1 .. 64] { refresh(); if (strcmp(enc_chars[i], base64str[k]) == 0) { ints = replace(ints, j, (k - 1) % 64); break; } } i++; } num = 0; out_buf = out_buf + `[(((ints[1]).shleft(2)) % 256) + ((ints[2]).shright(4)), (((ints[2]).shleft(4)) % 256) + ((ints[3]).shright(2)), (((ints[3]).shleft(6)) % 256) + (ints[4])]; } return buf_to_str(out_buf); }; new method Adding public method $string.reverse() public method $string.reverse() { arg string; var length, output, x; length = string.length(); output = ""; for x in [1 .. length] output += string[(length - x) + 1]; return output; }; new method Adding public method $string.regexp_escape() public method $string.regexp_escape() { arg str; // anticipate_assignment(); return strsed(str, "([[\^$|)(.*+?])", "\%1", "g"); }; new method Adding public method $string.is_positive() public method $string.is_positive() { arg str; if (match_regexp(str, "^(yes|y|true|t|all|everybody|anybody|everywhere|anywhere|1)$")) return 1; return 0; }; new method Replacing public method $object_lib.get_name() public method $object_lib.get_name() { arg obj, @args; var meth; // get_name(obj, 'method, [args]) (3rd arg must be a list) if ((type(obj) == 'frob) && (!valid(frob_class(obj)))) return toliteral(obj); if ((type(obj) != 'frob) && (!valid(obj))) return toliteral(obj); [(meth ?= 'name), (args ?= [])] = args; return obj.(meth)(@args); }; new method Replacing public method $parse_lib.traceback() public method $parse_lib.traceback() { arg traceback, @args; var line, out, pre, lines, cur, x, error; // $parse_lib.traceback(traceback(), lines, pre); // -1 lines represents the full error // pre is set to "! " unless otherwise specified. [(lines ?= -1), (pre ?= "! "), (error ?= 0)] = args; out = [(pre + "=> ") + ((traceback[1])[2])]; pre += " "; // The primary error if (error == 0) out += [(pre + "Thrown by ") + (._traceback(@(traceback[2]).subrange(2)))]; else out += [(((pre + "Error ") + error) + " caused by ") + (._traceback(@(traceback[2]).subrange(2)))]; // The rest of it for x in [1 .. (traceback.length()) - 2] { if ((x <= lines) || (lines == (-1))) { line = ((traceback[x + 2])[1]) + ": "; line += ._traceback(@(traceback[x + 2]).subrange(2)); out += [pre + line]; } } if (user()) user().set_last_traceback([time(), traceback, out]); return out; }; new method Replacing public method $parse_lib._traceback() public method $parse_lib._traceback() { arg what, @more; var line; if (more) { if ((more[1]) == (more[2])) return ((((more[1]) + ".") + what) + "() line ") + (more[3]); else return ((((((more[1]) + "<") + (more[2])) + ">.") + what) + "() line ") + (more[3]); } else { return what; } }; new method Replacing public method $parse_lib.opt() public method $parse_lib.opt() { arg line, @defs; var out, a, l, x, m, args, opts, o, i, v; // submit: ["template", "template"..] // => if value is 1, it will take the next part of the string // receive: [["template", "flag", bool, value]], [...]]; opts = (args = []); line = line.explode_quoted(); l = listlen(line); x = 1; while (x <= l) { a = line[x]; if ((m = regexp(a, "^[+-]"))) { o = (m[1]) == "+"; v = ""; a = substr(a, 2).trim(); if (!a) throw(~stop, ("Missing option flag following '" + (o ? "+" : "-")) + "'"); if ((i = "=" in a)) { if (i == strlen(a)) { v = line[++x]; a = substr(a, 1, strlen(a) - 1).trim(); } else { [a, v] = explode(a, "=", 1); } } if ((i = find m in (defs) where (match_template(a, m)))) opts += [[defs[i], a, o, v]]; else opts += [[0, a, o, v]]; } else { args += [a]; } x++; } return [args, opts]; }; new method Replacing public method $code_lib.parse_name() public method $code_lib.parse_name() { arg name, @def; var article, match, flag, type, tmps, ignore; // used to parse $has_name names and name templates [name, flag] = (> $parse_lib.opt(name, "u?nique", "p?roper", "n?ormal", "i?gnore") <); name = name.join(); // Parse +prop +norm +uniq and +ignore flags if (flag) { def = [@def, ["p?roper", "p", 1, ""]][1]; flag = (| flag.last() |) || def; if ((flag[1]) == "i?gnore") { article = 'prop; ignore = 1; } else { switch (flag[1]) { case "n?ormal": type = 'normal; case "u?nique": type = 'uniq; case "p?roper": type = 'prop; } article = type; } } else { article = 'prop; } [name, @tmps] = name.split(" *, *"); // Check to see if the name already has articles in it. if (!ignore) { if ((match = name.regexp("^the +(.*)$"))) { article = 'uniq; name = match[1]; } else if ((match = name.regexp("^(a|an) +(.*)$"))) { article = 'normal; name = match[2]; } // Complain if the flag does not agree with the given article if (type && (article != type)) throw(~article, (("Conflicting name types " + type) + " and ") + article); } return [[name, article], tmps]; }; new method Replacing public method $foundation.match_environment() public method $foundation.match_environment() { arg str; var obj, env, found, match, target; if (!str) throw(~objnf, "No object specified.", str); str = str.strip_article(); // Handle special cases. if (str in ["me", "my"]) { return this(); } else if (((str[1]) == "$") || ((str[1]) == "#")) { return (> $object_lib.to_dbref(str) <); } else if ((str[1]) == "~") { str = str.subrange(2); if ((str[1]) != "~") return $user_db.match_begin(str); } else if (str in ["it", "him", "her"]) { return (| .match_context(str) |) || throw(~context, ("I don't see " + str) + " here, do you?"); } // Start matching found = []; env = .environment(); // special case ordinal references if ((match = $parse_lib.ordinal_reference(str))) return env.match_nth(@match); if ((match = $parse_lib.possessive_reference(str))) { if ((match[1]) == "me") obj = this(); else obj = (> env.match_object(match[1]) <); if (!(obj.match_name(str))) { catch ~objnf, ~ambig, ~range { env = (| obj.contents() |) || []; if ((found = $parse_lib.ordinal_reference(match[2]))) return (> env.match_nth(@found) <); else return (> env.match_object(match[2]) <); } with { if (error() == ~objnf) throw(~objnf, (((obj.name()) + " does not have ") + ((match[2]).add_indefinite())) + "."); else if (error() == ~ambig) throw(~ambig, ((("\"" + str) + "\" can match ") + ((((traceback()[1])[3]).mmap('namef, 'ref)).to_english("", " or "))) + "."); else throw(~objnf, (obj.name()) + "'s what?"); } } } catch any { return (> env.match_object(str) <); } with { if (error() == ~badfrob) { target = (traceback()[1])[3]; obj = frob_value(target)['location]; obj.del_frob_from_contents(target); throw(~badfrob, "Cleaned up bogus frob in your environment, try again.."); } if (error() == ~objnf) throw(~objnf, ("You do not see " + (str.add_indefinite())) + " anywhere."); if (error() == ~ambig) { found = filter obj in ((traceback()[1])[3]) where ((obj.name()) == str); if (listlen(found) == 1) return found[1]; if (found) found = (found.mmap('namef, 'ref)).to_english("", " or "); else found = (((traceback()[1])[3]).mmap('namef, 'ref)).to_english("", " or "); throw(~ambig, ((("\"" + str) + "\" can match ") + found) + "."); } rethrow(error()); } }; new method Replacing public method $has_commands.add_command() public method $has_commands.add_command() { arg template, method, @type; var cmd, types, count, x; (> .perms(sender()) <); [(type ?= 'local)] = type; if ("*" in template) throw(~invcmd, "Invalid command, command templates cannot contain \"*\"!."); cmd = (> $command_lib.validate_command_template(template) <); if (!(type in ['local, 'remote])) throw(~type, "Command types can be either 'local or 'remote"); if ('this in (((cmd[2]).values()).slice(1))) type = 'remote; if (type == 'remote) { for x in (((cmd[2]).values()).slice(1)) { if (x == 'this) count++; } if (!count) throw(~add_command, "Command type defined as remote with no <this> argument."); else if (count > 1) throw(~add_command, "More than one <this> argument specified in template."); } if (!get_var(type)) set_var(type, #[]); set_var(type, get_var(type).setadd_elem((cmd[1])[1], [@cmd[1], template, method, cmd[2]])); if (type == 'remote) $remote_cache.add_remote_command((cmd[1])[1], this()); else if (('general_cache in (.flags())) || (| .command_cache() |)) (| .rehash_cache() |); }; new method Replacing root method $has_commands.uninit_has_commands() root method $has_commands.uninit_has_commands() { var c, cmd; for c in ((.remote_commands()).values()) { for cmd in (c) .del_command(cmd[3], cmd[4]); } (| clear_var('remote) |); (| clear_var('local) |); (| clear_var('shortcuts) |); }; new method Replacing public method $has_name.add_name_template() public method $has_name.add_name_template() { arg template; var p, r; (> .perms(sender()) <); if ((r = regexp(template, "[^a-z0-9|?_-]+"))) throw(~invtmpl, "Template contains invalid characters (allowed: a-z, 0-9, _ and -)"); for p in (explode(template, "|")) { if (match_begin(name[2], p.strip())) throw(~redundant, ("Redundant name template part \"" + p) + "\" already matches name."); } templates = setadd(templates || [], template); }; new method Adding public method $file.fopen() public method $file.fopen() { arg @args; return fopen(@args); }; new method Adding public method $file.fwrite() public method $file.fwrite() { arg what; return fwrite(what); }; new method Adding public method $file.fclose() public method $file.fclose() { return fclose(); }; old method Deleting normal method $compiler.do_action() object $compiler; eval { del_method('do_action); }; update objvar Updating objvar $bs_eval<$root>,flags object $bs_eval; var $root flags = ['variables, 'methods, 'code, 'core, 'fertile]; new method Replacing public method $bs_eval.gen_set() public method $bs_eval.gen_set() { arg vars, flags, args; return [[""], vars.add(((._eval_ctext(flags.getkey("var"), vars))[1])[1], ((._eval_ctext(args[1], vars))[1])[1])]; }; new method Adding public method $bs_eval.gen_fromliteral() public method $bs_eval.gen_fromliteral() { arg vars, flags, args; return [[(| fromliteral(((._eval_ctext(args[1], vars))[1])[1]) |)], vars]; }; new method Adding public method $bs_eval.old_gen_set() public method $bs_eval.old_gen_set() { arg vars, flags, args; var text, name; name = flags.getkey("var"); [text, vars] = ._eval_ctext(args[1], vars); return [[""], vars.add(name, text[1])]; }; old method Deleting normal method $plain_format.do_action() object $plain_format; eval { del_method('do_action); }; new method Replacing public method $tkmoo_format.tag_text() public method $tkmoo_format.tag_text() { arg tag; var match; match = tag.match_pattern("* \{text \"*\"\}*"); if (match) return match[2]; return tag; // this used to throw: // throw(~invtag, "Tag had no text field."); }; new method Replacing public method $ansi_format.weed_ansi() public method $ansi_format.weed_ansi() { arg str; var out; out = str.global_regexp("[\]A[0-9A-LN-Za-ln-z;]+m"); //$user_bruce.debug(out); //$user_bruce.debug(str); return out; return str.global_regexp("\\\A[0-9A-Ln-z;a-ln-z;]+[a-z]"); }; old method Deleting normal method $html_format.do_action() object $html_format; eval { del_method('do_action); }; new method Adding public method $html_format.do_passthru() public method $html_format.do_passthru() { arg vars, flags, args; args = args[1]; return [args, vars]; }; new method Replacing public method $html_format.do_obj() public method $html_format.do_obj() { arg vars, flags, args; var gateway, argname, context, object, name, options; context = flags.getkey("context"); options = (| flags.getkey("options") |); name = flags.getkey("name"); object = args[1]; if (type(context) == 'string) context = tosym(context); if (options && (type(options) == 'string)) options = tosym(options); if (type(object) == 'frob) return [name.to_html(), vars]; switch (context) { case 'look: if (options) { if (options == 'exit) { [gateway, argname] = ["describe", "target"]; object = object.dest(args[2]); } else { [gateway, argname] = ["describe", "target"]; } } else { [gateway, argname] = ["describe", "target"]; } case 'display: [gateway, argname] = ["display", "target"]; } return ["<a href=\"/bin/%s?%s=%s\">%s</a>".format(gateway, argname.to_html(), toliteral(object).to_html(), name.to_html()), vars]; }; new method Replacing public method $housekeeper.did_disconnect() public method $housekeeper.did_disconnect() { var task_queue, task; if (caller() != $user) throw(~perm, "Permission denied"); // Are we removing users? if (($world.get_setting("cleanup-disconnected-users", $world)) == 0) { return; } else { // because of guests if (valid(sender())) $scheduler.add_task(300, 'move_user_home, sender()); } }; new method Replacing public method $settings.is_type() public method $settings.is_type() { arg value, type, @subtypes; var i; if (type(value) == type) return value; switch (type) { case 'list: value = fromliteral(value); if (type(value) != 'list) throw(~type, "Value is unparsable as list."); if (subtypes) value = map i in (value) to ((> .is_type(i, subtypes[1]) <)); return value; case 'dictionary: value = fromliteral(value); if (type(value) != 'dictionary) throw(~type, "Value is unparsable as dictionary."); if (subtypes) value = hash i in (value) to ((> [.is_type(i, subtypes[1]), .is_type(i, subtypes[2])] <)); return value; case 'integer: if (value.is_numeric()) return toint(value); else throw(~type, "Value is unparsable as integer."); case 'symbol: if ((type(value) == 'string) && (((value.length()) > 1) && ((value[1]) == "'"))) value = value.subrange(2); if (type((| tosym(value) |)) == 'symbol) return tosym(value); else throw(~type, "Value is unparsable as a symbol."); case 'objnum: return (> $object_lib.to_dbref(value) <); default: return value; } }; add objvar Adding objvar $world<$world>,realms object $world; var $world realms = []; update objvar Updating objvar $world<$root>,settings public method $root.__upgrade_set_var() { var old, new; old = #[["managed", []], ["starting-place", $the_pit], ["heartbeat-rate", 600], ["weather-rate", 5000]]; new = #[["starting-place", $the_pit], ["weather-rate", 5000], ["cleanup-disconnected-users", 1]]; catch any { dblog("__upgrade_handle_var(1, settings)"); settings = .__upgrade_handle_var(1, "$world<$root>,settings", old, settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $world; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); add objvar Adding objvar $world<$world>,weather_rate object $world; var $world weather_rate = 5400; add objvar Adding objvar $world<$world>,heartbeat_rate object $world; var $world heartbeat_rate = 600; update objvar Updating objvar $world<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["managed", #[['parse, ['is_type, 'list, 'objnum]]]], ["starting-place", #[['parse, ['is_type, 'objnum]]]], ["heartbeat-rate", #[['parse, ['is_type, 'integer]]]], ["weather-rate", #[['parse, ['is_type, 'integer]]]]]; new = #[["starting-place", #[['parse, ['is_type, 'objnum]]]], ["heartbeat-rate", #[['parse, ['parse_heartbeat_rate]], ['get, ['get_heartbeat_rate]], ['set, ['set_heartbeat_rate]], ['format, ['fmt_heartbeat_rate]]]], ["weather-rate", #[['parse, ['parse_weather_rate]], ['get, ['get_weather_rate]], ['set, ['set_weather_rate]], ['format, ['fmt_weather_rate]]]], ["realms", #[['get, ['get_realms]], ['set, ['set_realms]], ['parse, ['parse_itemlist, 'parse_realms]], ['format, ['format_itemlist]]]], ["cleanup-disconnected-users", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$world<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $world; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); new method Adding protected method $world.set_weather_rate() protected method $world.set_weather_rate() { arg name, definer, value; weather_rate = value; }; new method Replacing public method $world.pulse() public method $world.pulse() { var i, d, weather_ticked, t; (> .perms(sender(), $heart) <); t = time(); weather_ticked = 0; if (t >= (last_weather_change + weather_rate)) { weather_ticked = 1; last_weather_change = t; } for i in (realms) { pause(); catch any { i.advance_weather(weather_ticked); } with { (| (i.manager()).tell_traceback(traceback()) |); (| (i.manager()).tell(("Weather change failed for " + i) + ".") |); } } }; new method Adding protected method $world.set_heartbeat_rate() protected method $world.set_heartbeat_rate() { arg name, definer, value; heartbeat_rate = value; if (heartbeat_rate > 0) $heart.add_heartbeat(heartbeat_rate); }; new method Adding protected method $world.set_realms() protected method $world.set_realms() { arg name, definer, value; switch (value[1]) { case 'set: realms = value[2]; case 'add: realms = setadd(realms, value[2]); case 'del: realms = setremove(realms, value[2]); default: throw(~type, "Unknown action: " + (value[1])); } }; new method Adding public method $world.parse_weather_rate() public method $world.parse_weather_rate() { arg value, @args; value = (> $time.from_english(value) <); if (value < 1) throw(~set, "You cannot set the weather rate to less than 1 second"); return value; }; new method Adding public method $world.parse_heartbeat_rate() public method $world.parse_heartbeat_rate() { arg value, @args; value = (> $time.from_english(value) <); if (value < 1) throw(~set, "You cannot set the heartbeat rate to less than 1 second"); return value; }; new method Adding public method $world.parse_realms() public method $world.parse_realms() { arg value, action, @args; var obj, list; obj = (> $object_lib.to_dbref(value) <); if (!(obj.is($realm))) throw(~set, ("The object '" + obj) + "' is not a realm object."); return obj; }; new method Adding public method $world.get_weather_rate() public method $world.get_weather_rate() { arg @args; return weather_rate; }; new method Replacing public method $world.startup() public method $world.startup() { arg @args; (> .perms(sender(), 'manager) <); if (heartbeat_rate > 0) $heart.add_heartbeat(heartbeat_rate); last_weather_change = 0; }; new method Adding public method $world.fmt_weather_rate() public method $world.fmt_weather_rate() { arg data; return $time.to_english(data); }; new method Adding public method $world.fmt_heartbeat_rate() public method $world.fmt_heartbeat_rate() { arg data; return $time.to_english(data); }; new method Adding public method $world.get_heartbeat_rate() public method $world.get_heartbeat_rate() { arg @args; return heartbeat_rate; }; new method Adding public method $world.get_realms() public method $world.get_realms() { arg @ignored; return realms; }; new method Replacing root method $world.core_world() root method $world.core_world() { .set_setting("realms", $world, ""); .set_setting("starting-place", $world, $the_pit); }; update objvar Updating objvar $motd<$motd>,server_title object $motd; var $motd server_title = "Virtual Community Server"; add objvar Adding objvar $motd<$root>,help_node object $motd; var $root help_node = $help_obj_motd; add objvar Adding objvar $motd<$root>,settings object $motd; var $root settings = #[["login-sequence", ['default]]]; update objvar Updating objvar $motd<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["server-name", #[['get, ['get_server_name_setting]], ['set, ['set_server_name_setting]]]], ["server-title", #[['get, ['get_server_title_setting]], ['set, ['set_server_title_setting]]]]]; new = #[["server-name", #[['get, ['get_server_name_setting]], ['set, ['set_server_name_setting]]]], ["server-title", #[['get, ['get_server_title_setting]], ['set, ['set_server_title_setting]]]], ["login-sequence", #[['parse, ['is_type, 'list]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$motd<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $motd; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); new method Replacing root method $motd.core_motd() root method $motd.core_motd() { server_url = "http://none:1180/"; .del_method('build_html); .rename_method('core_build_html, 'build_html); server_name = "ColdCore"; server_title = "Virtual Community Server"; welcome_notes = []; }; new method Replacing public method $motd.build() public method $motd.build() { arg @args; var output, out, line; output = []; if (!args) args = ['long, 'quote]; if ((args[1]) == 'default) args = ['name, "", 'title, "", "", 'quote, "", 'notes, 'admins, "", 'connected, 'core_version, 'driver_version, 'help, ""]; while (args) { if (type(args[1]) == 'string) { output += [""]; } else { switch (args[1]) { case 'long: args = ['title, 'long_name] + sublist(args, 2); continue; case 'short: args = ['title, 'name] + sublist(args, 2); continue; case 'title: output += [server_title.center(79)]; case 'name: output += [(("+ " + server_name) + " +").center(79)]; case 'notes: output += notes.center_lines(79); case 'quote: output += ($code_lib.random_quote()).center_lines(79); case 'admins: out = ($list.to_english($list.mmap($sys.admins(), 'name))).wrap_lines(50); line = out[1]; output += (["Administrators: " + line] + delete(out, 1)).mmap('center, 79); case 'connected: out = "Currently Connected users: "; out += tostr(($user_db.connected()).length()); out = out.center(79); output += [out]; case 'version: args = ['driver_version, 'core_version] + sublist(args, 2); continue; case 'driver_version: out = "Driver: " + ($sys.server_info('driver_version, 'long)); output += [out.center(79)]; case 'core_version: out = "Core: " + ($sys.server_info('core_version, 'long)); output += [out.center(79)]; case 'help: out = " ** Use 'Help' for a list of commands**"; output += [out.center(79)]; } } args = delete(args, 1); } return output; }; new method Replacing public method $located.move_to(): nooverride public method $located.move_to(): nooverride { arg place; var old, mover; // Don't do anything if we're already here. if (place == location) return; if (!(place.has_ancestor($location))) throw(~type, (place.namef('ref)) + " is not a location."); if (place == this()) throw(~move, "You cannot move something into itself."); if (!valid(location)) location = $nowhere; mover = sender(); (> .will_move(mover, place) <); (> location.will_leave(mover, place) <); (> place.will_arrive(mover, location) <); // Set location. old = location; location = place; old.del_sender_from_contents(); place.add_sender_to_contents(); // Notify involved parties of completed move, in reverse order. place.did_arrive(mover, old); old.did_leave(mover, place); .did_move(mover, old); }; new method Replacing root method $located.uninit_located() root method $located.uninit_located() { var location; location = .location(); if (valid(location)) { location.del_sender_from_contents(); location.did_leave(this(), $nowhere); } }; new method Replacing public method $thing.parse_home() public method $thing.parse_home() { arg value, @args; var home; home = (| .match_environment(value) |) || (> $place_db.search(value) <); if ((!(home.is_writable_by(user()))) && ((!(home.trusts(sender()))) && (!(home.get_setting("public-home", $place))))) throw(~notpublic, ("You do not have permission to make " + (home.name())) + " your home."); return home; }; new method Replacing public method $thing.boot_cmd() public method $thing.boot_cmd() { arg cmdstr, cmd, this; var loc, dest, exit; loc = .location(); if (!(| loc.perms(sender(), 'manager) |)) { (| .tell((((sender().name()) + " tried to boot you from ") + (loc.name())) + "!") |); loc.announce((((((sender().name()) + " tried to boot ") + (.name())) + " from ") + (loc.name())) + "!", sender(), this()); return ((("Only " + ((loc.manager()).name())) + " can boot people from ") + (loc.name())) + "!"; } dest = .home(); catch any { sender().tell(("You boot " + (.name())) + "."); loc.announce((((((sender().name()) + " boots ") + (.name())) + " from ") + ((.location()).name())) + ".", this(), sender()); if ((sender().location()) != loc) (sender().location()).announce((((((sender().name()) + " boots ") + (.name())) + " from ") + ((.location()).name())) + ".", this(), sender()); (> .move_to(dest) <); } with { return (traceback()[1])[2]; } }; update objvar Updating objvar $note<$root>,flags object $note; var $root flags = ['core]; new method Replacing public method $page_bin_index._show_object() public method $page_bin_index._show_object() { arg obj, what; var top, middle, bottom, desc, alert, nalert, line; middle = (bottom = []); top = [("<h1>" + (._make_object_href(obj))) + "</h1>"]; // CORENOTE: merge this with a central location (likely $directories) alert = ("<p><font size=\"+1\" color=\"#" + (($cml_color.get_color("red"))[1])) + "\"><b>"; nalert = "</b></font>"; top += ["<table>"]; top += [("<tr><td><b>Perms</b>:</td><td>" + (((.flags()).prefix("+")).join())) + "</td></tr>", ("<tr><td><b>Size</b>:</td><td>" + ((obj.size()).to_english())) + " bytes (on disk)</td></tr>", ("<tr><td><b>Manager</b>:</td><td>" + (._make_object_href(obj.manager()))) + "</td></tr>", ._show_header_objs(obj.writers('literal), "Writer"), ._show_header_objs(obj.parents(), "Parent")]; if (obj.has_ancestor($located)) top += [("<tr><td><b>Location</b>:</td><td>" + (._make_object_href(obj.location()))) + "</td></tr>"]; if (obj.help_node()) top += [((("<tr><td><b>Associated Help</b>:</td><td><a href=\"/bin/help?node=" + (obj.help_node())) + "\">") + (obj.help_node())) + "</a></td></tr>"]; top += [("<tr><td><b>Credit</b>:</td><td>" + join(obj.credit(), "<br>")) + "</td></tr>"]; top += ["</table><p><hr size=1 noshade><p>"]; if (obj.has_ancestor($described)) { if (what['desc]) { bottom += ["<p><b>Description</b>:<blockquote><pre>"]; desc = obj.prose(); switch (type(desc)) { case 'frob: for line in (desc.uncompile()) bottom += line.wrap_lines(79, " "); case 'list: bottom += desc; case 'string: bottom += [desc]; } bottom += ["</pre></blockquote>"]; middle += [._make_show_object_href("Hide Description", obj, what, 'desc, 0)]; } else { middle += [._make_show_object_href("Show Description", obj, what, 'desc, 1)]; } top += ["</td></tr>"]; } if (what['methods]) { if (!(obj.has_flag('methods, this()))) bottom += [(alert + "** No permission to List Methods **") + nalert]; else bottom += (["<p><b>Methods:</b><blockquote><pre>"] + (._show_methods(obj))) + ["</pre></blockquote>"]; middle += [._make_show_object_href("Hide Methods", obj, what, 'methods, 0)]; } else { middle += [._make_show_object_href("List Methods", obj, what, 'methods, 1)]; } if (what['vars]) { if (!(obj.has_flag('variables, this()))) bottom += [(alert + "** No permission to Show Variables **") + nalert]; else bottom += (["<p><b>Variables:</b><blockquote><pre>"] + (._show_variables(obj))) + ["</pre></blockquote>"]; middle += [._make_show_object_href("Hide Variables", obj, what, 'vars, 0)]; } else { middle += [._make_show_object_href("Show Variables", obj, what, 'vars, 1)]; } return (((top + middle) + ["<p>"]) + bottom) + ["<p>"]; }; new method Replacing public method $page_bin_index.object() public method $page_bin_index.object() { arg header, info, args; var out, obj, o, line, objs, m; obj = (| args["target"] |); out = [@.build_header(header, info, args, obj.namef('xref)), ("<h1 align=center>" + (._make_display_href(obj, "&methods=1"))) + "</h1>"]; line = "<p align=center><b>Parent(s)</b>: " + ((| ._make_object_href((obj.parents())[1]) |) || "(none)"); for o in ((| (obj.parents()).subrange(2) |) || []) line += ", " + (._make_object_href(o)); out += [line + "</p>", "<table>"]; objs = obj.children(); if (obj) { out += ["<p align=center><b>Children:</b></p>", "<center><table cellspacing=0 cellpadding=0>", "<tr><td width=25%><b>Name</b></td><td width=25%><b>Perms</b></td><td width=25%><b>Size</b></td><td width=25%><b>Manager</b></td></tr>"]; for o in (objs) { refresh(); m = o.manager(); if (!valid(o)) m = toliteral(m); else m = ._make_object_href(m); out += [((((((("<tr><td>" + (._make_object_href(o))) + "</td><td>") + ($object_lib.see_perms(o, ["", ""]))) + "</td><td>") + ((o.size()).to_english())) + "</td><td>") + m) + "</td></tr>"]; } } out += ["</table><p>", join(obj.credit(), "<br>"), "</center>"]; return [out + (.build_footer(header, info, args))]; }; new method Adding public method $page_bin_index._foof() public method $page_bin_index._foof() { arg @args; return []; }; new method Replacing public method $page_bin_index.method() public method $page_bin_index.method() { arg header, info, args; var ref, str_ref, name, obj, code, def, out, line, linenumbers, user, strings, flags, trace, anc, current, m, options; ref = (| args["target"] |); linenumbers = (| args["linenumbers"] |); if (!("linenumbers" in (args['arg_list]))) { if ($security_lib.check_userdb_with_optional(header['interface])) { user = (header['interface]).get_info('run_as); linenumbers = (| user.get_setting("www-show-line-num", $www_preferences) |) || 0; } } catch any { name = (> tosym(ref[4]) <); obj = ref[3]; def = obj.find_method(name); if ('native in (def.method_flags(name))) code = ["This method is implemented natively within the driver."]; else code = (def.list_method(name)).mmap('html_escape); options = (("linenumbers" in (args['arg_list])) && linenumbers) ? [["linenumbers", "yes"]] : []; code = $code_lib.code_to_html(code, obj, options); if (linenumbers) code = code.numbered_text(); str_ref = ((obj + ".") + name) + "()"; out = [@.build_header(header, info, args, str_ref), ((((("<h1>Method code for " + (._make_string_to_display_href(obj, "&methods=yes"))) + ((def != obj) ? (("<" + (._make_string_to_display_href(def, "&methods=yes"))) + ">") : "")) + ".") + name) + "()") + "</h1>", "<blockquote>"]; strings = linenumbers ? ["no", "off"] : ["yes", "on"]; out += [strfmt("[<A HREF=\"/bin/method?target=%s&linenumbers=%s\">Turn %s line numbering</A>]", str_ref, @strings)]; out += ["<hr size=1 noshade width=\"50%\" align=left><pre>"]; out += code + ["</pre><hr size=1 noshade width=\"50%\" align=left>"]; line = "// " + ((def.credit()).join("<br>// ")); out += [("<font color=\"#a0a0a0\">" + line) + "</font>"]; out += ["</blockquote>"]; strings = (trace = []); current = def; while (current) { trace += [current]; current = (| def.find_next_method(name, current) |); } if ((trace.length()) > 1) { out += ["<h2>Method Ancestry Override:</h2>"]; out += ["<blockquote><pre>"]; for anc in (trace) { m = anc.method_info(name); out += [strfmt(("%5l %4r " + (._make_string_to_display_href(anc))) + (._make_method_href([anc, name, m[1]], @options)), $object_lib.parse_method_flags(m[6]), m[4])]; } out += ["</pre></blockquote>"]; } } with { switch (error()) { case ~type: return [(header['interface]).response(400, ((("Invalid method reference " + obj) + ".") + name) + "()")]; case ~methodnf: line = ((obj + ".") + name) + "()"; return [(header['interface]).response(400, line + " not found.")]; default: return [(header['interface]).response(400, (traceback()[1])[2])]; } } return [out + (.build_footer(header, info, args))]; }; add objvar Adding objvar $mail_message<$mail_message>,frominet object $mail_message; var $mail_message frominet = 0; new method Replacing public method $mail_message.send() public method $mail_message.send() { arg @recips; var r, valid, invalid, from; if (!($mail_lib.has_mail_perms(caller()))) (> .perms(sender()) <); if (delivered) throw(~delivered, "This mail has already been delivered."); if (!recips) recips = .recipients(); if (((recips.length()) == 1) && ((recips[1]) == $no_one)) throw(~norcpt, "No recipients specified."); valid = []; invalid = []; for r in (recips) { if (r.has_ancestor($mail_list)) valid += [r]; else invalid += [r]; } if (invalid) throw(~invrcpt, "Invalid mail recipients: " + (invalid.mmap('name)), invalid); recips = valid; invalid = []; // ok, now that we have that cleared up, lets set pertinent info... .set_time(time()); if ((!(.from())) || (sender() != $no_one)) .set_from(sender()); // and now to finalize the recipients for r in (recips) { if ((r.list_is_inet()) && (!frominet)) { from = (sender().user_info("name")) || (sender().name()); from += (" <" + (sender().user_info("email"))) + ">"; r = r.get_setting("inet-list", $mail_list); $smtp.sendmail(from, r, header['subj], .body()); delivered++; } else if (r.list_is_sendable_by(sender())) { r.add_mail(); .add_recipient(r); delivered++; } else { invalid += [r]; } } if (!delivered) throw(~delivered, "Unable to deliver message."); return invalid; }; new method Adding public method $mail_message.is_frominet() public method $mail_message.is_frominet() { if (sender() == $no_one) frominet = 1; }; new method Replacing public method $command_cache.command_modules() public method $command_cache.command_modules() { arg @args; return modules || []; }; new method Replacing public method $command_cache.cache_server_uninit() public method $command_cache.cache_server_uninit() { var user; if (!(sender().has_ancestor(this()))) throw(~nochild, ((sender() + " is not a descendant of ") + this()) + "."); // see if anybody still needs us, otherwise purge if (.is_general_cache()) { for user in ($user_db.connected()) { if (user.has_ancestor(this())) return; } } .purge_cache(); }; new method Replacing public method $command_cache.del_command_module() public method $command_cache.del_command_module() { arg module; (> .perms(sender()) <); modules = setremove(modules || [], module); module.cache_server_uninit(); }; new method Replacing public method $command_cache.match_shortcut() public method $command_cache.match_shortcut() { arg str, @ignore; var s, match, obj, args; for obj in (([this()] + filter s in (parents()) where (s.has_ancestor($command_cache))) + modules) { for s in ((obj.shortcut_cache()) || []) { if ((match = match_pattern(str, s[1])) != 0) { args = $command_lib.handle_shortcut_fields((s[2])[2], match); return ['shortcut, [(s[2])[1], [str, @args]]]; } } } return 0; }; new method Replacing protected method $command_cache.set_command_modules() protected method $command_cache.set_command_modules() { arg name, definer, value; var m; switch (value[1]) { case 'set: for m in (modules.set_difference(value[2])) .del_command_module(m); for m in ((value[2]).set_difference(modules)) .add_command_module(m); case 'add: .add_command_module(value[2]); case 'del: .del_command_module(value[2]); default: throw(~type, "Unknown action: " + (value[1])); } }; new method Replacing public method $command_cache.match_remote_command() public method $command_cache.match_remote_command() { arg str, cmd, args; var command, m, matched, templates, info, cdef, def, cmds, c; if (this() != $remote_cache) throw(~perm, "This should only be used on $remote_cache"); templates = (matched = []); if (commands && dict_contains(commands, cmd)) cmds = commands[cmd]; else return 0; for command in (cmds) { if (!(info = (command[2]).command_info('remote, command[1]))) continue; for cdef in (info) { if ((m = match_template(args, cdef[2])) != 0) matched += [[listlen(m), command[2], [str, cmd, @m], @sublist(cdef, 3)]]; } templates = templates.union(info.slice(3)); refresh(); } if (matched) return ['remote, matched]; if (!templates) return 0; return ['partial, templates]; }; new method Replacing root method $command_cache.uninit_command_cache() root method $command_cache.uninit_command_cache() { var m; (| .purge_cache() |); for m in (modules || []) m.cache_server_uninit(); }; update objvar Updating objvar $mail_list<$root>,flags object $mail_list; var $root flags = ['methods, 'code, 'core, 'variables, 'fertile]; update objvar Updating objvar $mail_list<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["inet-list", #[['parse, ['parse_inet_list_setting]]]]]; new = #[["inet-list", #[['parse, ['parse_inet_list_setting]]]], ["mail-readers", #[['get, ['get_maillist_setting]], ['set, ['set_maillist_setting]], ['parse, ['parse_maillist_setting]], ['format, ['fmt_maillist_setting]]]], ["mail-senders", #[['get, ['get_maillist_setting]], ['set, ['set_maillist_setting]], ['parse, ['parse_maillist_setting]], ['format, ['fmt_maillist_setting]]]], ["mail-notify", #[['get, ['get_maillist_setting]], ['set, ['set_maillist_setting]], ['parse, ['parse_maillist_setting]], ['format, ['fmt_maillist_setting]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$mail_list<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $mail_list; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); new method Adding public method $mail_list.get_maillist_setting() public method $mail_list.get_maillist_setting() { arg name, definer; name = tosym(substr(name, 6)); if ((name == 'readers) || ((name == 'senders) || (name == 'notify))) return get_var(name); throw(~perm, "Permission Denied"); }; new method Replacing root method $mail_list.init_mail_list() root method $mail_list.init_mail_list() { mail = []; senders = 1; if (!(.has_ancestor($user))) { readers = 1; notify = []; (| $mail_db.insert(.name(), this()) |); } else { readers = [.manager()]; notify = [.manager()]; } }; new method Replacing root method $mail_list.uninit_mail_list() root method $mail_list.uninit_mail_list() { var m; for m in (mail) .del_mail(m); mail = []; senders = 1; readers = [.manager()]; notify = []; if (!(.has_ancestor($user))) (| $mail_db.remove(.name()) |); $smtp.remove_aliases(); }; new method Adding public method $mail_list.parse_maillist_setting() public method $mail_list.parse_maillist_setting() { arg value; var action, list, item, out; value = value.trim(); if (value.is_positive()) return ['set, 1]; else if ((value.is_negative()) || (value == "writers")) return ['set, 0]; if (value && ((value[1]) in ["+", "-"])) { if ((value[1]) == "-") action = 'del; else action = 'add; list = [substr(value, 2)]; } else { action = 'set; list = value.explode_english_list(); } out = []; for item in (list) out += [(> $object_lib.to_dbref(item) <)]; if (action == 'set) return [action, out]; else return [action, out[1]]; }; new method Replacing public method $mail_list.add_sender_to_notification() public method $mail_list.add_sender_to_notification() { var who; if (caller() != $mail_ui) throw(~perm, "Permission Denied"); who = sender(); if (!(who.has_ancestor($user))) throw(~type, "Sender is not a user."); if (!(.list_is_readable_by(who))) throw(~perm, ((who.name()) + " cannot read ") + (.mail_name())); notify = setadd(notify, who); }; new method Adding protected method $mail_list.set_maillist_setting() protected method $mail_list.set_maillist_setting() { arg name, definer, value; var action; name = tosym(substr(name, 6)); [action, value] = value; if ((name != 'readers) && ((name != 'senders) && (name != 'notify))) throw(~perm, "Permission Denied"); switch (action) { case 'set: set_var(name, value); case 'add: set_var(name, setadd(get_var(name), value)); case 'del: set_var(name, setremove(get_var(name), value)); } }; new method Adding public method $mail_list.fmt_maillist_setting() public method $mail_list.fmt_maillist_setting() { arg data; if (type(data) == 'list) return join(data, ", "); else if (data) return "anybody"; else return "writers"; }; new method Replacing protected method $mail_ui.send_to_cmd() protected method $mail_ui.send_to_cmd() { arg cmdstr, cmd, str; var subj, lists, note, list, x, mail, text, args, edit; (> .perms(caller(), 'command) <); if ((args = match_template((str[1]).join(" "), "* to *"))) { note = args[1]; args = args[3]; } else { note = ""; args = (str[1]).join(" "); } if (args) { if (!(lists = .parse_mail_recipient_list(args))) return "No (valid) lists specified."; } else { lists = [current['list]]; .tell(("No recipient specified, using current recipient (" + ((lists[1]).mail_name())) + ")"); } edit = "e?dit" in ((str[2]).slice(1)); edit = edit ? (((str[2])[edit])[3]) : (.get_setting("@send-editor", $mail_ui)); // get the text of the message if ((!note) && edit) { if (.active_editor()) { .tell("Storing active editor.."); .store_editor(); } subj = ""; text = []; (> .invoke_editor(this(), '_edit_mail_callback, text, ['mail, lists, subj, 0, 0]) <); if (.active_editor()) { .tell(("Editor invoked with " + ((.active_editor()).session_name())) + "."); .tell("Type 'help' for available commands."); } } else { if (note) { text = (> (.match_env_nice(note)).get_raw_text() <); } else { text = .read("-- Enter text for mail message, \".\" when done or \"@abort\" to abort --"); if (text == 'aborted) return; if (text == 'engaged) return "** Already reading - mail send aborted **"; } subj = .prompt("Subject: "); mail = $mail_message.new_mail(); mail.set_subject(subj); mail.set_text(text); catch any mail.send(@lists); with return (traceback()[1])[2]; return "Mail sent."; } }; new method Adding protected method $mail_ui.parse_mail_recipient_list() protected method $mail_ui.parse_mail_recipient_list() { arg str; var recip, lists; lists = []; for recip in (str.explode_english_list()) { catch ~listnf { recip = (> $mail_lib.match_mail_recipient(recip) <); if (recip.list_is_sendable_by(this())) lists += [recip]; else .tell("You cannot send to " + (recip.mail_name())); } with { .tell(("The recipient \"" + recip) + "\" is invalid."); } } return lists; }; new method Replacing protected method $mail_ui.reply_cmd() protected method $mail_ui.reply_cmd() { arg cmdstr, cmd, str; var list, msg, args, i, subj, text, recip; (> .perms(caller(), 'command) <); if ((args = match_template(str, "to *"))) str = args[2]; if ((args = match_template(str, "* on *"))) [msg, str, list] = args; else msg = str; if (!list) { list = current['list]; } else { catch ~listnf, ~perm { list = (> $mail_lib.match_mail_recipient(list) <); (> .new_list(list) <); } with { return (traceback()[1])[2]; } } if (!msg) { if (!valid((msg = (| (subscribed[list])[2] |)))) return "No current message to reply to."; } else { catch ~range msg = $mail_lib.range_to_actual($parse_lib.range(msg), current); with return (traceback()[1])[2]; msg = msg[1]; } i = msg in (list.mail()); if (list.is($user)) recip = msg.from(); else recip = list; if (!(recip.is($mail_list))) return (list.namef('ref)) + " is not a valid mail recipient."; .tell(((("Replying to message " + i) + " on ") + (list.mail_name())) + "."); text = msg.body(); if (text == ["", "(no message)", ""]) text = []; text = $mail_lib.indent_reply(text); text = [((("On " + ($time.format("%d-%b-%Y", msg.time()))) + " ") + ((msg.from()).namef('ref))) + " said: "] + text; if (.active_editor()) { .tell("Storing active editor.."); .store_editor(); } subj = msg.subject(); if (!(subj.match_begin("Re:"))) subj = "Re: " + subj; (> .invoke_editor(this(), '_edit_mail_callback, text, ['mail, [recip], subj, i, msg]) <); if (.active_editor()) { .tell(("Editor invoked with " + ((.active_editor()).session_name())) + "."); .tell("Type 'help' for available commands."); } }; new method Replacing protected method $mail_ui.mail_remove_cmd() protected method $mail_ui.mail_remove_cmd() { arg cmdstr, cmd, str; var mail, args, lmail, list, rng, m, x, name, lname, offset, ans; (> .perms(caller(), 'command) <); if ((args = match_template(str, "* on|from *"))) { rng = args[1]; list = args[3]; } else if (!str) { return "You must specify a message and list."; } else { // grr, be hacky args = explode(str); if ((args.length()) > 1) { list = args.last(); if (!(| $mail_lib.match_mail_recipient(list) |)) { rng = str; list = ""; } else { rng = (args.delete(args.length())).join(); } } else { rng = str; list = ""; } } if (!rng) return ("You must specify a message to remove from " + lname) + "."; if (!list) { list = current['list]; ans = .prompt(((("Remove mail " + rng) + " from ") + (list.mail_name())) + "? "); if (match_regexp(ans, "no|n")) return "Ok, aborting.."; } else { catch ~listnf list = (> $mail_lib.match_mail_recipient(list) <); with return ("The list \"" + list) + "\" is invalid."; } lname = list.mail_name(); catch any (> .new_list(list) <); with return (traceback()[1])[2]; if (rng == "$") { mail = (> $mail_lib.range_to_actual(['end, 'single], current) <); } else if (rng && ((rng[1]) == "$")) { catch ~namenf mail = [(> $object_lib.to_dbref(rng) <)]; with return (traceback()[1])[2]; } else { catch ~range mail = (> $mail_lib.range_to_actual($parse_lib.range(rng), current) <); with return (traceback()[1])[2]; } lmail = list.mail(); if ((mail[1]) != (| lmail[1] |)) { offset = (mail[1]) in lmail; lmail = sublist(lmail, offset); offset--; } for m in (mail) { catch ~perm { x = (m in lmail) + offset; name = ((((("#" + x) + " \"") + (m.subject())) + "\" (") + m) + ")"; list.del_mail(m); .tell(((("Removed message " + name) + " from ") + (list.mail_name())) + "."); } with { .tell((traceback()[1])[2]); } } }; new method Replacing protected method $mail_ui.subscribe_cmd() protected method $mail_ui.subscribe_cmd() { arg cmdstr, cmd, str; var list, mname, l, args, line, len, out; (> .perms(caller(), 'command) <); // this is ugly bad bad args = (> $parse_lib.opt(str, "n?ew") <); if (!(args[1])) { if ("n?ew" in ((args[2]).slice(1))) { out = []; for l in ((subscribed.keys()).setremove(this())) { if ((l.last_received_on()) > ((subscribed[l])[1])) out += [" " + (l.mail_name())]; } if (out) .tell(["New mail on:"] + out); else .tell(["No new mail on the lists you are subscribed to."]); return; } .tell("Currently Subscribed Lists:"); len = (.linelen()) / 3; for l in ((subscribed.keys()).setremove(this())) { line = " " + (l.mail_name()); if ((l.last_received_on()) > ((subscribed[l])[1])) line += " (new mail)"; .tell(line); } .tell("---"); return; } catch ~listnf { list = $mail_lib.match_mail_recipient(str); } with { .tell(("The list '" + str) + "' is not a valid list."); return; } mname = $mail_lib.mail_name(list); if (list in (subscribed.keys())) return .tell(("You are already subscribed to " + mname) + "."); if (!(list.list_is_readable_by(this()))) return .tell(mname + " is not subscribeable by you."); .subscribe(list); .tell(("Successfully subscribed to " + mname) + "."); }; new method Replacing protected method $mail_ui.mail_read_cmd() protected method $mail_ui.mail_read_cmd() { arg cmdstr, cmd, str; var mail, m, args, opts, lname, list, rng, args, meta; (> .perms(caller(), 'command) <); [args, opts] = (> $parse_lib.opt(str, "m?eta") <); str = args.join(" "); meta = []; if ((m = "m?eta" in (opts.slice(1)))) { if ((opts[m])[3]) meta = [1]; } if ((args = match_template(str, "* on *"))) { rng = args[1]; catch ~listnf list = (> $mail_lib.match_mail_recipient(args[3]) <); with return (traceback()[1])[2]; } else { rng = str; list = current['list]; } catch ~perm (> .new_list(list) <); with return (traceback()[1])[2]; if (((list.mail()).length()) == 0) return ("There is no mail on " + (list.mail_name())) + "."; if (!rng) return ("You must specify a message to read on " + (list.mail_name())) + "."; catch ~range { if (rng == "next") { .read_mail((> list.mail_list_next((subscribed[list])[2]) <), list, @meta); } else if (rng == "prev") { .read_mail((> list.mail_list_prev((subscribed[list])[2]) <), list, @meta); } else { for m in ($mail_lib.range_to_actual($parse_lib.range(rng), current)) .read_mail(m, list, @meta); } } with { return ((("Mail message " + rng) + " does not exist on ") + (list.mail_name())) + "."; } }; new method Replacing public method $location.did_leave() public method $location.did_leave() { arg mover, place; if (caller() != $located) throw(~perm, "Caller is not $located."); }; new method Replacing public method $location.did_arrive() public method $location.did_arrive() { arg mover, place; if (caller() != $located) throw(~perm, "Caller is not $located."); }; new method Replacing public method $location.will_arrive() public method $location.will_arrive() { arg mover, old_place; if (caller() != $located) throw(~perm, "Caller is not $located."); }; new method Replacing public method $location.will_leave() public method $location.will_leave() { arg mover, place; if (caller() != $located) throw(~perm, "Caller is not $located."); }; new method Replacing public method $located_location.will_arrive() public method $located_location.will_arrive() { arg mover, old_place; (> pass(mover, old_place) <); if (sender() == (.location())) throw(~perm, ((sender().namef('ref)) + " is holding ") + (.namef('ref))); }; clear objvar Clearing objvar $body<$command_cache>,shortcuts object $body; old var $command_cache shortcuts; clear objvar Clearing objvar $body<$command_cache>,commands object $body; old var $command_cache commands; update objvar Updating objvar $body<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["wh?isper", [["wh?isper", "* to *", "wh?isper <any> to <any>", 'whisper_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["say", [["say", "*", "say <any>", 'say_cmd, #[[1, ['any, []]]]]]], ["to", [["to", "* say *", "to <any> say <any>", 'to_say_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["emote", [["emote", "*", "emote <any>", 'emote_cmd, #[[1, ['any, []]]]]]], ["quote", [["quote", "*", "quote <any>", 'quote_cmd, #[[1, ['any, []]]]]]], ["spoof", [["spoof", "*", "spoof <any>", 'spoof_cmd, #[[1, ['any, []]]]]]], ["pose", [["pose", "*", "pose <any>", 'spoof_cmd, #[[1, ['any, []]]]]]], ["think", [["think", "*", "think <any>", 'think_cmd, #[[1, ['any, []]]]]]], ["wear", [["wear", "*", "wear <any>", 'wear_cmd, #[[1, ['any, []]]]]]], ["remove|shed", [["remove|shed", "*", "remove|shed <any>", 'remove_cmd, #[[1, ['any, []]]]]]], ["@a?ction", [["@a?ction", "*", "@a?ction <any>", 'action_cmd, #[[1, ['any, []]]]]]]]; new = #[["wh?isper", [["wh?isper", "* to *", "wh?isper <any> to <any>", 'whisper_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["say", [["say", "*", "say <any>", 'say_cmd, #[[1, ['any, []]]]]]], ["to", [["to", "* say *", "to <any> say <any>", 'to_say_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["emote", [["emote", "*", "emote <any>", 'emote_cmd, #[[1, ['any, []]]]]]], ["quote", [["quote", "*", "quote <any>", 'quote_cmd, #[[1, ['any, []]]]]]], ["spoof", [["spoof", "*", "spoof <any>", 'spoof_cmd, #[[1, ['any, []]]]]]], ["think", [["think", "*", "think <any>", 'think_cmd, #[[1, ['any, []]]]]]], ["wear", [["wear", "*", "wear <any>", 'wear_cmd, #[[1, ['any, []]]]]]], ["remove|shed", [["remove|shed", "*", "remove|shed <any>", 'remove_cmd, #[[1, ['any, []]]]]]], ["@act?ion", [["@act?ion", "*", "@act?ion <any>", 'action_cmd, #[[1, ['any, []]]]]]], ["pose", [["pose", "*", "pose <any>", 'pose_cmd, #[[1, ['any, []]]]]]], ["get|take", [["get|take", "*", "get|take <descendant of $thing>", 'get_cmd, #[[1, ['descendant, [$thing]]]]], ["get|take", "* from *", "get|take <any> from <descendant of $location>", 'get_from_cmd, #[[1, ['any, []]], [3, ['descendant, [$location]]]]]]], ["drop", [["drop", "*", "drop <descendant of $thing>", 'drop_cmd, #[[1, ['descendant, [$thing]]]]]]], ["give|put", [["give|put", "* to|in|on *", "give|put <descendant of $thing> to|in|on <descendant of $thing>", 'give_to_cmd, #[[1, ['descendant, [$thing]]], [3, ['descendant, [$thing]]]]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$body<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $body; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); add objvar Adding objvar $body<$body>,last_command object $body; var $body last_command = 0; add objvar Adding objvar $body<$body>,last_traceback object $body; var $body last_traceback = 0; old method Deleting normal method $body.reset_actions() object $body; eval { del_method('reset_actions); }; old method Deleting normal method $body.action_cmd() object $body; eval { del_method('action_cmd); }; old method Deleting normal method $body.actions() object $body; eval { del_method('actions); }; old method Deleting normal method $body.register_action() object $body; eval { del_method('register_action); }; new method Replacing public method $body.pose_cmd() public method $body.pose_cmd() { arg cmdstr, cmd, args; var shortwords, preword_punct_chars, postword_punct_chars, preword_punct_expr, postword_punct_expr, pronouns, ant_pronouns, selfmsg, othersmsg, recips, antecedent, prepunct, postpunct, word, oword, things, who, aliases, msg, cap, name, wname, m, w, quoted, msgdict, posessive, name_expr; (> .perms(caller(), $user, $body) <); if (!args) return; args = explode("." + (args.trim())); // ------------ shortwords = ["a", "an", "the", "to", "for", "out", "of", "on", "at", "and"]; preword_punct_chars = "[\"'`([{]"; postword_punct_chars = "[]})\"',.!?:;]"; // ------------ preword_punct_expr = ("^" + preword_punct_chars) + "+"; postword_punct_expr = postword_punct_chars + "+$"; pronouns = (.gender()).pronouns(); ant_pronouns = $gender_neuter.pronouns(); selfmsg = (othersmsg = (recips = (antecedent = []))); quoted = 0; for word in (args) { if ((m = match_regexp(word, preword_punct_expr))) { prepunct = substr(word, @m[1]); word = substr(word, ((m[1])[2]) + 1); } else { prepunct = ""; } if ((m = match_regexp(word, postword_punct_expr))) { postpunct = substr(word, @m[1]); word = substr(word, 1, ((m[1])[1]) - 1); } else { postpunct = ""; } oword = word; quoted = (quoted + (((prepunct + word).sed("[^\"]+", "", "g")).length())) % 2; if (!quoted) { if ((word[1]) == "\\") { oword = (word = word.subrange(2)); } else if (word in shortwords) { // don't match against common short words. } else if (word in ["me", "myself"]) { word = "yourself"; oword = pronouns['pr]; } else if (word == "I") { word = "you"; oword = pronouns['ps]; } else if (word == "my") { word = "your"; oword = pronouns['pp]; } else if (word == "mine") { word = "yours"; oword = pronouns['pq]; } else if (word in [ant_pronouns['ps], "%s"]) { word = ant_pronouns['ps]; oword = antecedent ? [antecedent, word, "you"] : word; } else if (word in [ant_pronouns['po], "%o"]) { word = ant_pronouns['po]; oword = antecedent ? [antecedent, word, "you"] : word; } else if (word in [ant_pronouns['pp], "%p"]) { word = ant_pronouns['pp]; oword = antecedent ? [antecedent, word, "your"] : word; } else if (word in [ant_pronouns['pr], "%r"]) { word = ant_pronouns['pr]; oword = antecedent ? [antecedent, word, ((antecedent.length()) > 1) ? "yourselves" : "yourself"] : word; } else if (word in [ant_pronouns['pq], "%q"]) { word = ant_pronouns['pq]; oword = antecedent ? [antecedent, word, "yours"] : word; } else if ((word[1]) == ".") { // verb to conjugate word = substr(word, 2); if (match_regexp(word, "(ch|sh|s)$")) oword = word + "es"; else if (match_regexp(word, "[^a]y$")) oword = substr(word, 1, strlen(word) - 1) + "ies"; else oword = word + "s"; } else if ((word[1]) == ":") { // a verb for antecedent, to conjugate word = substr(word, 2); if (match_regexp(word, "es$")) oword = substr(word, 1, strlen(word) - 2); else if (match_regexp(word, "ies$")) oword = substr(word, 1, strlen(word) - 3) + "y"; else if (match_regexp(word, "s$")) oword = substr(word, 1, strlen(word) - 1); if ((antecedent.length()) < 2) oword = [antecedent, word, oword]; else word = oword; } else { if ((| substr(word, (word.length()) - 1, 2) |) == "'s") { posessive = "'s"; word = (oword = substr(word, 1, (word.length()) - 2)); } else { posessive = ""; } if (((word[word.length()]) == "*") || (word in ["everyone", "everything"])) { // look for matching things.. if (word in ["everyone", "everything"]) { things = word == "everything"; word = ""; } else if (((word.length()) > 1) && ((word[(word.length()) - 1]) == "*")) { // match things too. word = substr(word, 1, (word.length()) - 2); things = 1; } else { // just match people. things = 0; word = substr(word, 1, (word.length()) - 1); } catch ~ambig, ~objnf { who = [.match_environment(word)]; } with { if ((error() == ~objnf) && word) { who = []; } else { catch ~ambig who = [(.environment()).match_object(word)]; with who = (traceback()[1])[3]; } } who = who.setremove(this()); if (!things) who = filter w in (who) where (w.is($body)); else who = filter w in (who) where (w.is($thing)); if (who) { word = map w in (who) to ((w.name()) + posessive).to_english(); recips = union(recips, who); } else { word = (things ? "nothing" : "nobody") + posessive; } oword = word; posessive = ""; antecedent = who; ant_pronouns = ((antecedent.length()) == 1) ? (((antecedent[1]).gender()).pronouns()) : ($gender_plural.pronouns()); } else if ((| (who = .match_environment((w = word))) |) && (who.is($body))) { // Might be a valid match for a username.. if ((wname = who.name()) == w) { // full name match. Make sure it's capitalized right. word = (oword = wname); recips = setadd(recips, who); antecedent = [who]; ant_pronouns = (who.gender()).pronouns(); } else { aliases = who.name_templates(); aliases = map w in (aliases) to (explode(w, "|")).flatten(); aliases = map w in (aliases) to (strsub(w, "?", "")); if (word in aliases) { word = (oword = wname); recips = setadd(recips, who); antecedent = [who]; ant_pronouns = (who.gender()).pronouns(); } } } word += posessive; oword += posessive; } } quoted = (quoted + ((postpunct.sed("[^\"]+", "", "g")).length())) % 2; selfmsg += [(prepunct + word) + postpunct]; if (type(oword) == 'string) othersmsg += [(prepunct + oword) + postpunct]; else othersmsg += [[oword[1], (prepunct + (oword[2])) + postpunct, (prepunct + (oword[3])) + postpunct]]; refresh(); } msg = ""; cap = 0; for word in (selfmsg) { word = cap ? (" " + (word.capitalize())) : (" " + word); msg += word; cap = match_regexp(word, "[.!?:][^A-Za-z0-9_]*$"); refresh(); } msgdict = #[[this(), (<$ctext_frob, [[("You" + msg) + (cap ? "" : ".")], #[]]>)]]; name = .name(); for w in (recips + [0]) { wname = w ? (w.name()) : 0; cap = 0; msg = ""; name_expr = ((((("( |^)" + preword_punct_chars) + "*(") + ((w.name()).regexp_escape())) + ")('s)?") + postword_punct_chars) + "*( |$)"; for word in (othersmsg) { switch (type(word)) { case 'string: if (w && (wname != "you")) { while ((m = word.match_regexp(name_expr))) { if ((m[4])[1]) word = ((word.subrange(1, ((m[3])[1]) - 1)) + "your") + (word.subrange(((m[4])[1]) + ((m[4])[2]))); else word = ((word.subrange(1, ((m[3])[1]) - 1)) + "you") + (word.subrange(((m[3])[1]) + ((m[3])[2]))); } } word = cap ? (" " + (word.capitalize())) : (" " + word); case 'list: if (w in (word[1])) word = cap ? (" " + ((word[3]).capitalize())) : (" " + (word[3])); else word = cap ? (" " + ((word[2]).capitalize())) : (" " + (word[2])); } msg += word; cap = match_regexp(word, "[.!?:][^A-Za-z0-9_]*$"); refresh(); } msg = (name + msg) + (cap ? "" : "."); msgdict = msgdict.add(w || "general", (<$ctext_frob, [[msg], #[]]>)); } (.location()).announce((<$message_frob, msgdict>)); }; new method Adding public method $body.set_last_traceback() public method $body.set_last_traceback() { arg tb; if (caller() != $parse_lib) throw(~sorry, "nope."); last_traceback = tb; }; new method Replacing public method $body.tell_traceback() public method $body.tell_traceback() { arg traceback, @parse; if (parse && (| ((parse[2]).find_method(parse[3])).has_flag('core) |)) $sys.log_traceback(traceback, last_command); if (.has_ancestor($sys.get_setting("traceback-for", $sys))) { .tell(traceback.fmt_tb()); .tell(["!", "! You may want to use @report to report this problem."]); } else { .tell("OOPS! An error has occurred, contact an administrator for help."); } }; new method Adding protected method $body.get_cmd() protected method $body.get_cmd() { arg cmdstr, cmd, what; var ol, l, isuser; (> .perms(caller(), 'command) <); ol = what.location(); if (ol == this()) { throw(~stop, ("You already have " + (what.name())) + "."); } else if (what == this()) { throw(~stop, "Ewww, its all twisty."); } else { l = .location(); if (l != ol) { isuser = ol.is($user); if ((| ol.location() |) != l) throw(~stop, ("You are not in " + (what.location())) + "."); } catch any { (> what.move_to(this()) <); } with { if (error() == ~locked) { if (isuser) ol.tell((((.name()) + " tried to take ") + (what.name())) + " from you."); rethrow(~stop); } else { rethrow(~stop); } } if (isuser) ol.tell((((.name()) + " takes ") + (what.name())) + " from you."); l.announce((((.name()) + " takes ") + (what.name())) + ".", this(), ol); if (l != ol) { if (!isuser) l.announce((((.name()) + " takes ") + (what.name())) + "."); return ((("You take " + (what.name())) + " from ") + (ol.name())) + "."; } return ("You take " + (what.name())) + "."; } }; new method Adding public method $body.set_last_command() public method $body.set_last_command() { arg cmd; // HACKNOTE: Remove if (caller() != $user) return; last_command = cmd; }; new method Adding protected method $body.give_to_cmd() protected method $body.give_to_cmd() { arg cmdstr, cmd, what, p, loc; var c, obj, l, wl, str; (> .perms(caller(), 'command) <); if (!(what in (.contents()))) return ("You don't have " + (what.name())) + "."; if (what == this()) return "Give yourself away? Interesting..."; if (what == loc) return ((("Uhh, you cannot give " + ((what.gender()).pronoun('po))) + " to ") + ((what.gender()).pronoun('pr))) + "."; if (loc.is($place)) return .drop_cmd(cmdstr, cmd, what); catch any { l = .location(); wl = loc.location(); (> what.move_to(loc) <); str = (((" " + (what.name())) + " ") + p) + " "; .tell(((("You " + cmd) + str) + (loc.name())) + "."); (| loc.tell((((((.name()) + " ") + cmd) + "s") + str) + "you.") |); cmd += "s"; str = (str + (loc.name())) + " "; if (l != wl) wl.announce((((.name()) + " ") + cmd) + str, this(), loc); l.announce((((.name()) + " ") + cmd) + str, this(), loc); } with { .tell_traceback(traceback()); return (traceback()[1])[2]; } }; new method Adding protected method $body.get_from_cmd() protected method $body.get_from_cmd() { arg cmdstr, cmd, what, p, loc; var c, obj, l, wl, str; (> .perms(caller(), 'command) <); if (loc == this()) return "Huh? Get what?"; for c in (loc.contents()) { if (c.match_name(what)) obj = c; } if (!obj) { if (loc.is($place)) return ("No \"" + what) + "\" in your environment."; else return ((loc.name()) + " does not have ") + what; } if ((obj == this()) || (obj == loc)) return "Ewww, its all twisty."; if (loc.is($place)) return .get_cmd(cmdstr, cmd, obj); catch any { l = .location(); (> obj.move_to(this()) <); str = (((" " + (obj.name())) + " ") + p) + " "; wl = loc.location(); .tell(((("You " + cmd) + str) + (loc.name())) + "."); (| loc.tell((((((.name()) + " ") + cmd) + "s") + str) + "you.") |); cmd += "s"; str = (str + (loc.name())) + " "; if (l != wl) wl.announce((((.name()) + " ") + cmd) + str, this(), loc); l.announce((((.name()) + " ") + cmd) + str, this(), loc); return; } with { switch (error()) { case ~locked: if (loc.is($user)) loc.tell((((((.name()) + " tried to take ") + (obj.name())) + " ") + p) + " you."); return (((obj.name()) + " is locked to ") + ((obj.lock()).lock_name('thing))) + "."; default: return (traceback()[1])[2]; } } }; new method Adding protected method $body.clear_last_traceback() protected method $body.clear_last_traceback() { (| clear_var('last_traceback) |); }; new method Adding protected method $body.drop_cmd() protected method $body.drop_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); if (!(what in (.contents()))) { return ("You don't have " + (what.name())) + "."; } else { catch any { (> what.move_to(.location()) <); .tell(("You drop " + (what.name())) + "."); (| (.location()).announce((((.name()) + " drops ") + (what.name())) + ".", this(), what) |); } with { return (traceback()[1])[2]; } } }; new method Adding public method $body.last_traceback() public method $body.last_traceback() { return last_traceback; }; new method Replacing public method $robot.parse_line() public method $robot.parse_line() { arg line; var parse; (> .perms(sender()) <); catch any { parse = $command_parser.parse(this(), line, $null_parser); (> .handle_parser_result(line, @parse) <); } with { if (error() == ~stop) { if ((traceback()[1])[2]) .tell((traceback()[1])[2]); } else if ((.manager()) != this()) { (.manager()).tell(traceback().fmt_tb()); } else { .tell_traceback(traceback()); } } }; new method Replacing public method $help_ui.find_help_in_index() public method $help_ui.find_help_in_index() { arg str; var indices, i, node, index, matches, len; // get from $help_lib to keep in a consistent prioritized order indices = $help_lib.indices(); // put the 'current' node at the end, and use it first if ((i = sender().help_index())) { indices = setremove(indices, i); indices = setadd(indices, i); } // loop through the indices backwards len = listlen(indices); matches = []; for i in [1 .. len] { i = (len - i) + 1; catch any { if ((node = (| (indices[i]).exact_match(str) |))) { // return the first perfect match return node; } else if ((node = (> (indices[i]).match_begin(str) <))) { matches = setadd(matches, node); } } with { if (error() == ~ambig) matches += ((traceback()[1])[3]) || []; } } if (listlen(matches) == 1) return matches[1]; else if (matches) throw(~ambig, "More than one match.", matches); throw(~nonode, ("Unable to find help on \"" + str) + "\"."); }; new method Replacing root method $help_ui.uninit_help_ui() root method $help_ui.uninit_help_ui() { (| clear_var('history) |); (| clear_var('current) |); (| clear_var('index) |); }; new method Replacing protected method $help_ui.parse_help_reference() protected method $help_ui.parse_help_reference() { arg str; var node, cnode, current, indices, len, links, i, matches, m; if ((str[1]) == "$") { node = (| $object_lib.to_dbref(str) |); if (node && (node.help_node())) node = node.help_node(); else if ((!node) || (!(node.has_ancestor($help_node)))) throw(~nonode, ("\"" + str) + "\" is not a help node, and does not have a help node assigned to it."); return node; } if ((m = match_template(str, "*=*"))) { if (!(m[2])) throw(~nonode, ("Search in " + (m[1])) + " for nothing?"); else if (match_template(m[1], "g?roup")) return (> .find_help_in_group(m[2]) <); else if (match_template(m[1], "l?inks")) return (> .find_help_in_links(m[2]) <); else if (match_template(m[1], "i?ndex")) return (> .find_help_in_index(m[2]) <); if (!(i = $help_index.match_children(m[1]))) throw(~nonode, ("\"" + (m[1])) + "\" is not a help index."); if ((m[2]) == "#") return i; if (!(node = (| i.match_begin(m[2]) |))) throw(~nonode, ((("Unable to find help on \"" + (m[2])) + "\" in the ") + (i.name())) + " index."); return node; } if (">" in str) return (> .step_help_nodes(split(str, " *> *")) <); if ((m = regexp(str, "(\.[a-z][0-9a-z_]+)\( *\)"))) { str = m[1]; } else if ((m = regexp(str, " *([a-z][0-9a-z_]+)\( *\)"))) { i = "help_func_" + (m[1]); if ((node = (| lookup(tosym(i)) |))) return node; else throw(~nonode, ("Unable to find help on function " + (m[1])) + "()"); } return (| .find_help_in_links(str) |) || ((| .find_help_in_group(str) |) || (> .find_help_in_index(str) <)); }; new method Replacing protected method $help_ui.help_cmd() protected method $help_ui.help_cmd() { arg cmdstr, cmd, args; var o, opt, optval, way, node, links, i; (> .perms(caller(), 'command) <); o = #[["?", ["h?istory"]], ["<", ["b?ack"]], [">", ["f?orward"]], ["!", ["fix"]], ["#", ["l?inks"]], ["^", ["u?p"]]]; args = (> $parse_lib.opt(args, o.values()) <); opt = args[2]; args = args[1]; if (!opt) { if (!args) { if (cmd == "?") node = .current_node(); else node = $help_lib.default_node(); } else { args = args.join(); if ((args[1]) in (o.keys())) { opt = (o[args[1]])[1]; if ((args.length()) > 1) optval = args.subrange(2); } else if ((o = match_template(args, "* in *"))) { if (!(i = $help_index.match_children(o[3]))) return ("\"" + (o[3])) + "\" is not a help index."; if ((!(o[1])) || ((o[1]) == "#")) node = i; else if (!(node = (| i.match_begin(o[1]) |))) return ((("Unable to find help on \"" + (o[1])) + "\" in the ") + (i.name())) + " index."; } else { catch ~nonode, ~ambig { node = (> .parse_help_reference(args) <); } with { if (error() == ~ambig) { o = (traceback()[1])[3]; i = (.get_rows()) - 3; .tell(((("Topic '" + args) + "' has ") + (o.length())) + " possibilities:"); if ((o.length()) > i) { i--; .tell((sublist(o, 1, i).mmap('namef, 'ref)).prefix(" ")); .tell(("[truncated, " + ((o.length()) - i)) + " more matches]"); } else { .tell((o.mmap('namef, 'ref)).prefix(" ")); } return "---"; } return (traceback()[1])[2]; } } } } else { // since all options override each other, just use the last one. optval = (opt[opt.length()])[4]; opt = (opt[opt.length()])[1]; } if (!node) { catch ~nonode { switch (opt) { case "u?p": o = ((.current_node()).parents())[1]; while ((o.is($help_node)) && (o.holder())) o = (o.parents())[1]; if ((!(o.is($help_node))) || (o.top_of_help_heirarchy())) return "You are at the top of this help node heirarchy."; node = o; case "h?istory": return ._help_node_history(); case "b?ack": if (!optval) optval = ""; node = (> ._navigate_node_history("<" + optval) <); case "f?orward": if (!optval) optval = ""; node = (> ._navigate_node_history(">" + optval) <); case "fix": .tell("Fixing your help history."); for node in (history) { if ((!valid(node)) || (!(node.has_ancestor($help_node)))) history = setremove(history, node); } current = listlen(history); return; case "l?inks": node = .current_node(); links = node.links(); if (!links) { .tell(("No links from " + (node.name())) + "."); } else { .tell(("Links from " + (node.name())) + ":"); .tell(map i in (links) to (strfmt("%30l %s", @i)).prefix(" ")); } if (node.group()) { links = ((node.parents())[1]).children(); links = filter o in (links) where ((!(o.nolist())) && (o != node)); if (!links) return ("No group nodes with " + (node.name())) + "."; .tell(("Group nodes with " + (node.name())) + ":"); .tell(map i in (links) to (strfmt("%30e %s", i.name(), i)).prefix(" ")); } return; } } with { return (traceback()[1])[2]; } } .set_help_node(node); .tell_help_node(node); }; new method Replacing public method $editor_reference.invoke_editor() public method $editor_reference.invoke_editor() { arg object, method, initial_text, cdata; // finishing object, finishing method, initial text, client data; if (active_editor != 0) throw(~misc, "Editor already active"); (> object.perms(sender()) <); active_editor = $editor_session.spawn(); if (active_editor.startup(object, method, initial_text, cdata)) .add_parser($editor_parser); }; new method Replacing public method $editor_reference.edit_cmd() public method $editor_reference.edit_cmd() { arg cmdstr, com, args; var syn, num, sess, out, type, i, e, bg; (> .perms(caller(), 'command) <); syn = "@edit <object reference> [+type=...]"; args = args.trim(); if (!args) { // list sessions out = []; e = .active_editor(); if (e) { if ($editor_parser in (.parsers())) out += ["** %0 " + (e.session_name())]; else out += [" %0 " + (e.session_name())]; } bg = .background_editor_sessions(); for sess in [1 .. listlen(bg)] out += [((" %" + sess) + " ") + ((bg[sess]).session_name())]; if (out) return ["Editor Sessions:"] + out; return "No editor sessions."; } else if ((args[1]) == "%") { // resume session args = substr(args, 2); if ((!args) || ((args[1]) == " ")) { num = 0; } else { catch ~nonum num = (> args.to_number() <); with return (traceback()[1])[2]; } if (!num) { if (.active_editor()) return .reinvoke_editor(.active_editor(), "%0"); else if (.background_editor_sessions()) sess = (.background_editor_sessions())[1]; else return "No sessions to resume."; } else { if ((listlen((.background_editor_sessions()) || []) < num) || (num < 0)) return ("There is not an editor session %" + num) + "."; sess = (.background_editor_sessions())[num]; } return .reinvoke_editor(sess, "%" + num); } else { args = (> $parse_lib.opt(args, "t?ype") <); if ((i = "t?ype" in ((args[2]).slice(1)))) type = ((args[2])[i])[4]; type ?= "any"; catch ~objnf, ~namenf args = replace(args, 1, (> $parse_lib.ref((args[1]).join()) <)); with return (traceback()[1])[2]; return .edit(@args, type); } }; clear objvar Clearing objvar $menu<$command_cache>,shortcuts object $menu; old var $command_cache shortcuts; clear objvar Clearing objvar $menu<$command_cache>,commands object $menu; old var $command_cache commands; new method Replacing public method $menu.do_menu() public method $menu.do_menu() { arg @menu; var l, str, options, title, prompt, temp, instr, helptext, accept_any, accept_skip, accept_exit, accept_numeric, accept_return, myline, mylist, reloop; if ((menu.length()) < 3) throw(~menu, "Menu must consist of title, prompt text, and at least one option."); // Obtain the title and prompt text: title = menu[1]; menu = menu.delete(1); prompt = menu[1]; menu = menu.delete(1); options = []; .tell(""); pause(); .menubar(title); for l in [1 .. menu.length()] { switch (type((menu[l]) || 'blank)) { case 'symbol: switch ((menu[l]) || 'blank) { case 'accept_any: // Accept any input accept_any = 1; case 'accept_numeric: // Accept numeric input accept_numeric = 1; case 'back: // .tell(" [-] Back Up"); options = [@options, "-"]; case 'blank: // Probably not needed. .tell(""); case 'exit: // .tell(" [X] Exit"); options = [@options, "X"]; accept_exit = 1; case 'help: // .tell(" [?] Help"); options = [@options, "?"]; case 'nothing: // Nothing; not even a blank line. case 'return: accept_return = 1; case 'skip: // .tell(" [+] Skip Set"); options = [@options, "+"]; accept_skip = 1; } case 'list: // One of the elements is a list. Split this // up as we do with normal strings, columnize // it, store the options, then columnize it. mylist = []; for myline in (menu[l]) { myline.replace("=> ", "=>"); temp = myline.explode("=>"); if ((temp.length()) == 1) { // It's just a string. Print it. // .tell(" "+temp[1]); mylist = mylist.add((temp[1]) + " "); } else { // It's a menu choice and txt. mylist = mylist.add(((("[" + ((temp[1]).uppercase())) + "] ") + (temp[2])) + " "); // .tell(" ["+temp[1].uppercase()+"] "+temp[2]); options = [@options, ((temp[1])[1]).uppercase()]; } } mylist = mylist.lcolumnize(); for myline in (mylist) .tell(" " + myline); case 'string: // Break things up into choice, text: (menu[l]).replace("=> ", "=>"); temp = (menu[l]).explode("=>"); if ((temp.length()) == 1) { // It's just a string. Print it. .tell(" " + (temp[1])); } else { // It's a menu choice and txt. switch (temp[1]) { case "?": // .tell(" ["+temp[1].uppercase()+"] Help"); // helptext=temp[2]; // options=[@options,temp[1][1].uppercase()]; default: // Print the choice and text: .tell(((" [" + ((temp[1]).uppercase())) + "] ") + (temp[2])); options = [@options, ((temp[1])[1]).uppercase()]; } } } } .menubar(); pause(); reloop = 1; while (reloop == 1) { reloop = 0; .tell(""); .non_terminated_tell(prompt); instr = tostr(.prompt(" ")); if (((instr.length()) > 1) && ((instr[1]) == "~")) { .tell(""); .menuline("Command Line: " + ((instr.subrange(2)).chop(40))); reloop = 1; ((.connections())[1]).parse_line(instr.subrange(2)); .tell(""); .menuline(); } if (instr == "abort") { .tell("Aborted! Exiting menu."); throw(~abort, "Aborted! Exiting menu.", 'notraceback); } } if (helptext && (instr == "?")) { .atell("[help!]"); .atell(helptext); .prompt("Press Return> "); } // Yell at the user if a valid option is not selected: if ((!(accept_return && (instr == ""))) && ((!(accept_numeric && (instr.is_numeric()))) && ((!accept_any) && ((instr in options) == 0)))) { .tell(""); .tell(("Valid options are " + ([@options, "Abort"].to_english())) + "."); menu_choice = 'invalid; } // 'skip, 'exit and such can be specified in the menu call. If these // are included, accept_skip, accept_exit, etc. will be set to 1. If // the user then selects the approprate character, 'skip, 'exit, etc. // will be returned instead of the character. Why? I don't know. if (accept_skip && (instr == "+")) instr = 'skip; if (accept_exit && (instr == "X")) instr = 'exit; if (accept_return && (instr == "")) instr = 'return; menu_choice = instr; return instr; }; add objvar Adding objvar $user<$user>,away object $user; var $user away = 0; add objvar Adding objvar $user<$user>,connection_options object $user; var $user connection_options = 0; add objvar Adding objvar $user<$user>,away_time object $user; var $user away_time = 0; update objvar Updating objvar $user<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["experienced", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["global-tell", #[['get, ['get_global_tell]], ['set, ['set_global_tell]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["cols", #[['get, ['get_cols]], ['set, ['set_cols]], ['parse, ['is_type, 'integer]]]], ["rows", #[['get, ['get_rows]], ['set, ['set_rows]], ['parse, ['is_type, 'integer]]]], ["prompt", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["auto-look", #[['get, ['get_auto_look]], ['set, ['set_auto_look]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["content-type", #[['set, ['set_content_type]], ['parse, ['parse_content_type]], ['format, ['format_content_type]], ['clear, ['clear_content_type]], ['get, ['get_content_type]]]], ["extended-parsers", #[['parse, ['parse_ext_parsers]], ['format, ['format_ext_parsers]]]], ["exit-style", #[['parse, ['parse_exit_style]]]], ["title", #[['get, ['title]], ['set, ['set_title]]]]]; new = #[["experienced", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["global-tell", #[['get, ['get_global_tell]], ['set, ['set_global_tell]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["cols", #[['get, ['get_cols]], ['set, ['set_cols]], ['parse, ['is_type, 'integer]]]], ["rows", #[['get, ['get_rows]], ['set, ['set_rows]], ['parse, ['is_type, 'integer]]]], ["prompt", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["auto-look", #[['get, ['get_auto_look]], ['set, ['set_auto_look]], ['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["content-type", #[['set, ['set_content_type]], ['parse, ['parse_content_type]], ['format, ['format_content_type]], ['clear, ['clear_content_type]], ['get, ['get_content_type]]]], ["extended-parsers", #[['parse, ['parse_ext_parsers]], ['format, ['format_ext_parsers]]]], ["exit-style", #[['parse, ['parse_exit_style]]]], ["title", #[['get, ['title]], ['set, ['set_title]]]], ["@who-options", #[]], ["away", #[['get, ['get_away]], ['set, ['set_away]], ['clear, ['clear_away]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$user<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $user; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); update objvar Updating objvar $user<$root>,settings public method $root.__upgrade_set_var() { var old, new; old = #[["experienced", 0], ["exit-style", 'none], ["home", $body_cave], ["prompt", 0], ["extended-parsers", []]]; new = #[["experienced", 0], ["exit-style", 'brief], ["home", $body_cave], ["prompt", 0], ["extended-parsers", []], ["@who-options", ""]]; catch any { dblog("__upgrade_handle_var(1, settings)"); settings = .__upgrade_handle_var(1, "$user<$root>,settings", old, settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $user; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); update objvar Updating objvar $user<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["@quit", [["@quit", "", "@quit", 'quit_cmd, #[]]]], ["i?nventory", [["i?nventory", "", "i?nventory", 'inventory_cmd, #[]]]], ["@audit", [["@audit", "*", "@audit <any>", 'audit_cmd, #[[1, ['any, []]]]]]], ["@who", [["@who", "*", "@who <any>", 'who_cmd, #[[1, ['any, []]]]]]], ["@del-command-a?lias|@dca?lias", [["@del-command-a?lias|@dca?lias", "*", "@del-command-a?lias|@dca?lias <any>", 'del_command_alias_cmd, #[[1, ['any, []]]]]]], ["@command-a?liases|@ca?liases", [["@command-a?liases|@ca?liases", "*", "@command-a?liases|@ca?liases <any>", 'command_aliases_cmd, #[[1, ['any, []]]]]]], ["@add-command-a?lias|@aca?lias", [["@add-command-a?lias|@aca?lias", "*", "@add-command-a?lias|@aca?lias <any>", 'add_command_alias_cmd, #[[1, ['any, []]]]]]], ["@com?mands", [["@com?mands", "*", "@com?mands <any>", 'commands_cmd, #[[1, ['any, []]]]]]], ["@news", [["@news", "", "@news", 'news_cmd, #[]]]], ["@forget", [["@forget", "*", "@forget <any>", 'forget_cmd, #[[1, ['any, []]]]]]], ["@whereis|@where-is", [["@whereis|@where-is", "*", "@whereis|@where-is <any>", 'whereis_cmd, #[[1, ['any, []]]]]]], ["@password|@passwd", [["@password|@passwd", "*", "@password|@passwd <any>", 'password_cmd, #[[1, ['any, []]]]]]], ["@age", [["@age", "*", "@age <object>", 'age_cmd, #[[1, ['object, []]]]]]], ["@context", [["@context", "", "@context", 'context_cmd, #[]]]], ["get|take", [["get|take", "*", "get|take <thing>", 'get_cmd, #[[1, ['descendant, [$thing]]]]], ["get|take", "* from *", "get|take <any> from <descendant of $location>", 'get_from_cmd, #[[1, ['any, []]], [3, ['descendant, [$location]]]]]]], ["drop", [["drop", "*", "drop <thing>", 'drop_cmd, #[[1, ['descendant, [$thing]]]]]]], ["@rename", [["@rename", "*", "@rename <any>", 'rename_cmd, #[[1, ['any, []]]]]]], ["@add-writer|@aw", [["@add-writer|@aw", "*", "@add-writer|@aw <any>", 'add_writer_cmd, #[[1, ['any, []]]]]]], ["@del-writer|@dw", [["@del-writer|@dw", "*", "@del-writer|@dw <any>", 'del_writer_cmd, #[[1, ['any, []]]]]]], ["@manage?d", [["@manage?d", "*", "@manage?d <any>", 'managed_cmd, #[[1, ['any, []]]]]]], ["@remember", [["@remember", "* as *", "@remember <object> as <any>", 'remember_cmd, #[[1, ['object, []]], [3, ['any, []]]]]]], ["@remembered", [["@remembered", "*", "@remembered <any>", 'remembered_cmd, #[[1, ['any, []]]]]]], ["give|put", [["give|put", "* to|in *", "give|put <thing> to|in <thing>", 'give_to_cmd, #[[1, ['descendant, [$thing]]], [3, ['descendant, [$thing]]]]]]], ["discard", [["discard", "*", "discard <object>", 'discard_cmd, #[[1, ['object, []]]]]]], ["@writes", [["@writes", "*", "@writes <object>", 'writes_cmd, #[[1, ['object, []]]]]]], ["@trusted?-by", [["@trusted?-by", "*", "@trusted?-by <object>", 'trusted_by_cmd, #[[1, ['object, []]]]]]], ["@add-trust?ee|@at", [["@add-trust?ee|@at", "*", "@add-trust?ee|@at <object:>", 'add_trustee_cmd, #[[1, ['object_opt, []]]]]]], ["@del-trust?ee|@dt", [["@del-trust?ee|@dt", "*", "@del-trust?ee|@dt <object:>", 'del_trustee_cmd, #[[1, ['object_opt, []]]]]]], ["@monitor", [["@monitor", "*", "@monitor <any>", 'monitor_cmd, #[[1, ['any, []]]]]]], ["@ex?amine", [["@ex?amine", "*", "@ex?amine <object:+c?hop>", 'examine_cmd, #[[1, ['object_opt, ["c?hop"]]]]]]], ["@map", [["@map", "", "@map", 'map_cmd, #[]]]], ["@finger|@ustat", [["@finger|@ustat", "*", "@finger|@ustat <user>", 'finger_cmd, #[[1, ['user, []]]]]]], ["@trusts|@trustee?s", [["@trusts|@trustee?s", "*", "@trusts|@trustee?s <object>", 'trusts_cmd, #[[1, ['object, []]]]]]], ["@writers", [["@writers", "*", "@writers <object>", 'writers_cmd, #[[1, ['object, []]]]]]], ["@manager", [["@manager", "*", "@manager <object>", 'manager_cmd, #[[1, ['object, []]]]]]], ["@desc?ribe|@prose", [["@desc?ribe|@prose", "*", "@desc?ribe|@prose <any>", 'description_cmd, #[[1, ['any, []]]]]]], ["l?ook|exam?ine", [["l?ook|exam?ine", "*", "l?ook|exam?ine <any>", 'look_cmd, #[[1, ['any, []]]]]]], ["walk|go", [["walk|go", "*", "walk|go <any>", 'go_cmd, #[[1, ['any, []]]]]]], ["@ant|@add-name-template", [["@ant|@add-name-template", "*", "@ant|@add-name-template <any>", 'add_name_template_cmd, #[[1, ['any, []]]]]]], ["@dnt|@del-name-template", [["@dnt|@del-name-template", "*", "@dnt|@del-name-template <any>", 'del_name_template_cmd, #[[1, ['any, []]]]]]], ["@name-template?s|@template?s", [["@name-template?s|@template?s", "*", "@name-template?s|@template?s <object>", 'name_templates_cmd, #[[1, ['object, []]]]]]], ["@register|@register-name", [["@register|@register-name", "*", "@register|@register-name <any>", 'register_name_cmd, #[[1, ['any, []]]]]]], ["@unregister|@unregister-name", [["@unregister|@unregister-name", "*", "@unregister|@unregister-name <any>", 'unregister_name_cmd, #[[1, ['any, []]]]]]], ["@registered", [["@registered", "", "@registered", 'registered_cmd, #[]]]], ["@page", [["@page", "* with *", "@page <any> with <any>", 'remote_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@paste?-to", [["@paste?-to", "*", "@paste?-to <any>", 'paste_cmd, #[[1, ['any, []]]]]]], ["@new", [["@new", "*", "@new <any>", 'new_cmd, #[[1, ['any, []]]]]]], ["@status|@uptime", [["@status|@uptime", "*", "@status|@uptime <any>", 'status_cmd, #[[1, ['any, []]]]]]], ["@msg?s|@message?s", [["@msg?s|@message?s", "*", "@msg?s|@message?s <any>", 'msg_cmd, #[[1, ['any, []]]]]]], ["@date|@time", [["@date|@time", "*", "@date|@time <any>", 'date_cmd, #[[1, ['any, []]]]]]], ["@set", [["@set", "*", "@set <any>", 'set_cmd, #[[1, ['any, []]]]]]], ["PUEBLOCLIENT", [["PUEBLOCLIENT", "*", "PUEBLOCLIENT <any>", 'pueblo_cmd, #[[1, ['any, []]]]]]], ["@ways|@exits", [["@ways|@exits", "*", "@ways|@exits <any>", 'ways_cmd, #[[1, ['any, []]]]]]], ["@tut?orial", [["@tut?orial", "*", "@tut?orial <any>", 'tutorial_cmd, #[[1, ['any, []]]]]]], ["null", [["null", "*", "null <any>", 'null_cmd, #[[1, ['any, []]]]]]]]; new = #[["@quit", [["@quit", "", "@quit", 'quit_cmd, #[]]]], ["i?nventory", [["i?nventory", "", "i?nventory", 'inventory_cmd, #[]]]], ["@audit", [["@audit", "*", "@audit <any>", 'audit_cmd, #[[1, ['any, []]]]]]], ["@who", [["@who", "*", "@who <any>", 'who_cmd, #[[1, ['any, []]]]]]], ["@del-command-a?lias|@dca?lias", [["@del-command-a?lias|@dca?lias", "*", "@del-command-a?lias|@dca?lias <any>", 'del_command_alias_cmd, #[[1, ['any, []]]]]]], ["@command-a?liases|@ca?liases", [["@command-a?liases|@ca?liases", "*", "@command-a?liases|@ca?liases <any>", 'command_aliases_cmd, #[[1, ['any, []]]]]]], ["@add-command-a?lias|@aca?lias", [["@add-command-a?lias|@aca?lias", "*", "@add-command-a?lias|@aca?lias <any>", 'add_command_alias_cmd, #[[1, ['any, []]]]]]], ["@com?mands", [["@com?mands", "*", "@com?mands <any>", 'commands_cmd, #[[1, ['any, []]]]]]], ["@news", [["@news", "", "@news", 'news_cmd, #[]]]], ["@forget", [["@forget", "*", "@forget <any>", 'forget_cmd, #[[1, ['any, []]]]]]], ["@whereis|@where-is", [["@whereis|@where-is", "*", "@whereis|@where-is <any>", 'whereis_cmd, #[[1, ['any, []]]]]]], ["@password|@passwd", [["@password|@passwd", "*", "@password|@passwd <any>", 'password_cmd, #[[1, ['any, []]]]]]], ["@age", [["@age", "*", "@age <object>", 'age_cmd, #[[1, ['object, []]]]]]], ["@context", [["@context", "", "@context", 'context_cmd, #[]]]], ["@rename", [["@rename", "*", "@rename <any>", 'rename_cmd, #[[1, ['any, []]]]]]], ["@add-writer|@aw", [["@add-writer|@aw", "*", "@add-writer|@aw <any>", 'add_writer_cmd, #[[1, ['any, []]]]]]], ["@del-writer|@dw", [["@del-writer|@dw", "*", "@del-writer|@dw <any>", 'del_writer_cmd, #[[1, ['any, []]]]]]], ["@manage?d", [["@manage?d", "*", "@manage?d <any>", 'managed_cmd, #[[1, ['any, []]]]]]], ["@remember", [["@remember", "* as *", "@remember <object> as <any>", 'remember_cmd, #[[1, ['object, []]], [3, ['any, []]]]]]], ["@remembered", [["@remembered", "*", "@remembered <any>", 'remembered_cmd, #[[1, ['any, []]]]]]], ["discard", [["discard", "*", "discard <object>", 'discard_cmd, #[[1, ['object, []]]]]]], ["@writes", [["@writes", "*", "@writes <object>", 'writes_cmd, #[[1, ['object, []]]]]]], ["@trusted?-by", [["@trusted?-by", "*", "@trusted?-by <object>", 'trusted_by_cmd, #[[1, ['object, []]]]]]], ["@del-trust?ee|@dt", [["@del-trust?ee|@dt", "*", "@del-trust?ee|@dt <object:>", 'del_trustee_cmd, #[[1, ['object_opt, []]]]]]], ["@monitor", [["@monitor", "*", "@monitor <any>", 'monitor_cmd, #[[1, ['any, []]]]]]], ["@ex?amine", [["@ex?amine", "*", "@ex?amine <object:+c?hop>", 'examine_cmd, #[[1, ['object_opt, ["c?hop"]]]]]]], ["@map", [["@map", "", "@map", 'map_cmd, #[]]]], ["@finger|@ustat", [["@finger|@ustat", "*", "@finger|@ustat <user>", 'finger_cmd, #[[1, ['user, []]]]]]], ["@trusts|@trustee?s", [["@trusts|@trustee?s", "*", "@trusts|@trustee?s <object>", 'trusts_cmd, #[[1, ['object, []]]]]]], ["@writers", [["@writers", "*", "@writers <object>", 'writers_cmd, #[[1, ['object, []]]]]]], ["@manager", [["@manager", "*", "@manager <object>", 'manager_cmd, #[[1, ['object, []]]]]]], ["@desc?ribe|@prose", [["@desc?ribe|@prose", "*", "@desc?ribe|@prose <any>", 'description_cmd, #[[1, ['any, []]]]]]], ["l?ook|exam?ine", [["l?ook|exam?ine", "*", "l?ook|exam?ine <any>", 'look_cmd, #[[1, ['any, []]]]]]], ["walk|go", [["walk|go", "*", "walk|go <any>", 'go_cmd, #[[1, ['any, []]]]]]], ["@ant|@add-name-template", [["@ant|@add-name-template", "*", "@ant|@add-name-template <any>", 'add_name_template_cmd, #[[1, ['any, []]]]]]], ["@dnt|@del-name-template", [["@dnt|@del-name-template", "*", "@dnt|@del-name-template <any>", 'del_name_template_cmd, #[[1, ['any, []]]]]]], ["@name-template?s|@template?s", [["@name-template?s|@template?s", "*", "@name-template?s|@template?s <object>", 'name_templates_cmd, #[[1, ['object, []]]]]]], ["@register|@register-name", [["@register|@register-name", "*", "@register|@register-name <any>", 'register_name_cmd, #[[1, ['any, []]]]]]], ["@unregister|@unregister-name", [["@unregister|@unregister-name", "*", "@unregister|@unregister-name <any>", 'unregister_name_cmd, #[[1, ['any, []]]]]]], ["@registered", [["@registered", "", "@registered", 'registered_cmd, #[]]]], ["@page", [["@page", "* with *", "@page <any> with <any>", 'remote_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@paste?-to", [["@paste?-to", "*", "@paste?-to <any>", 'paste_cmd, #[[1, ['any, []]]]]]], ["@new", [["@new", "*", "@new <any>", 'new_cmd, #[[1, ['any, []]]]]]], ["@status|@uptime", [["@status|@uptime", "*", "@status|@uptime <any>", 'status_cmd, #[[1, ['any, []]]]]]], ["@msg?s|@message?s", [["@msg?s|@message?s", "*", "@msg?s|@message?s <any>", 'msg_cmd, #[[1, ['any, []]]]]]], ["@date|@time", [["@date|@time", "*", "@date|@time <any>", 'date_cmd, #[[1, ['any, []]]]]]], ["@set", [["@set", "*", "@set <any>", 'set_cmd, #[[1, ['any, []]]]]]], ["PUEBLOCLIENT", [["PUEBLOCLIENT", "*", "PUEBLOCLIENT <any>", 'pueblo_cmd, #[[1, ['any, []]]]]]], ["@ways|@exits", [["@ways|@exits", "*", "@ways|@exits <any>", 'ways_cmd, #[[1, ['any, []]]]]]], ["@tut?orial", [["@tut?orial", "*", "@tut?orial <any>", 'tutorial_cmd, #[[1, ['any, []]]]]]], ["null", [["null", "*", "null <any>", 'null_cmd, #[[1, ['any, []]]]]]], ["@away", [["@away", "*", "@away <any>", 'away_cmd, #[[1, ['any, []]]]]]], ["@back", [["@back", "", "@back", 'back_cmd, #[]]]], ["@add-trust?ee|@at", [["@add-trust?ee|@at", "*", "@add-trust?ee|@at <object:>", 'add_trustee_cmd, #[[1, ['object_opt, []]]]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$user<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $user; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); old method Deleting normal method $user.pose_cmd() object $user; eval { del_method('pose_cmd); }; old method Deleting normal method $user.tell_traceback() object $user; eval { del_method('tell_traceback); }; old method Deleting normal method $user.get_cmd() object $user; eval { del_method('get_cmd); }; old method Deleting normal method $user.test() object $user; eval { del_method('test); }; old method Deleting normal method $user.give_to_cmd() object $user; eval { del_method('give_to_cmd); }; old method Deleting normal method $user.get_from_cmd() object $user; eval { del_method('get_from_cmd); }; old method Deleting normal method $user.drop_cmd() object $user; eval { del_method('drop_cmd); }; new method Adding protected method $user.clear_away() protected method $user.clear_away() { arg name; clear_var('away); }; new method Replacing public method $user.msg_cmd() public method $user.msg_cmd() { arg cmdstr, cmd, args; var who, branch, name, msg, what, definer, opts, clear; (> .perms(caller(), 'command) <); // it niggles the string enough to 'clean' up little mistakes [args, opts] = (> $parse_lib.opt(args, "c?lear") <); args = join(args).trim(); clear = "c?lear" in (opts.slice(1)); if ((what = regexp(args, "^([^:=]+): *(.*)$"))) { who = (> .match_env_nice((what[1]).trim()) <); args = (what[2]).trim(); } else { who = this(); } if ((what = regexp(args, "^([^=]+)=(.*)$"))) { name = (what[1]).trim(); args = (what[2]).trim(); } else { name = args; args = ""; } if (!name) return ([("-- Messages on " + (who.namef('ref))) + ":"] + (.format_messages(who))) + ["---"]; [name, @branch] = split(name, " *\. *", "b"); if (!($code_lib.valid_message_id(name))) return ("Invalid Message name \"" + name) + "\""; msg = args.unquote(); catch any { [definer, name, branch] = who.parse_msg(name, branch); if (clear) who = who.clear_msg(name, branch); else who = who.set_msg(name, branch, definer, args); msg = (who.get_msg(name, definer))[branch]; if (branch == "general") return ["-- Message changed to:", (" " + name) + " = "].affix(msg.uncompile()); else return ["-- Message changed to:", (((" " + name) + ".") + branch) + " = "].affix(msg.uncompile()); } with { return (traceback()[1])[2]; } }; new method Replacing public method $user.did_move() public method $user.did_move() { arg @args; (> pass(@args) <); if (auto_look != 'no) .tell((.location()).get_description(#[['actor, this()], ['exclude, [this()]]])); }; new method Replacing protected method $user.look_cmd() protected method $user.look_cmd() { arg cmdstr, cmd, args; var m, obj, desc, flags, loc, prep, line, exam; (> .perms(caller(), 'command) <); // flags that are always the same flags = #[['actor, this()], ['actor_location, .location()], ['examine, match_begin(cmd, "e")], ['exclude, [this()]]]; // Because we do some non-environment things, we parse look ourselves. // some times I critically catch things and sometimes I let the catch // statement catch them, this is because of how I want the errors to look. catch any { if ((m = match_template(args, "in|on *"))) { obj = (> .match_environment(m[2]) <); flags = (flags.add('type, m[1])).add_elem('exclude, obj); return obj.get_description(flags); } else { if ((m = match_template(args, "at *"))) args = m[2]; if (!args) { obj = .location(); return obj.get_description(flags.add_elem('exclude, obj)); } else if ((m = match_template(args, "* in|on *"))) { prep = m[2]; catch any loc = (> .match_environment(m[3]) <); with return (traceback()[1])[2]; obj = (| loc.match_environment(m[1]) |); if (!obj) { return (> loc.get_detail(m[1]) <); } else if ((m = match_template(args, "det?ail *"))) { desc = (| loc.get_detail(m[2]) |); if (!desc) return strfmt("No detail %d %l %l.", m[2], prep, loc.name()); return desc; } else { return obj.get_description(flags.add_elem('exclude, obj)); } } else if ((m = match_template(args, "det?ail *"))) { return (> (.location()).get_detail(m[2]) <); } else { obj = (> .match_environment(args) <); return obj.get_description(flags.add_elem('exclude, obj)); } } } with { line = (traceback()[1])[2]; if (error() in [~ambig, ~nodetail]) return line; desc = (| (.location()).get_detail(args) |); if (!desc) return line; return desc; } }; new method Replacing protected method $user._who_is() protected method $user._who_is() { arg people, @args; var person, p, who, x; who = []; if (type(people) == 'string) people = ($string.explode_english_list(people, @args)) || []; for p in (people) { catch any { person = $user_db.search(p); } with { switch (error()) { case ~ambig: .tell(((("The name \"" + p) + "\" can match any of: ") + ($list.to_english(filter x in ($user_db.users()) where (x.match_begin(p))))) + "."); continue; default: // hack, look for robots.. catch any { person = ($robot.children()).match_object(p); } with { .tell(("I don't know who \"" + p) + "\" is."); continue; } } } who += [person]; } if (!who) return 0; return [who, ((who.length()) == 1) ? "User" : "Users"]; }; new method Adding protected method $user.set_away() protected method $user.set_away() { arg name, definer, value, @args; if (value) { away = value; away_time = time(); } else { clear_var('away); } }; new method Adding protected method $user.set_conn_options() protected method $user.set_conn_options() { arg conn, options; if (!(conn in connections)) throw(~invarg, (conn + " is not a connection for ") + this); connection_options = (| connection_options.add(conn, options) |) || #[[conn, options]]; }; new method Adding public method $user.back_cmd() public method $user.back_cmd() { arg cmdstr, cmd; (> .perms('command, caller()) <); if (away) { clear_var('away); return "You are no longer marked as being away."; } else { return "You are not marked as being away."; } }; new method Replacing protected method $user.go_cmd() protected method $user.go_cmd() { arg cmdstr, cmd, path; var m, route, loc; (> .perms(caller(), 'command) <); if ((m = match_template(path, "to *"))) { path = m[2]; if (!path) { .tell("Specify a destination."); return; } if (path == "home") loc = .home(); else loc = (| .match_environment(path) |); // if we have still not found a location... if (!loc) { catch any { loc = $place_db.search(path); } with { switch (error()) { case ~ambig: .tell("Several rooms match that name: " + ((((traceback()[1])[3]).mmap('namef)).to_english())); case ~namenf: .tell(("Unable to find place \"" + path) + "\"."); return; default: return (traceback()[1])[2]; } } } if (!loc) { .tell(("Unable to find place \"" + path) + "\"."); return; } if (loc == (.location())) { .tell("You are already there!"); return; } if (!(route = (| $place_lib.bfs(.location(), loc) |))) throw(~stop, ("I can't find a route to " + path) + "."); return .follow_path(@route); } path = path.explode_quoted(); catch any .walk_path(@path); with .tell((traceback()[1])[2]); if (auto_look != 'no) .tell((.location()).get_description(#[['actor, this()], ['exclude, [this()]]])); return "You arrive"; }; new method Adding public method $user.read_line2() public method $user.read_line2() { arg @args; var line, abort, head, con; if (!(.connections())) return 'not_connected; con = (| .task_connection() |) || ((.connections())[1]); if (con.is_reading_block()) throw(~engaged, "This connection is already reading input."); [(head ?= ""), (abort ?= 'yes)] = args; if (head) .tell(head); line = con.start_reading_block('one); if ((line == 'aborted) || ((abort != 'no) && ((| (line[1]).trim() |) == "@abort"))) { if (type(abort) == 'string) throw(~stop, abort); else throw(~stop, "** Aborted **"); } if ((| type(line[1]) |) != 'string) throw(~prompt, "Unexpected result from .prompt(): " + line); return line[1]; }; new method Replacing public method $user.set_cmd() public method $user.set_cmd() { arg cmdstr, cmd, args; var who, branch, name, setting, what, def, opts, clear, showdef; (> .perms(caller(), 'command) <); if ((what = regexp(args, "^ *\+(clear|c) +(.*)"))) { clear = 1; args = what[2]; } if ((what = regexp(args, "^ *\+(definers|definer|def|d) *= *\$?([a-z0-9_]+) *(.*)"))) { if (!(showdef = (| lookup(tosym(what[2])) |))) return "Invalid definer $" + (what[2]); args = what[3]; } if ((what = regexp(args, "^ *\+(def|definer|definers|d) *(.*)"))) { showdef = 1; args = what[2]; } if ((what = regexp(args, "^([^:=]+): *(.*)$"))) { who = (> .match_env_nice((what[1]).trim()) <); args = (what[2]).trim(); } else { who = this(); } if ((what = regexp(args, "^([\@a-z0-9-]+) *= *(.*)$"))) { name = (what[1]).trim(); args = (what[2]).trim(); } else { name = args; args = ""; } if (!name) return ([("-- Settings on " + (who.namef('ref))) + ":"] + (.format_settings(who, showdef))) + ["---"]; if (!($code_lib.valid_setting_id(name))) return ("Invalid Setting name \"" + name) + "\""; setting = args.unquote(); catch any { def = who.setting_definer(name); if (clear) who = who.clear_setting(name, def); else who = who.set_setting(name, def, setting); setting = who.format_setting(name, def, who.get_setting(name, def)); return ["-- Setting changed to:", ((" " + name) + " = ") + setting, "--"]; } with { if (error() == ~perm) return "You are not allowed to change settings on " + (who.namef('ref)); return (traceback()[1])[2]; } }; new method Replacing public method $user.remote_cmd() public method $user.remote_cmd() { arg cmdstr, com, who, prep, str; var target, line, fstr, wstr, type, bad, awaymsg; (> .perms(caller(), $user, $robot) <); if (str && ((str[1]) == ":")) { type = 'emote; str = str.subrange(2); } else { type = 'say; } who = (> .parse_interaction_reference(who, tostr(type), 'userdb) <); if ((bad = filter target in (who) where (type(target) != 'objnum))) return ("Unable to find " + (bad.to_english())) + "."; .add_interaction('objs, who); line = .name(); if (str && ((str[1]) == ":")) str = str.subrange(2); else line += " "; if (type == 'emote) { line += str; } else { if (str) line += $code_lib.punctuation_type(str); else line += "say"; line = ((line + "s, \"") + str) + "\""; } wstr = (who.mmap('name)).to_english(); fstr = "[from " + ((.location()).name()); if ((who.length()) > 1) fstr = (fstr + ", to ") + wstr; fstr = (fstr + "] ") + line; for target in (who) { if (!(target.connected())) .tell((target.name()) + " is not connected."); (| target.directed_tell(fstr, 'remote) |); } .tell((("[to " + wstr) + "] ") + line); if ((| (awaymsg = target.away()) |)) .tell((((target.name()).capitalize()) + " is away: ") + awaymsg); }; new method Adding public method $user.away_time() public method $user.away_time() { return away_time; }; new method Replacing public method $user.prompt() public method $user.prompt() { arg prompt, @abort; // second argument represents how to handle '@abort' as input, // if it is 'no, then '@abort' is treated as any other string. // If it is 'yes, then ~stop will be thrown if @abort is // encountered, with the message "** Aborted **". If it is a // string, then the behaviour is the same as with 'yes, but // that string is used instead of the default message. .non_terminated_tell(prompt); [(abort ?= 'yes)] = abort; return (> .read_line(0, abort) <); }; new method Replacing protected method $user.commands_cmd() protected method $user.commands_cmd() { arg cmdstr, cmd, args; var s, full, o, opt, lcmds, rcmds, len, obj, shorts, m, c, local, remote, short, all; (> .perms(caller(), 'command) <); s = cmd + " [options] <object>"; args = (> $parse_lib.opt(args, "f?ull", "a?ll", "l?ocal", "r?emote", "s?hortcuts") <); o = args[2]; local = (remote = (short = 1)); if ((opt = "f?ull" in (o.slice(1)))) full = (o[opt])[3]; if ((opt = "a?ll" in (o.slice(1)))) all = (o[opt])[3]; if ((opt = "r?emote" in (o.slice(1)))) remote = (o[opt])[3]; if ((opt = "s?hortcuts" in (o.slice(1)))) short = (o[opt])[3]; if ((opt = "l?ocal" in (o.slice(1)))) local = (o[opt])[3]; args = (args[1]).join(); if ((!args) && (!all)) { (| .tell_error(cmd + " <object> [options]") |); return "! Defaults: -f?ull -a?ll +l?ocal +r?emote +s?hortcuts"; } else { args = args || "me"; obj = (> .match_env_nice(args) <); } if (!(obj.has_ancestor($has_commands))) return "Sorry, that object has no commands."; lcmds = (rcmds = #[]); shorts = []; if (all) { if (local) lcmds = obj.all_local_commands(); if (remote) rcmds = obj.all_remote_commands(); if (short) shorts = obj.all_shortcuts(); } else { if (local) { c = obj.local_commands(); if (c) lcmds = #[[obj, c]]; } if (remote) { c = obj.remote_commands(); if (c) rcmds = #[[obj, c]]; } if (short) shorts = (obj.shortcuts()).to_list(); } if (full) { m = 'format_commands_long; len = ((.linelen()) / 3) * 2; } else { m = 'format_commands_short; len = .linelen(); } o = []; if (lcmds) o += $command_lib.(m)(lcmds, "Local", len); if (rcmds) o += $command_lib.(m)(rcmds, "Remote", len); if (shorts) { o += ["Shortcuts:"]; if (full) m = 'unparse_shortcut_full; else m = 'unparse_shortcut; for c in (shorts) o += [" " + $command_lib.(m)(c)]; } return o || ("No commands defined on " + (obj.namef('ref))); }; new method Replacing public method $user.logout() public method $user.logout() { arg connection; var p; (| (.location()).did_disconnect() |); (| .reset_parsers() |); (| .clear_help_history() |); (| $user_db.did_disconnect() |); // Track how long they are online (random info) -Lynx connected_seconds += time() - connected_at; // set this to -last_command so we know they aren't connected // (and using last command will be last_login) connected_at = -last_command_at; // user specific things if (!($guest in (.parents()))) { (| $housekeeper.did_disconnect() |); (| $user_db.last_log_disconnect(this()) |); } else { (| $user_db.last_log_disconnect($guest) |); } .cache_client_uninit(); $channel_ui._broadcast('Login, (((.namef('titled)) + " has disconnected (total: ") + ($user_db.total_connected())) + ")"); task_connections = #[]; .set_activity(""); (| clear_var('monitor) |); (| .new_list(this()) |); .unhook_events('startup); $world.unhook_from_event('realm_announce); (| clear_var('context) |); }; new method Replacing public method $user.read_line() public method $user.read_line() { arg @args; var line, abort, head, con; if (!(.connections())) return 'not_connected; con = (| .task_connection() |) || ((.connections())[1]); if (con.is_reading_block()) throw(~engaged, "This connection is already reading input."); [(head ?= ""), (abort ?= 'yes)] = args; if (head) .tell(head); line = con.start_reading_block('one); if ((line == 'aborted) || ((abort != 'no) && ((| (line[1]).trim() |) == "@abort"))) { if (type(abort) == 'string) throw(~stop, abort); else throw(~stop, "** Aborted **"); } if ((| type(line[1]) |) != 'string) throw(~prompt, "Unexpected result from .prompt(): " + line); return line[1]; }; new method Replacing protected method $user.add_trustee_cmd() protected method $user.add_trustee_cmd() { arg cmdstr, cmd, args; var syn, obj, trustee; (> .perms(caller(), 'command) <); trustee = args[1]; args = args[2]; if (args && ((args[1]) == "to")) args = delete(args, 1); args = join(args); if (!args) throw(~stop, ("Syntax: " + cmd) + " <trustee> to <object>"); obj = (> .match_env_nice(args) <); catch any { (> obj.add_trusted(trustee) <); return [(("Added trustee " + (trustee.namef('ref))) + " to ") + (obj.namef('ref)), (((obj.namef('ref)) + " now trusts: ") + ((((obj.trusted('literal)).compress()).mmap('namef, 'ref)).to_english("nobody"))) + "."]; } with { return (traceback()[1])[2]; } }; new method Adding protected method $user.get_away() protected method $user.get_away() { arg name, def; return away; }; new method Adding protected method $user.away() protected method $user.away() { return away; }; new method Replacing public method $user._edit_mail_callback() public method $user._edit_mail_callback() { arg text, cdata; var list, subj, err, mail, nosend, sent; // not necessarily safe perm checks (> .perms(caller(), $editor_session, $editor_reference) <); list = cdata[2]; subj = cdata[3]; if (!subj) subj = .prompt("Subject: "); mail = $mail_message.new_mail(); mail.set_subject(subj); mail.set_text(text); catch any nosend = mail.send(@list); with return ['failed, [(traceback()[1])[2]]]; if (nosend) { sent = list.set_difference(nosend); if (sent) err = ["Mail sent to " + (sent.map_to_english('mail_name))]; else err = []; nosend = list.set_difference(sent); err += ["Mail NOT sent to " + (nosend.map_to_english('mail_name))]; return ['failure, err]; } return ['success, ["Mail sent to " + (list.map_to_english('mail_name))]]; }; new method Adding protected method $user.conn_options() protected method $user.conn_options() { arg conn; return (| connection_options[conn] |) || []; }; new method Replacing protected method $user.examine_cmd() protected method $user.examine_cmd() { arg cmdstr, cmd, args; var obj, opts, i, chop, out, m, cmds, c, desc, notfrobby, frobhandler; (> .perms(caller(), $user) <); obj = args[1]; opts = args[3]; chop = .linelen(); if (type(obj) != 'frob) notfrobby = 1; if (notfrobby) c = obj.created_on(); if ((i = "ch?op" in (opts.slice(1))) && (!((opts[i])[3]))) chop = 0; out = ["Object (@rename): " + (obj.namef('ref)), "Templates (@ant): " + ((| (obj.name_templates()).to_english("none") |) || "none")]; if (notfrobby) out += ["Created: " + (c ? ctime(c) : "(Before Time)"), (("Quota: " + ((obj.quota()).to_english())) + " bytes") + ((obj.quota_exempt()) ? " ** exempt **" : "")]; out += [("Size: " + ((notfrobby ? (obj.size()) : size(obj)).to_english())) + " bytes (on disk)"]; if (notfrobby) out += ["Perms (@chmod): " + (((obj.flags()).prefix("+")).join())]; out += ["Manager (@chmanage): " + ($object_lib.get_name(obj.manager(), 'namef, ['ref])), ._exam_sub("Writer", 1, "@aw/@dw", chop, obj, 'writers, 'literal)]; if (notfrobby) out += [._exam_sub("Trusted", 0, "@at/@dt", chop, obj, 'trusted, 'literal), ._exam_sub("Parent", 1, "@ap/@dp", chop, obj, 'parents)]; if (!notfrobby) { out += ["Frob Class: " + frob_class(obj)]; if ((frobhandler = (| frob_handler(obj) |))) out += ["Frob Handler: " + frobhandler]; } if (obj.has_ancestor($located)) out += ["Location (@move): " + ($object_lib.get_name(obj.location(), 'namef, ['xref]))]; if ((desc = (| obj.prose() |))) out += ["Description:", "@describe " + ((type(obj) == 'frob) ? (obj.name()) : obj), @(type(desc) == 'frob) ? (desc.uncompile()) : ((type(desc) == 'list) ? desc : [desc]), "."]; if ((cmds = (| obj.remote_commands() |))) out += $command_lib.format_commands_short(#[[obj, cmds]], "Remote", .linelen()); if ((cmds = (| obj.local_commands() |))) out += $command_lib.format_commands_short(#[[obj, cmds]], "Local", .linelen()); return out + ((| obj.examine() |) || []); }; new method Replacing protected method $user._who_short() protected method $user._who_short() { arg people, title, @rest; var user, tmp, who, namestr, total; who = []; total = people.length(); .tell((((title + " (total: ") + tostr(total)) + ((total == 1) ? " person" : " people")) + "):"); for user in (people) { namestr = (((((" " + (user.name())) + " (") + ($time.elapsed(user.connected_at()))) + " ") + ($time.dhms(user.idle_seconds()))) + ")"; who += [namestr]; if (tmp < ((namestr.length()) + 2)) tmp = (namestr.length()) + 2; } .tell($list.vcolumnize(who, (.linelen()) / (tmp + 1), .linelen())); }; new method Replacing public method $user.who_cmd() public method $user.who_cmd() { arg cmdstr, com, args; var who, title, rest, opts, opt, a, all, prog, admin, short, sort, sortorder, s, x, place, results, sortopts, sortmeths; (> .perms(caller(), 'command) <); // just the basic who listing args = ((.get_setting("@who-options", $user)) + " ") + args; [args, opts] = (> $parse_lib.opt(args, "a?ll", "p?rogrammers", "a?dmins", "s?hort", "so?rt") <); for opt in (opts) { switch (opt[1]) { case "a?ll": all = opt[3]; case "p?rogrammers": prog = opt[3]; case "a?dmins": admin = opt[3]; case "s?hort": short = opt[3]; case "so?rt": sort = opt[4]; sortorder = opt[3]; } } args = (args.join()).explode_english_list(); results = []; if (admin && (admin = ._who_admins([], all))) results += [admin]; if (prog && (prog = ._who_programmers([], all))) results += [prog]; if ((!prog) && ((!admin) && (!args))) { results += [[$user_db.connected(), "Connected Users"]]; } else { for a in (args) { if ((a[1]) == "@") { if ((place = ._who_at_place(a.subrange(2)))) results += [place]; args = args.setremove(a); } } if (args && (args = ._who_is(args))) results += [args]; } who = []; for x in (results) who = who.union(x[1]); title = (results.slice(2)).to_english(); rest = ((results.length()) == 1) ? ((results[1]).subrange(3)) : []; if (!who) return "Ack, nobody to list?"; if (sort) { sortopts = ["idle", "connected", "name", "location", "place"]; sortmeths = ['idle_seconds, 'connected_at, 'name, 'location, 'location]; s = filter x in (sortopts) where (match_begin(x, sort)); if ((s.length()) != 1) { .ptell("Unrecognized sort option: " + sort, #[['type, 'command]]); sort = 0; } else { sort = sortmeths[(s[1]) in sortopts]; } } if (sort) { sort = who.mmap(sort); if (type(sort[1]) == 'objnum) sort = sort.mmap('name); who = who.sort(sort); if (!sortorder) who = who.reverse(); } if (short) return ._who_short(who, title, @rest); else .ptell($code_lib.generate_listing(who, title, @rest), #[['type, 'command]]); }; new method Replacing public method $user.parse_line() public method $user.parse_line() { arg line; var parse, c, r, rval; (> .perms(caller(), $connection) <); set_user(); // if we dont set it, it'll act like normal rval = this(); last_command_at = time(); .set_last_command(line.trim()); catch any { task_connections = task_connections.add(task_id(), sender()); parse = parsers ? ((parsers[1]).parse(this(), line, @parsers.subrange(2), $null_parser)) : ['failed]; switch (parse[1]) { case 'action: r = (| (parse[2]).action(@parse[3]) |); if (type(r) in ['list, 'frob, 'string]) .ptell(r, #[['type, 'parser], ['action, parse[3]]]); else .tell(("Invalid registered action '" + (parse[3])) + "'"); case 'error: .tell(parse[2]); case 'match, 'command: r = (> (parse[2]).(parse[3])(@parse.subrange(4)) <); if (type(r) in ['list, 'frob, 'string]) .ptell(r, #[['type, 'parser], ['command, parse[3]]]); else rval = r; case 'failed: for c in (($place_lib.coordinate_shortcuts()).keys()) { if (line.match_template(c)) { .tell(("There is no exit " + line) + " here."); r = 1; } } if (!r) .tell(("I don't understand " + (line.chop((.linelen()) - 22))) + "."); case 'ok: // do nothing, probably a null command default: .tell("Unusual response from the parser: " + toliteral(parse)); } } with { if (error() == ~stop) { if ((traceback()[1])[2]) .tell((traceback()[1])[2]); } else { .tell_traceback(traceback(), @parse); } } catch any task_connections = task_connections.del(task_id()); return rval; }; new method Adding public method $user.away_cmd() public method $user.away_cmd() { arg cmdstr, cmd, msg; (> .perms('command, caller()) <); if (msg) { away = msg; away_time = time(); return "You are now marked as being away."; } else if (away) { return "You are marked as being away. Message: " + away; } else { return "You are not marked as being away."; } }; method access Changing method $user.set_title() access from root to protected object $user; eval { var l; dblog("set_method_access('set_title, 'protected"); catch any { set_method_access('set_title, 'protected); } with { for l in ($parse_lib.traceback(traceback())) dblog(l); } }; new method Replacing public method $user.activity() public method $user.activity() { arg @noidle; var idle, r; // different from action, returns a broader version of your doings if (!(.connected())) return "asleep"; if (activity) return activity; if (!noidle) { idle = .idle_seconds(); if (idle >= 180) { if (idle < 300) r = "daydreaming"; if (idle < 900) r = "zoned"; else r = "long gone"; } if (away) return ((((r ? (r + ", ") : "") + "away for ") + ($time.dhms(time() - away_time, 1))) + ": ") + away; } return r; }; new method Replacing protected method $user.finger_cmd() protected method $user.finger_cmd() { arg cmdstr, cmd, who; var out, awaymsg; (> .perms(caller(), 'command) <); out = ([("Information on " + (who.name())) + " (use @set to change):"] + ((who.display_info('no_blanks)).prefix(" "))) + ((.age_cmd("", "", who)).prefix(" ")); if (who.connected()) { if ((| (awaymsg = who.away()) |)) return out + [((((" " + (who.name())) + " has been away for ") + ($time.dhms(time() - (who.away_time()), 1))) + ": ") + awaymsg]; return out + [(" " + (who.name())) + " is currently connected."]; } else { return out + [((((" " + (who.name())) + " was last connected at ") + ($time.format("%r", abs(who.connected_at())))) + " ") + ($time.format("%A %B %d %Y", abs(who.connected_at())))]; } }; new method Adding protected method $user.follow_path() protected method $user.follow_path() { arg @path; var e, oal; if (!path) throw(~badpath, "Walk nowhere?"); oal = .get_auto_look(); .set_auto_look($user, "", 0); catch any { for e in (path) { e.invoke(); pause(); } .set_auto_look(0, 0, oal); } with { .set_auto_look(0, 0, oal); rethrow(error()); } }; new method Replacing protected method $user.password_cmd(): nooverride protected method $user.password_cmd(): nooverride { arg cmdstr, com, args; var syn, c, curr, new, verify; (> .perms(caller(), 'command) <); syn = com + " [<old password> [<new password>]]"; args = explode(args); c = .task_connection(); if (!args) { while (!curr) curr = (.prompt("Current Password (@abort to abort): ")).trim(); } else { curr = args[1]; } if (!(.check_password(curr))) return "Invalid Password"; if (listlen(args) < 2) { while (1) { while (!new) new = (.prompt("New Password (@abort to abort): ")).trim(); while (!verify) verify = (.prompt("Retype New Password (@abort to abort): ")).trim(); if (new == verify) break; .tell("Passwords do not match!"); new = (verify = 0); } } else if (listlen(args) == 2) { new = args[2]; } else { .tell_error(syn); } catch any .set_password(new); with .tell_error(syn, (traceback()[1])[2]); .tell("Password changed."); }; new method Replacing protected method $user.audit_cmd() protected method $user.audit_cmd() { arg cmdstr, cmd, args; var who, obj, col, str, out, total, line, syntax, loc, size, full, s, o; (> .perms(caller(), 'command) <); o = (> $parse_lib.opt(args, "f?ull") <); args = (o[1]).join(); full = (| "f?ull" in ((o[2]).slice(1)) |); if (full) full = ((o[2])[full])[3]; who = (| .match_environment(args) |); if (!who) { who = (| $user_db.search(args) |); if (!who) return ("Unable to find \"" + args) + "\"."; } if (!(who.managed())) return (who.name()) + " does not managed anything."; if (full) { col = (.linelen()) / 2; out = [(((("Objects managed by " + (who.namef('ref))) + ":").pad(col)) + ("bytes".pad(-10))) + " Location"]; for obj in (who.managed()) { if (!valid(obj)) { .tell((" ** invalid object (" + toliteral(obj)) + ") **"); continue; } line = (" " + (obj.namef('xref))).pad(col); s = obj.size(); size = s.to_english(); line = (line + (size.pad(-(((size.length()) > 10) ? (size.length()) : 10)))) + " "; loc = (obj.has_ancestor($located)) ? (("[" + ((obj.location()).name())) + "]") : ""; out += [(line + loc).pad(.linelen())]; total += s; } } else { if ((who != this()) && (!(.is($admin)))) return "Only admins can get quota usage information from other users."; out = [("Quota information on " + (who.namef('ref))) + ":"]; for obj in (who.managed()) { if (valid(obj)) total += obj.size(); } } if ((who == this()) || (.is($admin))) { out += [("Total usage: " + ($integer.to_english(total))) + " bytes"]; size = who.get_quota(); line = ("Total quota: " + ($integer.to_english(size))) + " bytes"; out += [line, ("Remaining: " + ($integer.to_english(size - total))) + " bytes"]; } if (!(who.quota_valid())) { if (who == this()) out += ["*** You are over quota! ***"]; else out += [("*** " + (who.name())) + " is over quota! ***"]; } return out; }; new method Adding public method $user.prompt2() public method $user.prompt2() { arg prompt, @abort; // second argument represents how to handle '@abort' as input, // if it is 'no, then '@abort' is treated as any other string. // If it is 'yes, then ~stop will be thrown if @abort is // encountered, with the message "** Aborted **". If it is a // string, then the behaviour is the same as with 'yes, but // that string is used instead of the default message. .non_terminated_tell(prompt); [(abort ?= 'yes)] = abort; return (> .read_line2(0, abort) <); }; new method Replacing public method $user.connection_going_away() public method $user.connection_going_away() { arg addr, port; var con, line, opt; catch any { (> .perms(caller(), $connection) <); for con in (connections) { if (!valid(con)) connections = connections.setremove(con); } con = sender() in connections; connections = connections.setremove(sender()); catch any { for opt in (connection_options) { if (!((opt[1]) in connections)) connection_options = connection_options.del(opt[1]); } } if (!connections) .logout(sender()); else .logout_connection(sender()); line = ((((((("DISCONNECT " + tostr(con)) + " (") + ((.parents())[1])) + "): ") + this()) + " <") + addr) + ">"; (| $sys.log(line) |); } with { $sys.log($parse_lib.traceback(traceback())); } }; update objvar Updating objvar $guest<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[]; new = #[["@request", [["@request", "*", "@request <any>", 'request_cmd, #[[1, ['any, []]]]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$guest<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $guest; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); new method Replacing root method $guest.init_guest() root method $guest.init_guest() { .set_title(0, 0, "a guest"); }; new method Adding public method $guest.request_cmd() public method $guest.request_cmd() { arg @args; var msg, ans, utypes, line, mail; (> .perms(caller(), 'command) <); // hardcoded questions for now--should eventually drop this in a // configurable 'schema' dict somewhere --Brandon .tell(["", "*" * (.linelen())]); .tell([">> This is the new-user request system. You will be asked a few questions", ">> at this time. Please answer to the best of your ability."]); .tell(["*" * (.linelen()), ""]); msg = [("Email:".pad(22)) + (.user_info("email"))]; line = "Read Tutorial:".pad(22); ans = .prompt(">> Have you read the Introductory Tutorial? [no] "); if ((!ans) || ((ans.is_boolean()) < 1)) { line += "no"; .tell(["", ">> We suggest you take some time afterwards and enter the Introductory", ">> Tutorial. To do so, just type: @tutorial", ""]); } else { .tell(""); line += "yes"; } msg += [line]; line = "Heard about us from: ".pad(22); ans = ""; while (ans == "") { ans = .prompt((">> Where did you hear about " + ($motd.server_name())) + "? "); ans = strsed(ans, "^ +", ""); } msg += (line + ans).wrap_lines(.linelen(), " " * 22); .tell(""); line = "Interest is with: ".pad(22); ans = ""; while (ans == "") { ans = .prompt(">> What is your reason for requesting a user? "); ans = strsed(ans, "^ +", ""); } msg += (line + ans).wrap_lines(.linelen(), " " * 22); line = "User type: ".pad(22); ans = ""; .tell(""); utypes = ["User", "Builder", "Programmer"]; while (!(ans in utypes)) { ans = .prompt(([">> Available user types:"] + (utypes.prefix(">> "))) + [">> Which of the above user types are you most interested in:"]); ans = ans.strip(); } msg += [line + ans]; .tell(""); if (ans == "Programmer") { ans = .prompt([">> By asking for Programmer permissions, do you agree never to exploit", ">> any problem or security hole which may be found by your or yourself,", ">> and to reveal any problems to the appropriate administration as soon", ">> as possible? [yes] "]); line = "Will not exploit:".pad(22); if ((ans.is_boolean()) != 0) msg += [line + "yes"]; else msg += [line + "no"]; } mail = $mail_message.new_mail(); mail.set_subject("New User Request for: " + (.name())); mail.set_text(msg); catch any mail.send($mail_admin); with return (traceback()[1])[2]; return ["New User Request Sent as:"] + msg; }; add objvar Adding objvar $no_one<$root>,quota_exempt object $no_one; var $root quota_exempt = 1; add objvar Adding objvar $no_one<$root>,trusted object $no_one; var $root trusted = [$smtp_interface]; new method Adding frob method $no_one.mail_name() frob method $no_one.mail_name() { arg frob; return frob[1]; }; new method Adding public method $no_one.mail_as() public method $no_one.mail_as() { arg from, meta, subj, body, @recips; var mail, l; if (!(.trusts(caller()))) (> .perms(sender()) <); mail = $mail_message.new_mail(); mail.set_subject(subj); mail.set_text(body); if (from) mail.set_from((<this(), [from]>)); if (meta) mail.set_meta(meta); if (caller() == $smtp_interface) mail.is_frominet(); catch any { mail.send(@recips); } with { // dont call .log_traceback because it calls this, recursion bad $sys.log((this() + " traceback: ") + ((traceback()[1])[2])); $sys.log((this() + " traceback: ") + traceback()); } }; new method Adding frob method $no_one.name() frob method $no_one.name() { arg frob, @args; return frob[1]; }; clear objvar Clearing objvar $player<$command_cache>,commands object $player; old var $command_cache commands; clear objvar Clearing objvar $player<$command_cache>,shortcuts object $player; old var $command_cache shortcuts; add objvar Adding objvar $player<$player>,chargen_origin object $player; var $player chargen_origin = 0; update objvar Updating objvar $player<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["@sheet|@score", [["@sheet|@score", "*", "@sheet|@score <any>", 'sheet_cmd, #[[1, ['any, []]]]]]], ["@new-char?acter", [["@new-char?acter", "*", "@new-char?acter <any>", 'new_character_cmd, #[[1, ['any, []]]]]]]]; new = #[["@sheet|@score", [["@sheet|@score", "*", "@sheet|@score <any>", 'sheet_cmd, #[[1, ['any, []]]]]]], ["@new-char?acter", [["@new-char?acter", "*", "@new-char?acter <any>", 'new_character_cmd, #[[1, ['any, []]]]]]], ["@char?acters", [["@char?acters", "*", "@char?acters <any>", 'characters_cmd, #[[1, ['any, []]]]]]], ["@del-char?acter", [["@del-char?acter", "*", "@del-char?acter <any>", 'del_character_cmd, #[[1, ['any, []]]]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$player<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $player; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); new method Adding public method $player.raise_charcmd() public method $player.raise_charcmd() { arg @args; var attr, amt, syn, msg; syn = ["Syntax: raise <attribute> <amount>", " OR: +<amount> <attribute>", " OR: +<attribute>"]; if (listlen(args) == 1) { if ((args[1]).is_numeric()) return syn; attr = args[1]; amt = 1; } else if (listlen(args) == 2) { [attr, amt] = args; } else { return syn; } amt = toint(amt); attr = (| attr.to_symbol() |); if (!(attr in ($character.attributes()))) return "Invalid Attribute: " + attr; if (type((amt = character.ok_to_raise_initial(attr, amt))) == 'string) return amt; character.set_attribute(attr, amt); return (("Set " + uppercase(tostr(attr))) + " to ") + amt; }; new method Adding public method $player.lower_charcmd() public method $player.lower_charcmd() { arg @args; var attr, amt, syn, msg; syn = ["Syntax: lower <attribute> <amount>", " OR: -<amount> <attribute>", " OR: -<attribute>"]; if (listlen(args) == 1) { if ((args[1]).is_numeric()) return syn; attr = args[1]; amt = 1; } else if (listlen(args) == 2) { [attr, amt] = args; } else { return syn; } amt = toint(amt); attr = (| attr.to_symbol() |); if (!(attr in ($character.attributes()))) return "Invalid Attribute: " + attr; if (type((amt = character.ok_to_lower_initial(attr, amt))) == 'string) return amt; character.set_attribute(attr, amt); return (("Set " + uppercase(tostr(attr))) + " to ") + amt; }; new method Adding public method $player.character() public method $player.character() { return character; }; new method Replacing public method $player.help_charcmd() public method $player.help_charcmd() { arg @args; .tell("** Special commands: HELP, LOWER, RAISE, SHEET, DONE and ABORT"); .tell("** As well as +X and -X as shortcuts for raise and lower"); .tell("** All other normal commands are available"); }; new method Adding public method $player.abort_charcmd() public method $player.abort_charcmd() { arg @args; .tell("** Aborting Character Generation, cleaning up..."); catch any character.destroy(); with .tell(["** Unable to destroy character sheet:", (traceback()[1])[1]]); clear_var('character); .del_parser($chargen_parser); if (chargen_origin) .move_to(chargen_origin); else .move_to($world.starting_place()); (| clear_var('chargen_origin) |); }; new method Adding public method $player.characters() public method $player.characters() { return characters; }; new method Adding public method $player.sheet_charcmd() public method $player.sheet_charcmd() { arg @args; var tot, group, line, x, out; tot = map x in ($character.attributes()) to ((character.attribute(x))[1]); tot = tot.sum(); out = ["", ((("Attribute Points Remaining: " + (115 - tot)) + " (") + tot) + " of 115)"]; tot = map x in ($character.physical_attributes()) to ((character.attribute(x))[1]); tot = tot.sum(); out += [(((" Physical: " + (56 - tot)) + " (") + tot) + ", cap 56)"]; tot = map x in ($character.mental_attributes()) to ((character.attribute(x))[1]); tot = tot.sum(); out += [(((" Mental: " + (56 - tot)) + " (") + tot) + ", cap 56)"]; tot = map x in ($character.meta_attributes()) to ((character.attribute(x))[1]); tot = tot.sum(); out += [(((" Meta-Phys: " + (30 - tot)) + " (") + tot) + ", cap 30)"]; return (character.format_sheet()) + out; }; new method Adding public method $player.characters_cmd() public method $player.characters_cmd() { arg @args; var out, c, x, line; (> .perms(caller(), 'command) <); out = []; for x in [1 .. listlen(characters)] { c = characters[x]; line = (c == character) ? "*" : " "; out += [strfmt("%2r: %s ", x, line) + (c.namef('ref))]; } if (!out) out = [" <None>"]; return (["Characters:"] + out) + ["---"]; }; new method Adding public method $player.done_charcmd() public method $player.done_charcmd() { arg @args; .tell("** Done Generating, cleaning up..."); characters += [character]; clear_var('character); .del_parser($chargen_parser); if (chargen_origin) .move_to(chargen_origin); else .move_to($world.starting_place()); (| clear_var('chargen_origin) |); }; new method Adding public method $player.del_character_cmd() public method $player.del_character_cmd() { arg cmdstr, cmd, str; var delchar, x, yesno, name; (> .perms(caller(), 'command) <); catch any { delchar = characters.match_object(str); } with { if ((x = str.is_numeric()) && (delchar = (| characters[x] |))) { // Good } else { return [("Syntax: " + cmd) + " <character>", (" OR: " + cmd) + " <character index>"]; } } name = delchar.namef('ref); yesno = (.prompt(("Delete " + name) + "? [no] ")).is_boolean(); if (yesno <= 0) return "Ok, Aborting..."; catch any delchar.destroy(); with return [("** Unable to destroy character " + name) + ":", (traceback()[1])[1]]; characters = setremove(characters, delchar); return ((("Deleted " + name) + ", ") + listlen(characters)) + " characters remaining."; }; new method Replacing public method $player.new_character_cmd() public method $player.new_character_cmd() { arg @args; (> .perms(caller(), 'command) <); if (character) return ("You already have a character active (" + character) + ")"; catch any character = $character.new(); with return ["Unable to enter character creation:", (traceback()[1])[2]]; characters ?= []; (.location()).announce((.name()) + " fades away to generate a new character.", this()); chargen_origin = .location(); .move_to($nowhere); .add_parser($chargen_parser); .tell("** Raw character generation subsystem, will get better later"); .tell("** Based off En Requiem: http://web.roguetrader.com/EnRequime/rules"); .tell("** type 'help' for help"); }; update objvar Updating objvar $builder<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["@realm?s", [["@realm?s", "", "@realm?s", 'realms_cmd, #[]]]], ["@mv|@move", [["@mv|@move", "*", "@mv|@move <object:>", 'move_cmd, #[[1, ['object_opt, []]]]]]], ["@child?ren|@kids", [["@child?ren|@kids", "*", "@child?ren|@kids <object>", 'children_cmd, #[[1, ['object, []]]]]]], ["@par?ents", [["@par?ents", "*", "@par?ents <object>", 'parents_cmd, #[[1, ['object, []]]]]]], ["@build", [["@build", "*", "@build <any:-conf?igure>", 'build_cmd, #[[1, ['any_opt, ["conf?igure"]]]]]]], ["@attach", [["@attach", "* to *", "@attach <any> to <descendant of $place>", 'attach_cmd, #[[1, ['any, []]], [3, ['descendant, [$place]]]]]]], ["@destroy", [["@destroy", "*", "@destroy <list object>", 'destroy_cmd, #[[1, ['list, ['object, []]]]]]]], ["@dig", [["@dig", "*", "@dig <any>", 'dig_cmd, #[[1, ['any, []]]]]]], ["@teleport|@go", [["@teleport|@go", "*", "@teleport|@go <any>", 'teleport_cmd, #[[1, ['any, []]]]]]], ["@def-msg|@def-message", [["@def-msg|@def-message", "*", "@def-msg|@def-message <any>", 'define_msg_cmd, #[[1, ['any, []]]]]]], ["@undef-msg|@undef-message", [["@undef-msg|@undef-message", "*", "@undef-msg|@undef-message <any>", 'undefine_msg_cmd, #[[1, ['any, []]]]]]]]; new = #[["@realm?s", [["@realm?s", "", "@realm?s", 'realms_cmd, #[]]]], ["@mv|@move", [["@mv|@move", "*", "@mv|@move <object:>", 'move_cmd, #[[1, ['object_opt, []]]]]]], ["@child?ren|@kids", [["@child?ren|@kids", "*", "@child?ren|@kids <object>", 'children_cmd, #[[1, ['object, []]]]]]], ["@par?ents", [["@par?ents", "*", "@par?ents <object>", 'parents_cmd, #[[1, ['object, []]]]]]], ["@build", [["@build", "*", "@build <any:-conf?igure>", 'build_cmd, #[[1, ['any_opt, ["conf?igure"]]]]]]], ["@attach", [["@attach", "* to *", "@attach <any> to <descendant of $place>", 'attach_cmd, #[[1, ['any, []]], [3, ['descendant, [$place]]]]]]], ["@destroy", [["@destroy", "*", "@destroy <list object>", 'destroy_cmd, #[[1, ['list, ['object, []]]]]]]], ["@dig", [["@dig", "*", "@dig <any>", 'dig_cmd, #[[1, ['any, []]]]]]], ["@teleport|@go", [["@teleport|@go", "*", "@teleport|@go <any>", 'teleport_cmd, #[[1, ['any, []]]]]]], ["@def-msg|@def-message", [["@def-msg|@def-message", "*", "@def-msg|@def-message <any>", 'define_msg_cmd, #[[1, ['any, []]]]]]], ["@undef-msg|@undef-message", [["@undef-msg|@undef-message", "*", "@undef-msg|@undef-message <any>", 'undefine_msg_cmd, #[[1, ['any, []]]]]]], ["@prob?lems|@pr|@bug?s", [["@prob?lems|@pr|@bug?s", "*", "@prob?lems|@pr|@bug?s <any>", 'problems_cmd, #[[1, ['any, []]]]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$builder<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $builder; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); old method Deleting normal method $builder._interactive_bug_cmd() object $builder; eval { del_method('_interactive_bug_cmd); }; old method Deleting normal method $builder._passive_bug__view() object $builder; eval { del_method('_passive_bug__view); }; old method Deleting normal method $builder._passive_bug__list() object $builder; eval { del_method('_passive_bug__list); }; old method Deleting normal method $builder._passive_bug_cmd() object $builder; eval { del_method('_passive_bug_cmd); }; old method Deleting normal method $builder.scan_bugs() object $builder; eval { del_method('scan_bugs); }; old method Deleting normal method $builder._passive_bug__fix() object $builder; eval { del_method('_passive_bug__fix); }; old method Deleting normal method $builder._passive_bug__add() object $builder; eval { del_method('_passive_bug__add); }; old method Deleting normal method $builder.bug_fixed() object $builder; eval { del_method('bug_fixed); }; new method Replacing public method $builder.format_messages() public method $builder.format_messages() { arg target, @what; var messages, out, b, branches, m; catch ~methodnf messages = target.all_msgs(); with return [("[" + (target.name())) + " does not have settable messages]"]; out = []; for m in ((messages.keys()).sort()) { branches = messages[m]; if (branches.contains("general")) { out += [(" " + m) + " = "].affix((branches["general"]).uncompile()); branches = dict_del(branches, "general"); } for b in ((branches.keys()).sort()) out += [(((" " + m) + ".") + b) + " = "].affix((branches[b]).uncompile()); } return out; }; new method Replacing protected method $builder.define_msg_cmd() protected method $builder.define_msg_cmd() { arg cmdstr, cmd, args; var what, opts, def, o, i, br, ref, compiler, eval, getter; (> .perms(caller(), 'command) <); [args, opts] = (> $parse_lib.opt(args, "b?ranches", "c?ompiler", "e?valuator", "g?etter") <); args = join(args); what = split(args, " *: *"); if (listlen(what) != 2) return "Invalid message reference " + args; [def, what] = what; what = what.trim(); if (match_regexp(what, "[=.]")) return ("You cannot set the default with " + cmd) + "."; def = (> .match_env_nice(def) <); if (!(def.is_writable_by(this()))) return ("You cannot define messages on " + (def.namef('ref))) + "."; if (type(def) == 'frob) return "You cannot define messages on a frob."; catch any { (> def.define_msg(what) <); ref = (def + ":") + what; .tell(("Message " + ref) + " defined."); } with { return (traceback()[1])[2]; } o = opts.slice(1); if ((i = "b?ranches" in o)) { br = (((opts[i])[4]).trim()).split(" *, *"); catch any { def.set_msg_attr(what, 'branches, br); .tell("Message branches defined:"); for i in (br) .tell(((" " + ref) + ".") + i); } with { .tell((traceback()[1])[2]); } } if ((i = "e?valuator" in o)) { eval = (opts[i])[4]; if (!eval) { .tell("No evaluator specified with +evaluator=??"); } else { eval = (> .match_env_nice(eval) <); if (!(eval.is($evaluator))) return "Invalid evaluator object: " + evaluator; catch any { def.set_msg_attr(what, 'evaluator, eval); .tell((("Set evaluator for " + ref) + " to ") + eval); } with { .tell((traceback()[1])[2]); } } } if ((i = "c?ompiler" in o)) { compiler = (opts[i])[4]; if (!compiler) { .tell("No compiler specified with +compiler=??"); } else { compiler = (> .match_env_nice(compiler) <); if (!(compiler.is($compiler))) .tell("Invalid compiler object: " + compiler); catch any { def.set_msg_attr(what, 'compiler, compiler); .tell((("Set compiler for " + ref) + " to ") + compiler); } with { .tell((traceback()[1])[2]); } } } if ((i = "g?etter" in o)) { getter = (opts[i])[4]; if (!getter) { .tell("No getter specified with +getter=??"); } else { getter = (> tosym(getter) <); catch any { def.set_msg_attr(what, 'getter, getter); .tell((("Set getter for " + ref) + " to ") + getter); } with { .tell((traceback()[1])[2]); } } } }; new method Replacing protected method $builder.undefine_msg_cmd() protected method $builder.undefine_msg_cmd() { arg cmdstr, cmd, args; var what, opts, def; (> .perms(caller(), 'command) <); // it niggles the string enough to 'clean' up little mistakes [args, opts] = (> $parse_lib.opt(args, "b?ranches", "c?ompiler") <); args = join(args); what = split(args, " *: *"); if (listlen(what) != 2) return "Invalid message reference " + args; [def, what] = what; what = what.trim(); def = (> .match_env_nice(def) <); if (!(def.is_writable_by(this()))) return ("You cannot define messages on " + (def.namef('ref))) + "."; catch any { (> def.undefine_msg(what) <); .tell(((("Message " + def) + ":") + what) + " undefined."); } with { return (traceback()[1])[2]; } }; new method Adding protected method $builder._problem__fix() protected method $builder._problem__fix() { arg args, opts, report; var line, cmt, n; n = (report.group()).name(); if (report.resolved_on()) return (((n + " Problem Report #") + (report.id())) + " has already been resolved by ") + ((report.resolved_by()).namef('ref)); .tell(report.format_full()); line = .prompt(("Mark " + n) + " Problem Report as resolved? [yes] "); if ((line.is_boolean()) == 0) return "** Aborting."; .tell("** Enter any final remarks, or nothing for no remarks."); cmt = .read("** Enter \".\" to finish or \"@abort\" to abort."); if (type(cmt) != 'list) return; report.resolve(); .tell(("** " + n) + " Problem Report has been marked as resolved."); if (cmt) report.add_comment(cmt); return ._problem__mailmsg(report, cmt); }; new method Adding protected method $builder._problem__dismiss() protected method $builder._problem__dismiss() { arg args, opts, report; var line, cmt, n, id; n = (report.group()).name(); n = report.id(); if ((report.group()) == $dismissed_problems) return ((n + " Problem Report #") + id) + " has already been dismissed"; .tell(report.format_full()); line = .prompt(((("Dismiss " + n) + " Problem Report #") + id) + "? [yes] "); if ((line.is_boolean()) == 0) return "** Aborting."; .tell("** Enter any remarks, or nothing for no remarks."); cmt = .read("** Enter \".\" to finish or \"@abort\" to abort."); if (type(cmt) != 'list) return; if (cmt) report.add_comment(cmt); report.change_group($dismissed_problems); return ("** " + n) + " Problem Report has been marked as resolved."; }; new method Adding protected method $builder._problem__interactive() protected method $builder._problem__interactive() { var choice, category, bug, list, line, menu; while (choice != 'exit) { choice = .do_menu("Problem Reports", "", "1=>Scan unclaimed open problem reports", "2=>Scan your open problem reports", "X=>Exit", 'exit); switch (choice) { case "1": (> ._problem__ilist('unclaimed) <); case "2": (> ._problem__ilist('mine) <); case 'exit: return "Goodbye."; } } }; new method Adding protected method $builder._problem__claim() protected method $builder._problem__claim() { arg args, opts, report; var n, id, s, cmt; n = (report.group()).name(); id = report.id(); if (report.claimed_on()) { .tell((((n + " Problem Report #") + id) + " has already been claimed by ") + ((report.claimed_by()).namef('ref))); s = .prompt("Reclaim it in your name? [no] "); if ((!s) || ((s.is_boolean()) == 0)) return "** Aborting."; } .tell(report.format_short()); s = .prompt(("Claim this " + n) + " Problem Report? [yes] "); if ((s.is_boolean()) == 0) return "** Aborting."; .tell("** Enter any remarks, or nothing for no remarks."); cmt = .read("** Enter \".\" to finish or \"@abort\" to abort claiming."); if (type(cmt) != 'list) return; if (cmt) report.add_comment(cmt); report.claim(); return (("** You have claimed " + n) + " Problem Report #") + id; }; method access Changing method $builder.teleport_cmd() access from public to protected object $builder; eval { var l; dblog("set_method_access('teleport_cmd, 'protected"); catch any { set_method_access('teleport_cmd, 'protected); } with { for l in ($parse_lib.traceback(traceback())) dblog(l); } }; new method Replacing protected method $builder.build_prompt() protected method $builder.build_prompt() { arg prompt, @def; var name, ans; [(def ?= "")] = def; while (!ans) { ans = .prompt(prompt); if (ans == "@skip") throw(~skip, "Skipped"); if (!ans) { if (!def) continue; ans = def; } } return ans; }; new method Adding private method $builder._problem__mailmsg() private method $builder._problem__mailmsg() { arg report, msg; var u, recip, text, mail, id, fmt; u = report.submitted_by(); id = report.id(); if (valid(u) && (u.is($mail_list))) { text = (u.mail_name()) + " and *bugs"; .tell("** Specify recipients for this comment, or 'none'"); recip = .prompt(("** Mail comment to [" + text) + "] "); if (!recip) recip = text; if ((recip == "no") || (recip == "none")) return "** Not mailing."; recip = .parse_mail_recipient_list(recip); if (!recip) return "** No valid recipients."; mail = $mail_message.new_mail(); mail.set_subject((("Comment on PR #" + id) + ": ") + (report.summary())); text = ["This comment is in regard to the following report:", ""]; fmt = report.format_short(); text += delete(fmt, listlen(fmt)).prefix(" "); text += ["", "You can view this problem report with the command:", ""]; text += [" @pr " + id, "", "-- Comment:", ""] + msg; mail.set_text(text); catch any mail.send(@recip); with return (traceback()[1])[2]; return "** Mail sent."; } }; new method Adding protected method $builder._problem__get_group() protected method $builder._problem__get_group() { arg args, opts; var group, groups, s, menu; groups = $problem_group.children(); if (opts) { if ("a?ll" in (opts.slice(1))) group = 'All; else if (!(group = (| groups.match_object((opts[1])[2]) |))) throw(~stop, ("Invalid Problem Group '" + ((opts[1])[2])) + "'"); } else { while (1) { menu = ["0=>ALL GROUPS"]; for group in [1 .. listlen(groups)] menu += [(group + "=>") + ((groups[group]).name())]; menu += ["X=>Exit"]; s = .do_menu("Problem Groups", "Select Problem Group", @menu); if ((!s) || (s == "X")) return 0; if (s.is_numeric()) { if ((!(group = (| groups[toint(s)] |))) && (s == "0")) group = 'All; } if (!group) .tell(["**", ("** Sorry, '" + s) + "' is not a valid group."]); else break; } } return group; }; new method Replacing protected method $builder.destroy_cmd() protected method $builder.destroy_cmd() { arg cmdstr, cmd, objs; var name, ans, obj, fail; (> .perms(caller(), 'command) <); cmd = cmd.trim(); for obj in (filter obj in (objs) where (obj.is($user))) { .tell(("You shouldn't @destroy users (" + (obj.name())) + "), use @reap."); fail++; } if (fail) { .tell("Destroying a user directly may not cleanup everything properly."); .tell("Objects managed by the user will be given to $reaper."); ans = .prompt("Given this information, do you want to continue? [no] "); if (!(ans in ["y", "yes"])) return "Ok, aborting.."; } for obj in (objs) { catch any { name = obj.namef('xref); (> obj.destroy() <); if (valid(obj)) .tell(("Unable to destroy " + name) + " immediately."); else .tell(("Successfully destroyed " + name) + "."); } with { return (traceback()[1])[2]; } } }; new method Adding protected method $builder._problem__comment() protected method $builder._problem__comment() { arg args, opts, report; var text, fmt, cmt, n, u, msg, id; n = (report.group()).name(); id = report.id(); .tell("** Commenting on Problem Report #" + id); cmt = .read("** Enter \".\" to finish or \"@abort\" to abort."); if ((type(cmt) != 'list) || (!cmt)) return "** No comments added."; report.add_comment(cmt); .tell((("** Comments added to " + n) + " PR #") + id); return ._problem__mailmsg(report, cmt); }; new method Replacing protected method $builder.attach_cmd() protected method $builder.attach_cmd() { arg cmdstr, cmd, source, prep, dest; var path; (> .perms(caller(), 'command) <); if (!source) { source = .location(); } else { catch any source = (> .match_environment(source) <); with return (traceback()[1])[2]; if (!(source.is($place))) return (source.namef('ref)) + " is not a $place."; } catch ~abort, ~skip path = (> .build_get_path(source, dest) <); with return "Aborted."; catch any { path.attach(source, dest); path.configure(#[['named_name, 1]]); } with { .tell("Ack, unable to attach path because:"); .tell(" " + ((traceback()[1])[2])); (| path.destroy() |); return; } return ("Successfully attached path " + (path.name())) + "."; }; new method Adding protected method $builder._problem__iview() protected method $builder._problem__iview() { arg pr; var str, msg; msg = "[RET] Return, [N]ext, [P]rev, [C]laim, [F]ix, [D]ismiss, [A]ppend"; while (1) { .tell(pr.format_full()); str = .prompt(msg); if ((!str) || match_template(str, "x|ex?it")) return 0; if (match_template(str, "n?ext")) return 'next; if (match_template(str, "p?revious")) return 'prev; if (match_template(str, "cl?aim")) .tell(._problem__claim([], [], pr)); else if (match_template(str, "f?ix|r?esolve")) .tell(._problem__fix([], [], pr)); else if (match_template(str, "d?ismiss")) .tell(._problem__dismiss([], [], pr)); else if (match_template(str, "a?ppend|cmt|com?ment")) .tell(._problem__comment([], [], pr)); } }; new method Adding protected method $builder._problem__ilist() protected method $builder._problem__ilist() { arg how; var reports, list, g, r, pr, list, keys, choice; while (1) { if (how == 'mine) { reports = #[]; for g in (setremove($problem_group.children(), $dismissed_problems)) { list = filter r in (g.problems()) where ((!((r[2])[2])) && (((r[2])[5]) == this())); if (list) reports = dict_add(reports, g, list); } .tell("** Your Un-Resolved Problem Reports:"); list = ._problem_listgrp(reports, (.linelen()) - 32, 1); } else { list = ._problem__list([], []); if ((!list) || (list == "Goodbye.")) return; } pr = .prompt("Select Problem Report, or [RET] to exit"); if ((!pr) || match_template(pr, "x|ex?it")) return; if ((!(pr.is_numeric())) || (!dict_contains(list, toint(pr)))) { .tell("Invalid Problem Report"); } else { pr = toint(pr); keys = dict_keys(list); while ((choice = ._problem__iview(list[pr]))) { if (choice == 'next) { r = pr in keys; if (r < listlen(keys)) { pr = keys[r + 1]; } else { .tell("No Next Problem Report."); break; } } else { r = pr in keys; if (r != 1) { pr = keys[r - 1]; } else { .tell("No Previous Problem Report."); break; } } } } } }; new method Adding protected method $builder._problem_listgrp() protected method $builder._problem_listgrp() { arg reports, w, full; var group, report, r, id, date, summary, resolved, str, list, out; list = #[]; out = []; for group in (dict_keys(reports)) { for report in (reports[group]) { id = report[1]; [r, resolved, date, summary] = report[2]; date = $time.format("%d-%h-%Y", date); if (full) str = strfmt("%4r: %11l %11l %*e", id, group.name(), date, w, summary).trim('right); else str = strfmt("%4r: %11l %*e", id, date, w, summary).trim('right); out += [str]; list = dict_add(list, id, r); } } .tell(out); .tell(("--- " + listlen(dict_keys(list))) + " Total"); return list; }; new method Adding protected method $builder.problems_cmd() protected method $builder.problems_cmd() { arg cmdstr, cmd, args; var syn, opts, report, command; syn = ("Syntax: " + cmd) + " [+<problem group>] <cmt|list|view|fix> [addtl]"; [args, opts] = (> $parse_lib.opt(args, "a?ll", "f?ull") <); if (!args) return ._problem__interactive(); if ((listlen(args) > 1) && ((args[1]).is_numeric())) args = [args[2], args[1]] + sublist(args, 3); [command, @args] = args; if (match_template(command, "com?ment|cmt")) { report = (> ._problem__get_report(args, cmd + " comment") <); return (> ._problem__comment(sublist(args, 2), opts, report) <); } else if (match_template(command, "l?ist")) { return (> ._problem__list(args, opts) <); } else if (match_template(command, "v?iew")) { report = (> ._problem__get_report(args, cmd + " view") <); return (> ._problem__view(sublist(args, 2), opts, report) <); } else if (match_template(command, "cl?aim")) { report = (> ._problem__get_report(args, cmd + " claim") <); return (> ._problem__claim(sublist(args, 2), opts, report) <); } else if (match_template(command, "r?esolv|f?ix")) { report = (> ._problem__get_report(args, cmd + " fix") <); return (> ._problem__fix(sublist(args, 2), opts, report) <); } else { if ((!args) && (command.is_numeric())) { report = (> ._problem__get_report([command], cmd + " view") <); return (> ._problem__view([], opts, report) <); } return [syn, ("Unsupported command '" + command) + "'"]; } }; method access Changing method $builder.dig_cmd() access from public to protected object $builder; eval { var l; dblog("set_method_access('dig_cmd, 'protected"); catch any { set_method_access('dig_cmd, 'protected); } with { for l in ($parse_lib.traceback(traceback())) dblog(l); } }; new method Adding protected method $builder._problem__view() protected method $builder._problem__view() { arg args, opts, report; // if (args && match_begin("full", args[1]) || "f?ull" in opts.slice(1)) return report.format_full(); // return report.format_short(); }; new method Adding protected method $builder._problem__get_report() protected method $builder._problem__get_report() { arg args, cmd; var report, g, menu; if (!args) throw(~stop, ("No report specified with '" + cmd) + "'"); [report, @args] = args; if ((report[1]) == "$") { catch any report = $object_lib.to_dbref(report); with throw(~stop, (traceback()[1])[2]); if ((!(report.is($problem_report))) || (report == $problem_report)) throw(~stop, (report.namef('ref)) + " is not a Problem Report."); } else { if ((report[1]) == "#") report = substr(report, 2); report = toint(report); if (report <= 0) throw(~stop, "Invalid report number #" + report); for g in ($problem_group.children()) { if (dict_contains(g.problems(), report)) return ((g.problems())[report])[1]; } throw(~stop, "Unable to find problem report #" + report); } }; new method Adding protected method $builder._problem__list() protected method $builder._problem__list() { arg args, opts; var reports, w, all, r, g, list, group; group = (> ._problem__get_group(args, opts) <); if (!group) return "Goodbye."; if (group != 'All) { reports = filter r in (group.problems()) where (!((r[2])[2])); reports = #[[group, reports]]; .tell(("** Un-Resolved " + (group.name())) + " Problem Reports:"); w = (.linelen()) - 20; } else { reports = #[]; for g in (setremove($problem_group.children(), $dismissed_problems)) { list = filter r in (g.problems()) where (!((r[2])[2])); if (list) reports = dict_add(reports, g, list); } all = 1; .tell("** ALL Un-Resolved Problem Reports:"); w = (.linelen()) - 32; } return ._problem_listgrp(reports, w, all); }; update objvar Updating objvar $storyteller<$thing>,gender object $storyteller; var $thing gender = $gender_neuter; new method Replacing public method $programmer.define_setting_cmd() public method $programmer.define_setting_cmd() { arg cmdstr, cmd, args; var def_opts, opts, o, name, config, m, definer, syn, type, def, val; syn = ("Syntax: `" + cmd) + " <definer>:<setting>[=default] [options]`"; def_opts = []; for o in (["get", "set", "parse"]) def_opts += [[o, 1], [o + "-a?rgs", 1]]; def_opts += [["c?lear", 1], ["f?ormat", 1], ["a?ccess", 1], ["t?ype", 1]]; [args, opts] = $parse_lib.getopt(args, def_opts); args = join(args, " "); if (!args) { .tell(syn); for o in (def_opts.slice(1)) .tell((((" +" + o) + "=<") + ((o.strip("?")).replace("-", " "))) + ">"); return "Types can be any ColdC type and \"boolean\""; } if ((m = regexp(args, "^([^=]+) *= *(.*)$"))) [args, def] = m; else def = ""; m = split(args, " *: *"); if (listlen(m) != 2) return syn; [definer, name] = m; if ((m = regexp(name, "[^\@a-z0-9-]"))) { .tell((("Invalid character '" + (m[1])) + "' in setting name: ") + name); throw(~stop, "Setting name may only contain a-z, 0-9 and a dash"); } catch any definer = (> .match_environment(definer) <); with return (traceback()[1])[2]; if (!name) return syn; // setup some default config opts based off the desired type config = #[]; if ((m = "t?ype" in (opts.slice(1)))) { type = (| ((opts[m])[4]).to_symbol() |); if ((!type) || (!($settings.is_valid_type(type)))) return "Types can be any ColdC type and " + (($settings.valid_types()).to_english("", " or ")); switch (type) { case 'boolean: config = #[['parse, ['is_boolean]], ['format, ['format_boolean]]]; case 'itemlist: // do nothing, we re-adjust things later default: config = #[['parse, ['is_type, type]]]; } } // now build default config--not the most efficient way--but cleaner config = (> ._def_setcmd_opt("get", 'symbol, opts, config) <); config = (> ._def_setcmd_opt("get-a?rgs", 'data_list, opts, config) <); config = (> ._def_setcmd_opt("set", 'symbol, opts, config) <); config = (> ._def_setcmd_opt("set-a?rgs", 'data_list, opts, config) <); config = (> ._def_setcmd_opt("parse", 'symbol, opts, config) <); config = (> ._def_setcmd_opt("parse-a?rgs", 'data_list, opts, config) <); config = (> ._def_setcmd_opt("c?lear", 'symbol, opts, config) <); config = (> ._def_setcmd_opt("f?ormat", 'symbol, opts, config) <); config = (> ._def_setcmd_opt("a?ccess", 'symbol, opts, config) <); if (type == 'itemlist) { config = config.add('parse, ['parse_itemlist, @(| config['parse] |) || []]); if (!(config.contains('format))) config = config.add('format, ['format_itemlist]); } // now add it.. catch any config = (> definer.define_setting(name, config) <); with return (traceback()[1])[2]; .tell(((("-- Defined setting " + definer) + ":") + name) + " as:"); for o in (config) { val = o[2]; o = o[1]; .tell(((" +" + strsub(tostr(o), "_", "-")) + "=") + (val[1])); if (listlen(val) > 1) .tell(((" +" + strsub(tostr(o), "_", "-")) + "-args=") + (sublist(val, 2).join(","))); } // and set the default value catch any { o = definer; o = o.set_setting(name, o, def); val = o.format_setting(name, o, o.get_setting(name, o)); return ["-- Default Setting:", ((" " + name) + " = ") + val, "--"]; } with { return (traceback()[1])[2]; } }; new method Adding protected method $programmer._eval_subs() protected method $programmer._eval_subs() { arg code; var out, x; out = ""; while ((x = match_regexp(code, "\^[a-z0-9_]+"))) { x = x[1]; out += substr(code, 1, (x[1]) - 1); out += .match_env_nice(substr(code, (x[1]) + 1, (x[2]) - 1)); code = substr(code, x.sum()); } if (code) out += code; return out; }; new method Replacing protected method $programmer.program_cmd() protected method $programmer.program_cmd() { arg cmdstr, com, args, @more; var ref, o, i, ops, ign, ed, fl, meth, ex, acc, warn, errs, code, line, errs, code; (> .perms(caller(), 'command) <); ops = args[3]; ref = args[1]; // verify what we have is correct if (!(meth = (| tosym(ref[4]) |))) { ign++; .tell(("The method name '" + (((ref[4]) == 0) ? "" : (ref[4]))) + "' is not acceptable."); } if ((!ign) && ((ref[3]) && (!((ref[3]).is_writable_by(this()))))) { ign++; .tell(("You cannot program on " + ((ref[3]).namef('ref))) + "."); } if ((!ign) && ((| (ref[3]).find_method(meth) |) == (ref[3]))) ex++; // ok, go on with options o = ops.slice(1); if ((i = "e?dited" in o)) { if (!((ops[i])[3])) { if (!($sys.is_admin(this()))) { ign++; .tell("Only admins can shut off edited comments."); } } else { ed = 1; } } else { ed = 1; } if (ed) { ed = (("// $#Edited: " + ($time.format("%d %h %y %H:%M"))) + " ") + this(); if (i && ((ops[i])[4])) ed += ": " + ((ops[i])[4]); } if ((i = "f?lags" in o)) fl = $parse_lib.parse_method_flags((ops[i])[4]); else if (ex) fl = (ref[3]).method_flags(meth); else fl = []; if ((i = "a?ccess" in o)) acc = $parse_lib.parse_method_access((ops[i])[4]); else if (ex) acc = (ref[3]).method_access(meth); else acc = 'public; if ((i = "w?arnings" in o)) warn = (ops[i])[4]; else warn = 1; // now get on with it already if (ign) line = "Ignoring input until \".\" or \"@abort\""; else if (ex) line = ((((("Reprogramming " + acc) + " method ") + (ref[3])) + ".") + meth) + "()"; else line = ((((("Programming " + acc) + " method ") + (ref[3])) + ".") + meth) + "()"; if (fl) line += (" [" + (fl.to_english())) + "]"; code = more ? (more.subrange(2)) : (.read(("-- " + line) + " --")); if (type(code) == 'symbol) { switch (code) { case 'aborted: return; case 'engaged: return "Sorry, you are already reading on this connection."; default: return "Unknown response from the read parser: " + code; } } if (ign) return "Finished ignoring input."; if (ed) code += [ed]; catch any { if ((errs = (ref[3]).add_method(code, meth))) return errs.prefix("** "); (> (ref[3]).set_method_flags(meth, fl) <); (> (ref[3]).set_method_access(meth, acc) <); if ((line = (> $code_lib.verify_code(code, meth, warn) <))) .tell(line); return ((((("Method " + (ref[3])) + ".") + meth) + "() ") + (ex ? "re" : "")) + "compiled."; } with { return (traceback()[1])[2]; } }; new method Replacing protected method $programmer.list_cmd() protected method $programmer.list_cmd() { arg cmdstr, cmd, args; var i, pattern, ref, methods, s, def, method, opts, str, m, d, out, type; (> .perms(caller(), 'command) <); if ((opts = .get_setting("@list-options", $programmer))) { opts = (> $parse_lib.opt(opts, "n?umbers", "t?extdump") <); opts = union(args[3], opts[2]); } else { opts = args[3]; } if ((i = (| "n?umbers" in (opts.slice(1)) |)) && ((opts[i])[3])) type = 'numbered; else if ((i = (| "t?extdump" in (opts.slice(1)) |)) && ((opts[i])[3])) type = 'textdump; else type = 'normal; ref = args[1]; if ((ref[1]) == 'variable) return ((("The reference " + (ref[3])) + ",") + ((ref[4]) || "")) + " is not for a method."; if ((ref[1]) == 'object) return ("The reference " + (ref[3])) + " is not for a method."; def = (| (ref[2]).find_method(tosym(ref[4])) |); if (def) { pattern = ref[4]; methods = [tosym(ref[4])]; } else { if (ref[4]) pattern = ref[4]; else pattern = .get_setting("match-default", $programmer); def = ref[3]; m = .get_setting("match-with", $programmer); methods = []; for method in (def.methods()) { if (tostr(method).(m)(pattern) != 0) methods += [method]; } if (!methods) return .tell((("No method found matching " + def) + ".") + pattern); } cmd = .get_setting("@program-options", $programmer); out = []; for method in (methods) out += .format_method(def, method, type, cmd); return out; }; new method Replacing public method $programmer.evaluate() public method $programmer.evaluate() { arg str, obj, definer, @mode; var start, end, time, ticks, mtime, times1, times2, method, errs, trace, result, is_error; mode = mode ? (mode[1]) : 0; if (sender() != $eval_parser) (> .perms(caller(), $programmer) <); method = tosym("tmp_eval_" + time()); if ((errs = (> definer.add_method([str], method, 'evalonly) <))) { if (mode) return [[0, 0, 0], ['errors, errs, 0, 0], []]; else return [[0, 0, 0], ['errors, errs, 0, 0]]; } if (mode == 'opcodes) { times1 = [tick(), time(), mtime()]; result = obj.method_bytecode(method); times2 = [mtime(), time(), tick()]; } else { catch any { if (mode in ['trace, 'profile]) debug_callers(1); else if (mode == 'debug) debug_callers(2); times1 = [tick(), time(), mtime()]; result = (> obj.(method)() <); times2 = [mtime(), time(), tick()]; trace = call_trace(); debug_callers(0); } with { times2 = [mtime(), time(), tick()]; result = traceback(); is_error = 1; debug_callers(0); } } (| definer.del_method(method) |); // figure up the actual times time = (times2[2]) - (times1[2]); ticks = (times2[3]) - (times1[1]); if ((times2[1]) > (times1[3])) mtime = (times2[1]) - (times1[3]); else if (time) mtime = ((time * 1000000) + (1000000 - (times1[3]))) + (times2[1]); else mtime = (1000000 - (times2[1])) + (times1[3]); // offset it? if (eval_offset && (mode != 'no_offset)) { ticks -= eval_offset[1]; time -= eval_offset[2]; mtime -= eval_offset[3]; } if (trace) return [[ticks, time, abs(mtime)], ['result, result], $code_lib.generate_debug_listing(trace, mode)]; return [[ticks, time, abs(mtime)], [is_error ? 'traceback : 'result, result]]; }; new method Replacing protected method $programmer.eval_subs() protected method $programmer.eval_subs() { arg code; var out, m, sub, tok; // HORRIBLY inefficient tok = ("#@#ESCQUOTE-" + time()) + "#@#"; code = strsub(code, "\\\"", tok); out = ""; while ((m = match_pattern(code, "*\"*\"*"))) { out += (((._eval_subs(m[1])) + "\"") + (m[2])) + "\""; code = m[3]; } if (code) out += ._eval_subs(code); return strsub(out, tok, "\\\""); }; new method Replacing protected method $programmer.ancestors_cmd() protected method $programmer.ancestors_cmd() { arg cmdstr, cmd, args; var syn, obj, maxlevels, line; (> .perms(caller(), 'command) <); syn = cmd + " <obj> [<levels>]"; args = args.explode(); if (!((args.length()) in [1, 2])) return syn; obj = (> .match_env_nice(args[1]) <); if ((args.length()) == 2) { if ((args[2]) == "all") maxlevels = 0; else maxlevels = abs(toint(args[2])) + 1; } else { maxlevels = 3; } line = ("Ancestors of " + obj) + ":"; if (maxlevels) { line += tostr(maxlevels - 1); line = ((line + " level") + (((maxlevels - 1) > 1) ? "s" : "s")) + ":"; } else { line += "all levels:"; } .tell(line); .tell(obj._display_ancestors("", #[], 0, maxlevels)); .tell("---"); }; new method Replacing protected method $programmer.eval_cmd() protected method $programmer.eval_cmd() { arg cmdstr, com, str; var result, adjust, vars, v, evalp, times, line, reg, obj, definer, ref, debug; (> .perms(caller(), 'command) <); evalp = .eval_prefix(); vars = (evalp.keys()).join(", "); v = (evalp.values()).join(); // clean it up str = strsed(str, "^;*", ""); // perform escape substitution if (str && ((str[1]) == "|")) str = substr(str, 2); else str = .eval_subs(str); // check for debug flags if ((reg = regexp(str, "^(trace|debug|profile|ops|opcodes) *;*(.*)$"))) { [debug, str] = reg; if (debug == "ops") debug = "opcodes"; debug = tosym(debug); } else { debug = 0; } // who are we evaluating as if ((reg = regexp(str, "^ *as +([^; ]+)"))) { ref = $parse_lib.ref(reg[1]); obj = ref[2]; definer = ref[3]; str = strsed(str, "^ *as +([^; ]+)[ ;]+", ""); if ((!(definer.is_writable_by(this()))) || (!(obj.is_writable_by(this())))) return ("You do not have permission to evaluate on " + (reg[1])) + "."; if (!(obj.is(definer))) return (obj + " isn't a child of ") + definer; } else { obj = (definer = this()); } // are we just adjusting our offset? if (!str) { result = (> .evaluate(((("var " + vars) + ";") + v) + "return (> 1 <);", obj, definer, 'no_offset) <); result = replace(result[1], 1, ((result[1])[1]) - 1); if (eval_offset) line = strfmt("adjusted by %s ticks and %s.%6{0}r seconds.", (eval_offset[1]) - (result[1]), (eval_offset[2]) - (result[2]), abs((eval_offset[3]) - (result[3]))); else line = strfmt("set to %s ticks and %s.%6{0}r seconds.", @result); eval_offset = result; return "Eval offset " + line; } // format it if (match_begin(str, "var") && (reg = regexp(str, "var ([^;]+)"))) { str = strsed(str, "var ([^;]+);", ""); str = ((((("var " + vars) + ", ") + (reg.join(","))) + ";") + v) + str; } else if ("return" in str) { str = ((("var " + vars) + ";") + v) + str; } else { str = strsed(str, " *;* *$", ""); str = ((((("var " + vars) + ";") + v) + "return (> ") + str) + " <);"; } if (debug) { result = (> .evaluate(str, obj, definer, debug) <); debug = (| result[3] |); } else { result = (> .evaluate(str, obj, definer, debug) <); } [times, result] = result; // Display the errors, or the result. if ((result[1]) == 'errors) { .tell(result[2]); } else if ((result[1]) == 'traceback) { .tell((result[2]).fmt_tb()); line = strfmt("[ seconds: %l.%6{0}r; operations: %s", times[2], times[3], times[1]); if (times[2]) line += (" (" + ((times[1]) / (times[2]))) + " ticks per second)"; return line + " ]"; } else { if (type(result[2]) == 'objnum) .tell("=> " + ((| (result[2]).namef('xref) |) || (result[2]))); else .tell("=> " + toliteral(result[2])); if (debug) .tell(debug); line = strfmt("[ seconds: %l.%6{0}r; operations: %s", times[2], times[3], times[1]); if (times[2]) line += (" (" + ((times[1]) / (times[2]))) + " ticks per second)"; return line + " ]"; } }; new method Replacing protected method $programmer.id_cmd() protected method $programmer.id_cmd() { arg cmdstr, cmd, obj; (> .perms(caller(), 'command) <); obj = (> .match_env_nice(obj) <); if (type(obj) == 'frob) return ["The target object was a frob."]; .tell((((((((obj.namef('xref)) + " ") + ($object_lib.see_perms(obj))) + " ") + toliteral(obj.parents())) + " ") + tostr(obj.size())) + " bytes"); }; new method Replacing protected method $programmer.del_shortcut_cmd() protected method $programmer.del_shortcut_cmd() { arg cmdstr, cmd, args; var ref, syn; (> .perms(caller(), 'command) <); args = args.explode_quoted(); if ((listlen(args) == 3) && ((args[2]) == "from")) args = delete(args, 2); if (listlen(args) != 2) return ("Syntax: `" + cmd) + " \"<shortcut>\" [from] <objref>"; ref = (> $parse_lib.ref(args[2]) <); if (((ref[1]) != 'method) || ((!(ref[4])) || (!(| tosym(ref[4]) |)))) return ("Invalid method reference reference \"" + (args[2])) + "\"."; catch any (> (ref[2]).del_shortcut(args[1]) <); with return (traceback()[1])[2]; return strfmt("Deleted shortcut %d from %s.%s().", args[1], ref[2], ref[4]); }; update objvar Updating objvar $admin<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["@del-t?ask|@kill", [["@del-t?ask|@kill", "*", "@del-t?ask|@kill <any>", 'del_task_cmd, #[[1, ['any, []]]]]]], ["@backup", [["@backup", "", "@backup", 'backup_cmd, #[]]]], ["@shutdown", [["@shutdown", "*", "@shutdown <any>", 'shutdown_cmd, #[[1, ['any, []]]]]]], ["@mojo", [["@mojo", "*", "@mojo <any>", 'mojo_cmd, #[[1, ['any, []]]]]]], ["@adjust|@promote", [["@adjust|@promote", "* to *", "@adjust|@promote <user> to <any>", 'adjust_cmd, #[[1, ['user, []]], [3, ['any, []]]]]]], ["@new-password|@newpw?d", [["@new-password|@newpw?d", "*", "@new-password|@newpw?d <user>", 'new_password_cmd, #[[1, ['user, []]]]]]], ["@task?s", [["@task?s", "*", "@task?s <any>", 'tasks_cmd, #[[1, ['any, []]]]]]], ["@core", [["@core", "*", "@core <list object>", 'core_cmd, #[[1, ['list, ['object, []]]]]]]], ["@rehash-all", [["@rehash-all", "*", "@rehash-all <any:-p?urge>", 'rehash_all_cmd, #[[1, ['any_opt, ["p?urge"]]]]]]], ["@reap", [["@reap", "*", "@reap <any>", 'reap_cmd, #[[1, ['any, []]]]]]], ["@quota", [["@quota", "* to *", "@quota <object> to <any:+e?xempt>", 'quota_cmd, #[[1, ['object, []]], [3, ['any_opt, ["e?xempt"]]]]]]], ["@kick", [["@kick", "*", "@kick <any>", 'kick_cmd, #[[1, ['any, []]]]]]], ["@chman?age", [["@chman?age", "*", "@chman?age <any>", 'chmanage_cmd, #[[1, ['any, []]]]]]]]; new = #[["@del-t?ask|@kill", [["@del-t?ask|@kill", "*", "@del-t?ask|@kill <any>", 'del_task_cmd, #[[1, ['any, []]]]]]], ["@backup", [["@backup", "", "@backup", 'backup_cmd, #[]]]], ["@shutdown", [["@shutdown", "*", "@shutdown <any>", 'shutdown_cmd, #[[1, ['any, []]]]]]], ["@mojo", [["@mojo", "*", "@mojo <any>", 'mojo_cmd, #[[1, ['any, []]]]]]], ["@adjust|@promote", [["@adjust|@promote", "* to *", "@adjust|@promote <user> to <any>", 'adjust_cmd, #[[1, ['user, []]], [3, ['any, []]]]]]], ["@new-password|@newpw?d", [["@new-password|@newpw?d", "*", "@new-password|@newpw?d <user>", 'new_password_cmd, #[[1, ['user, []]]]]]], ["@task?s", [["@task?s", "*", "@task?s <any>", 'tasks_cmd, #[[1, ['any, []]]]]]], ["@core", [["@core", "*", "@core <list object>", 'core_cmd, #[[1, ['list, ['object, []]]]]]]], ["@rehash-all", [["@rehash-all", "*", "@rehash-all <any:-p?urge>", 'rehash_all_cmd, #[[1, ['any_opt, ["p?urge"]]]]]]], ["@reap", [["@reap", "*", "@reap <any>", 'reap_cmd, #[[1, ['any, []]]]]]], ["@quota", [["@quota", "* to *", "@quota <object> to <any:+e?xempt>", 'quota_cmd, #[[1, ['object, []]], [3, ['any_opt, ["e?xempt"]]]]]]], ["@kick", [["@kick", "*", "@kick <any>", 'kick_cmd, #[[1, ['any, []]]]]]], ["@chman?age", [["@chman?age", "*", "@chman?age <any>", 'chmanage_cmd, #[[1, ['any, []]]]]]], ["@player-breakdown|@pb", [["@player-breakdown|@pb", "", "@player-breakdown|@pb", 'player_breakdown_cmd, #[]]]]]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$admin<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $admin; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); new method Replacing protected method $admin.adjust_cmd() protected method $admin.adjust_cmd() { arg cmdstr, cmd, who, prep, str; var i, what, p, pwd, o, email, valid; (> .perms(caller(), 'command) <); (> .check_mojo() <); valid = #[["user", $user], ["player", $player], ["builder", $builder], ["programmer", $programmer], ["admin", $admin]]; what = (str.explode()).last(); if (!(valid.contains(what))) return ("Promote to: " + ((valid.keys()).to_english())) + "."; // mail them the password--do this first incase we fail here if ($guest in (who.parents())) { who.set_setting("title", $user, ""); pwd = $code_lib.random_password(); who.set_password(pwd); email = who.user_info("email"); if (!email) return (who.namef('ref)) + " does not have an email address!"; catch any { $smtp.sendmail('admin, email, ("[" + ($motd.server_name())) + "] password change.", [((("The password for the user " + (who.name())) + " on ") + ($motd.server_name())) + " has been set as:", "", " " + pwd, "", "This is an automatic message sent to the supplied address. If this message is in error simply discard it.", "", "If no connections are made to this user within a week it will be purged."]); } with { if (error() == ~error) { .tell(("While trying to email '" + email) + "':"); .tell((traceback()[1])[2]); return "** Aborting adjustment **"; } .tell_traceback(traceback()); return "** Unable to send mail message, no changes made **"; } } // selectively cleanup their 'new' parents list, retain special parents p = who.parents(); for o in ([$guest] + (valid.values())) p = setremove(p, o); // add the parent we care about to the front, call chparents() // we are admins, we can handle tracebacks if they occur. (> who.chparents(valid[what], @p) <); // update caches. who.cache_client_init(); // let'em know what we did what = what.add_indefinite(); who.tell((((.name()) + " has made you ") + what) + "."); // if we changed their password, let them know that too if (pwd) { who.tell(("** Your password has been emailed to " + email) + " **"); who.tell("** You can change it with the command: `@password` **"); } (.location()).announce(((("*poof* " + (who.name())) + " is now ") + what) + ".", who, this()); return ((("Ok, " + (who.name())) + " is now ") + what) + "."; }; new method Replacing protected method $admin.status_cmd() protected method $admin.status_cmd() { arg cmdstr, com, @args; var opt, cache, x, y, width, depth, info, out, str, pre, dstr, dirty, c; (> .perms(caller(), 'command) <); opt = (> $parse_lib.opt(args.join(" "), "c?ache", "d?irtyonly") <); if ((x = "c?ache" in ((opt[2]).slice(1)))) cache = 1; if (!cache) return pass(cmdstr, com, @args); [width, depth, info] = $sys.cache_info(); out = [((((("Cache Size: " + width) + "x") + depth) + " (") + (width * depth)) + " total object capacity)"]; info = map x in (info) to (strsub(x, "i", ".", "c")); if (width < 80) { if (width < 78) { pre = 1; str = " +"; } else { pre = 0; str = ""; } str = strfmt(str + "%*{-}c", width, " WIDTH "); out += ["Cache Map (Horizontal):", str]; dstr = "DEPTH"; for y in [1 .. depth] { if (pre) { if (y <= strlen(dstr)) str = (dstr[y]) + "|"; else str = " |"; } else { str = ""; } for x in [1 .. width] { refresh(); if (strlen(info[x]) >= y) { c = (info[x])[y]; str += (info[x])[y]; } else { str += " "; } } out += [str]; } if (pre) out += [" +" + ("-" * width)]; else out += ["-" * width]; } else { str = strfmt(" +%*{-}c", depth, " DEPTH "); out += ["Cache Map (Vertical):", str] + (info.prefix(" |")); } return out + ["Object Legend: a=active, A=active+dirty, .=inactive, I=inactive+dirty"]; }; new method Replacing protected method $admin.tasks_cmd() protected method $admin.tasks_cmd() { arg cmdstr, cmd, args; var out, task, queue, time, args, fmt, tfmt, info, suspend, preempt, line, x; (> .perms(caller(), 'command) <); (> .check_mojo() <); out = []; if (args) { for x in (explode(args)) { if ((x[1]) == "*") x = substr(x, 2); if (!(task = (| $scheduler.task_info(toint(x)) |))) { .tell(("Invalid task '" + x) + "'"); continue; } out = ["Task: " + ((task[1])[1]), "", strfmt(" %8l %15L %s", "TICKS", "USER", "METHOD")]; // add an option to not restrict this for info in (sublist(task, 3)) out += [strfmt(" %8l %15L %s.%s()", info[7], info[4], info[1], info[8])]; } return out; } queue = $scheduler.task_queue(); if (queue) { tfmt = "%d %h %y %H:%M:%S"; fmt = "%5L %20L %s"; time = $time.format(tfmt); out = [strfmt(fmt, "ID", "EXEC TIME", "TASK"), strfmt(fmt, "---", "---------", "----")]; fmt += ".%s(%s)"; for task in (queue) { args = toliteral(task[8]); out += [strfmt(fmt, task[1], $time.format(tfmt, task[2]), task[4], task[6], substr(args, 2, strlen(args) - 2))]; } if (out) out = ["-- Database Tasks --"] + out; } if ((queue = tasks())) { suspend = []; preempt = []; fmt = "%8l%8l%24L"; for task in (queue) { info = $scheduler.task_info(task); line = strfmt(fmt, (info[1])[1], (info[3])[7], ((((info[3])[1]) + ".") + ((info[3])[8])) + "()", (info[3])[4]); catch any { task = ($scheduler.suspended_task(task)).join(); if (strlen(task) > 38) task = substr(task, 1, 35) + "..."; } with { task = ""; } if ((info[1])[2]) preempt += [line + task]; else suspend += [line + task]; } tfmt = strfmt(fmt, "TASK", "TICKS", "METHOD") + "RESUMABLE BY"; if (preempt) out += ["-- Preempted Tasks --", tfmt] + preempt; if (suspend) out += ["-- Suspended Tasks --", tfmt] + suspend; } return out || "-- No suspended or preempted tasks --"; }; new method Replacing protected method $admin.reap_cmd() protected method $admin.reap_cmd() { arg cmdstr, cmd, args; var opts, thresh, i; (> .perms(caller(), 'command) <); (> .check_mojo() <); [args, opts] = (> $parse_lib.opt(args, "t?ime", "m?ail") <); args = args.join(); if ((i = "t?ime" in (opts.slice(1)))) { catch any thresh = $time.from_english((opts[i])[4]); with return (traceback()[1])[2]; } if ("m?ail" in (opts.slice(1))) return .reap_mail(args, thresh || (86400 * 7)); if (args) return (> .reap_user(args) <); else return (> .reap_list(thresh || ((86400 * 30) * 3)) <); }; new method Adding public method $admin.player_breakdown_cmd() public method $admin.player_breakdown_cmd() { arg cmdstr, cmd; var admins, programmers, builders, users, total, pstrip, bstrip, strip, names, players; // stuff to strip // users strip = [$guest, $user, $reaper, $no_one, $player, $builder, $storyteller, $programmer, $admin, #48421]; // programmers pstrip = [$admin]; // builders bstrip = [$programmer, $admin]; // get number of admins admins = listlen($sys.admins()); names = $sys.admins(); // get number of programmers, minus those that are also admins programmers = $programmer.descendants(); programmers = $list.setremove_all(programmers, pstrip); programmers = $list.setremove_all(programmers, $sys.admins()); names += programmers; programmers = listlen(programmers); // get number of builders builders = $builder.descendants(); builders = $list.setremove_all(builders, $sys.admins()); builders = $list.setremove_all(builders, $programmer.descendants()); builders = $list.setremove_all(builders, strip); names += builders; builders = listlen(builders); // get number of users users = $user.descendants(); users = $list.setremove_all(users, strip); names += users; users = listlen(users); // get total number of players, users counts everybody, even admins total = users; // correct for backwards places like tCD where everybody is a programmer if ((users - ((admins + programmers) + builders)) < 0) users = 0; else users = users - ((admins + programmers) + builders); // break it down sender().tell("--- Player Breakdown ---"); sender().tell(("There are currently " + total) + " total users."); sender().tell((" " + admins) + " admin(s) *"); sender().tell((" " + programmers) + " programmer(s)"); sender().tell((" " + builders) + " builder(s)"); sender().tell((" " + users) + " user(s)"); sender().tell("---"); sender().tell(""); players = (($sys.admins()).mmap('name)).prefix("*"); players += ($list.setremove_all($list.setremove_all($list.setremove($list.setremove($user_db.user_dbrefs(), #-732), #-581), strip), $sys.admins())).mmap('name); sender().tell($list.columnize(players, 3)); }; new method Replacing protected method $admin.shutdown_cmd() protected method $admin.shutdown_cmd() { arg cmdstr, com, @args; var time, opt, why, answer, ans; (> .perms(caller(), 'command) <); (> .check_mojo() <); args = (> $parse_lib.opt(args.join(), "t?ime") <); opt = "t?ime" in ((args[2]).slice(1)); if (opt && ((((args[2])[opt])[4]).is_numeric())) time = toint(((args[2])[opt])[4]); else time = 5; if (!(why = (args[1]).join())) why = "Administrator's whim."; .tell(((("Shutdown " + ($motd.server_name())) + " in ") + tostr(time)) + " minutes"); .tell("Reason for shutdown: " + why); ans = .prompt("Is this correct? [yes]: "); if (!ans) ans = "yes"; if (!(ans in ["yes", "y"])) { .tell("I didn't think so, aborting shutdown..."); return; } .tell("Ok!"); $sys.do_shutdown(time, why); }; new method Replacing protected method $admin.mojo_cmd() protected method $admin.mojo_cmd() { arg cmdstr, cmd, str; var syn, line, vars; (> .perms(caller(), $user, $admin) <); syn = cmd + " on|off"; if ((!str) || (!(str in ["on", "up", "off", "down"]))) return .mojo(1); // this is horribly non-configurable--we need a standard set of subs. vars = #[["$actor", this()], ["actor", .name()], ["actor.pp", (.gender()).pronoun('pp)]]; switch (str) { case "on", "up": if (this() in ($sys.system())) { return "You already have mojo turned on."; } else { $sys.add_to_system(this()); (.location()).announce(.eval_message("mojo-on", $admin, vars)); } case "off", "down": if (this() in ($sys.system())) { $sys.del_from_system(this()); (.location()).announce(.eval_message("mojo-off", $admin, vars)); } else { return "You don't have mojo turned on."; } } }; new method Replacing protected method $admin.new_password_cmd(): nooverride protected method $admin.new_password_cmd(): nooverride { arg cmdstr, cmd, user; var new, email; (> .perms(caller(), 'command) <); (> .check_mojo() <); email = user.user_info("email"); if (!email) return (user.namef('ref)) + " does not have an email address!"; .tell("Generating password and mailing it to: " + email); new = $code_lib.random_password(); catch any { $smtp.sendmail('admin, email, ("[" + ($motd.server_name())) + "] password change.", [((("The password for the user " + (user.name())) + " on ") + ($motd.server_name())) + " has been changed to:", "", " " + new, "", "This is an automatic message sent to the supplied address. If this message is in error simply discard it.", "", "This password was changed by " + (.name())]); } with { .tell_traceback(traceback()); return "** Unable to send mail message, password not changed **"; } user.set_password(new); user.tell([((("Your password has been reset by " + (.name())) + ". The new password has been emailed to ") + email) + "."]); .tell((("You reset " + (user.name())) + "'s password to: ") + new); }; chpar Changing parents for $on_location [$located_location] => [$thing, $location] object $on_location: $thing, $location; clear objvar Clearing objvar $on_location<$command_cache>,modules object $on_location; old var $command_cache modules; new method Replacing public method $on_location.description() public method $on_location.description() { arg flags; var line; line = ((("You see " + ((.contents()).map_to_english('namef, 'name))) + " on ") + (.name())) + "."; return (> pass(flags) <) + [line]; }; update objvar Updating objvar $in_location<$foundation>,msgs object $in_location; var $foundation msgs = #[["open", #[["general", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " opens ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>], ["inside", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " opens ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>], ["actor", <$ctext_frob, [["You open ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>]]], ["close", #[["inside", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " closes ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>], ["general", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " closes ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>], ["actor", <$ctext_frob, [["You close ", <$generator, ["this", [], [], 'gen_this]>, "."], #[]]>]]]]; update objvar Updating objvar $in_location<$has_commands>,local public method $has_commands.__upgrade_set_var() { var old, new; old = #[["exit|leave", [["exit|leave", "", "exit|leave", 'exit_cmd, #[]]]], ["exit", [["exit", "", "exit", 'exit_cmd, #[]]]]]; new = #[]; catch any { dblog("__upgrade_handle_var(1, local)"); local = .__upgrade_handle_var(1, "$in_location<$has_commands>,local", old, local, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $in_location; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); update objvar Updating objvar $in_location<$has_commands>,remote public method $has_commands.__upgrade_set_var() { var old, new; old = #[["enter", [["enter", "*", "enter <this>", 'enter_cmd, #[[1, ['this, []]]]]]], ["open", [["open", "*", "open <this>", 'open_cmd, #[[1, ['this, []]]]]]], ["close", [["close", "*", "close <this>", 'close_cmd, #[[1, ['this, []]]]]]]]; new = #[["open", [["open", "*", "open <this>", 'open_cmd, #[[1, ['this, []]]]]]], ["close", [["close", "*", "close <this>", 'close_cmd, #[[1, ['this, []]]]]]]]; catch any { dblog("__upgrade_handle_var(1, remote)"); remote = .__upgrade_handle_var(1, "$in_location<$has_commands>,remote", old, remote, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $in_location; eval { .__upgrade_set_var(); }; object $has_commands; eval { del_method('__upgrade_set_var); }; // old public method $has_commands.__upgrade_set_var(); update objvar Updating objvar $in_location<$foundation>,defined_msgs object $in_location; var $foundation defined_msgs = #[["open", #[['branches, ["general", "actor", "inside"]]]], ["close", #[['branches, ["general", "actor", "inside"]]]]]; old method Deleting normal method $in_location.enter_cmd() object $in_location; eval { del_method('enter_cmd); }; old method Deleting normal method $in_location.exit_cmd() object $in_location; eval { del_method('exit_cmd); }; old method Deleting normal method $in_location.tell() object $in_location; eval { del_method('tell); }; new method Replacing public method $trash.did_leave() public method $trash.did_leave() { arg mover, place; (> pass(mover, place) <); (| (items = items.del(sender())) |); }; update objvar Updating objvar $place<$root>,defined_settings public method $root.__upgrade_set_var() { var old, new; old = #[["public-home", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["realm", #[['get, ['realm]], ['set, ['set_setting_realm]], ['parse, ['parse_realm_setting]], ['clear, ['clear_realm_setting]]]], ["darkness", #[['get, ['darkness]], ['set, ['set_darkness]], ['parse, ['is_type, 'integer]]]]]; new = #[["public-home", #[['parse, ['is_boolean]], ['format, ['format_boolean]]]], ["realm", #[['get, ['realm]], ['set, ['set_setting_realm]], ['parse, ['parse_realm_setting]], ['clear, ['clear_realm_setting]]]], ["darkness", #[['get, ['darkness]], ['set, ['set_darkness]], ['parse, ['is_type, 'integer]]]], ["restrict-entry", #[['get, ['get_restrict_entry]], ['set, ['set_restrict_entry]], ['parse, ['parse_restrict_entry]], ['format, ['format_restrict_entry]]]]]; catch any { dblog("__upgrade_handle_var(3, defined_settings)"); defined_settings = .__upgrade_handle_var(3, "$place<$root>,defined_settings", old, defined_settings, new); } with { dblog("ERROR: " + traceback()[1][2]); } }; object $place; eval { .__upgrade_set_var(); }; object $root; eval { del_method('__upgrade_set_var); }; // old public method $root.__upgrade_set_var(); add objvar Adding objvar $place<$place>,restrict_entry object $place; var $place restrict_entry = 0; new method Replacing public method $place.did_arrive() public method $place.did_arrive() { arg mover, place; pass(mover, place); .cache_client_init(); }; new method Adding public method $place.will_arrive() public method $place.will_arrive() { arg mover, old_place; (> pass(mover, old_place) <); if (restrict_entry && ((!(mover.is($path))) && ((mover != $housekeeper) && ((!(.trusts(mover))) && ((| (mover.location()) != this() |) && (!(restrict_entry.try(sender())))))))) throw(~locked, ((((.name()).capitalize()) + " is locked to ") + (restrict_entry.lock_name('place))) + "."); }; new method Adding root method $place.format_restrict_entry() root method $place.format_restrict_entry() { arg value; var unparse; unparse = value.unparse(); if (unparse == "yes") return "none"; else if (unparse == "no") return "by-entrances"; return unparse; }; new method Adding protected method $place.set_restrict_entry() protected method $place.set_restrict_entry() { arg name, definer, value; if (class(value) == $true_lock_frob) (| clear_var('restrict_entry) |); else restrict_entry = value; }; new method Adding public method $place.parse_restrict_entry() public method $place.parse_restrict_entry() { arg value; if (!value) throw(~invalid, "Restrict with 'by-entrances', 'none' or a lock frob"); if (value == "by-entrances") value = "no"; else if (value == "none") value = "yes"; return (> $lock_frob.parse(value, user() || this()) <); }; new method Replacing public method $place.attach_exit() public method $place.attach_exit() { arg type, exit; if (!(caller().is($path))) throw(~perm, "Caller is not an exit."); if (type == 'source) { (| (.realm()).add_exit_to(exit.dest()) |); exits = setadd(exits, exit); } else { entrances = setadd(entrances, exit); } }; new method Adding public method $place.get_restrict_entry() public method $place.get_restrict_entry() { arg name, definer; return restrict_entry || (<$true_lock_frob, []>); }; add objvar Adding objvar $nowhere<$event_handler>,hooked object $nowhere; var $event_handler hooked = #[]; new method Replacing public method $tutorial.did_leave() public method $tutorial.did_leave() { arg mover, new_place; pass(mover, new_place); if (!(new_place.is(parents()[1]))) (parents()[1]).user_left(sender()); }; new method Replacing public method $tutorial.did_arrive() public method $tutorial.did_arrive() { arg mover, old_place; pass(mover, old_place); (parents()[1]).track_user(sender(), old_place); }; new method Replacing public method $tutorial.will_arrive() public method $tutorial.will_arrive() { arg mover, old_place; pass(mover, old_place); if ((!((parents()[1]).is($tutorial))) || ((parents()[1]) == $tutorial)) throw(~perm, "Something is wrong with that tutorial topic, you cannot go there."); }; new method Replacing public method $tutorial.announce() public method $tutorial.announce() { arg str, @whonot; var p, msg; if ((!sender()) in (.contents())) return; if ((type(str) == 'frob) && ((class(str) == $message_frob) && (this() in (str.parts())))) { p = str.get_part(this()); str = str.change_entry(this(), "general"); } if ((!(sender() in whonot)) && (sender() in (.contents()))) (| sender().tell(str, sender()) |); switch (type(str)) { case 'string: (| sender().tell(("[ Everyone else would see: " + str) + " ]") |); case 'frob: msg = ($parse_lib.filter_ctext(str, #[['formatter, $plain_format]])).to_strings(); if (((msg.length()) == 2) && ((msg[2]) == `[])) { (| sender().tell(("[ Everyone else would see: " + (msg[1])) + " ]") |); } else { (| sender().tell("[-- Everyone else would see the following: --]") |); (| sender().tell(p) |); (| sender().tell("[-- End --]") |); } } }; new method Adding root method $tutorial.core_tutorial() root method $tutorial.core_tutorial() { if (tracking) tracking = 0; }; update objvar Updating objvar $introductory_tutorial<$tutorial>,tracking object $introductory_tutorial; var $tutorial tracking = 0; add objvar Adding objvar $introtut_desc<$event_handler>,hooked object $introtut_desc; var $event_handler hooked = #[]; update objvar Updating objvar $introtut_moving<$place>,entrances object $introtut_moving; var $place entrances = [$introtut_path1]; update objvar Updating objvar $introtut_moving<$place>,exits object $introtut_moving; var $place exits = [$introtut_path1]; add objvar Adding objvar $introtut_objs_env<$event_handler>,hooked object $introtut_objs_env; var $event_handler hooked = #[]; update objvar Updating objvar $introtut_moving_1<$place>,entrances object $introtut_moving_1; var $place entrances = [$introtut_path1, $introtut_path2]; update objvar Updating objvar $introtut_moving_1<$place>,exits object $introtut_moving_1; var $place exits = [$introtut_path1, $introtut_path2]; update objvar Updating objvar $introtut_moving_2<$place>,entrances object $introtut_moving_2; var $place entrances = [$introtut_path2]; update objvar Updating objvar $introtut_moving_2<$place>,exits object $introtut_moving_2; var $place exits = [$introtut_path2]; new method Replacing public method $antisocial.anti_cmd() public method $antisocial.anti_cmd() { arg cmdstr, cmd, @who; var message, vars, victim, m, s; (> .perms(caller(), 'command) <); s = sender(); vars = #[["$actor", s], ["actor", s.name()]]; if (who) vars = (vars.add("$who", who[1])).add("who", (who[1]).name()); (s.location()).announce(s.eval_message(cmd, definer(), vars)); }; add objvar Adding objvar $social<$foundation>,msgs object $social; var $foundation msgs = #[["bow", #[["actor", <$ctext_frob, [["You bow to ", <$generator, ["victim", [], [], 'gen_victim]>, "."], #[]]>], ["victim", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " bows to you."], #[]]>], ["general", <$ctext_frob, [[<$generator, ["actor", [], [], 'gen_actor]>, " bows to ", <$generator, ["victim", [], [], 'gen_victim]>, "."], #[]]>]]]]; add objvar Adding objvar $social<$command_cache>,commands object $social; var $command_cache commands = 0; add objvar Adding objvar $social<$foundation>,defined_msgs object $social; var $foundation defined_msgs = #[["bow", #[['branches, ["actor", "general", "victim"]]]]]; add objvar Adding objvar $social<$command_cache>,shortcuts object $social; var $command_cache shortcuts = 0; new method Replacing public method $social.social_cmd() public method $social.social_cmd() { arg cmdstr, cmd, @who; var vars, i, n, s; (> .perms(caller(), 'command) <); s = sender(); vars = #[["$actor", s], ["actor", s.name()]]; n = 0; for i in (who) { if ((| i.name() |)) { vars = (vars.add(n ? ("$victim_" + n) : "$victim", i)).add(n ? ("victim_" + n) : "victim", i.name()); n++; } } (s.location()).announce(.eval_message(cmd, $social, vars)); }; add objvar Adding objvar $connection<$connection>,debugees object $connection; var $connection debugees = 0; new method Replacing public method $connection.change_interface() public method $connection.change_interface() { arg new; var old; (> .perms(sender()) <); (> .perms(caller(), $login_interface) <); if (interface) { old = interface; old.connection_going_away(.address(), remote_port); } interface = new; (.manager()).change_connection_interface(old, new); interface.connection_starting(.address(), remote_port); }; new method Replacing public method $connection.write() public method $connection.write() { arg what, @how; var elem, sep; sep = ('non_terminated in how) ? `[] : `[13, 10]; switch (type(what)) { case 'string: what = strings_to_buf([what], sep); case 'list: what = strings_to_buf(what, sep); case 'buffer: default: throw(~type, "Write: strings, list of strings and buffers."); } cwrite(what); }; new method Replacing public method $login_connection.local_echo_on() public method $login_connection.local_echo_on() { (sender() == (.interface())) || (> .perms(sender()) <); cwrite(`[255, 252, 1]); }; new method Replacing public method $login_connection.local_echo_off() public method $login_connection.local_echo_off() { (sender() == (.interface())) || (> .perms(sender()) <); cwrite(`[255, 251, 1]); }; new method Replacing public method $smtp.parse_maildrop_setting() public method $smtp.parse_maildrop_setting() { arg value, @args; var name, ip; [(name ?= ""), (ip ?= "")] = explode(value, "/"); if (!ip) { if (!name) name = "localhost"; ip = (> $dns.ip(name) <); } else { (> $dns.hostname(ip) <); } return ip; }; method access Changing method $smtp.set_maildrop_setting() access from public to protected object $smtp; eval { var l; dblog("set_method_access('set_maildrop_setting, 'protected"); catch any { set_method_access('set_maildrop_setting, 'protected); } with { for l in ($parse_lib.traceback(traceback())) dblog(l); } }; new method Replacing public method $daemon.start_listening() public method $daemon.start_listening() { arg @ports; var p, last, l; (> .perms(sender()) <); (| .stop_listening() |); ports ?= listen; current_ports = []; for p in (ports) { catch any { last = p; bind_port(@p); current_ports += [p]; $sys.slog((("** Starting " + this()) + " on ") + (.format_listen([p], 1))); } with { p = (p.reverse()).join(":"); $sys.slog((("** Unable to bind " + this()) + " to ") + p); if (error() != ~bind) $sys.log_traceback(traceback(), (("LISTEN: " + this()) + " ") + p); } } if (!current_ports) throw(~daemon, ("** " + this()) + " NOT LISTENING **"); next_connection = connection.new_connection(); }; new method Replacing public method $daemon.startup(): forked public method $daemon.startup(): forked { arg @args; var match, port, rx, str, o, ports, msg; (> .perms(caller(), 'system) <); rx = tostr(.objname()); rx = ("-(p)" + substr(rx, 1, ("_" in rx) - 1)) + "=(.*)"; if (find str in (args) where ((match = regexp(str, rx)))) { [o, ports] = match; ports = .parse_port(ports); if (strcmp(o, "p") == 0) ports = listen + [ports]; } else { ports = listen; } (> .start_listening(@ports) <); }; update objvar Updating objvar $smtp_daemon<$smtp_daemon>,msg_id object $smtp_daemon; var $smtp_daemon msg_id = 310; new method Replacing protected method $thing_frob.change_data() protected method $thing_frob.change_data() { arg this, what, new, @remove; var l; l = this['location]; if (valid(l)) { if ((<this(), this>) in (l.contents())) (this['location]).del_frob_from_contents((<this(), this>)); // else if (what != 'location) // throw(~perm, "Bogus location information in frob."); } if (remove) this = this.del(what); else this = this.add(what, new); if (valid(this['location])) (this['location]).add_frob_to_contents((<this(), this>)); return (<this(), this>); }; new method Replacing public method $coord_exit.configure() public method $coord_exit.configure() { arg set; var s, radial, azimuth, distance, ans, c, dist, m; set = (> pass(set) <); if (set.contains('exit_coordinates)) return set; s = sender(); if (!(| s.get_setting("experienced", $user) |)) s.tell($place_lib.build_hint(5)); while (1) { ans = s.prompt(((("Exit coordinates for " + (.name())) + " (to ") + ((.dest()).name())) + ") "); if (ans == "@skip") return set; if (ans == "@shortcuts") { s.tell(["-- Coordinate Shortcuts:", map c in ($place_lib.coordinate_shortcuts()) to (strfmt(" %20l %7l %s", c[1], @c[2]))]); continue; } if (!ans) { s.tell("Invalid Coordinates."); continue; } catch ~coordnf, ~invcoord { if (ans.is_numeric()) { ans = ans.explode_english_list(); if ((ans.length()) != 2) { s.tell("Seperate coordinates with a comma."); continue; } if ((!((ans[1]).is_numeric())) || (!((ans[2]).is_numeric()))) { s.tell("Invalid coordinates."); continue; } if ((!((ans[1]).is_numeric())) || (!((ans[2]).is_numeric()))) { s.tell("Invalid coordinates."); continue; } radial = toint(ans[1]); azimuth = toint(ans[2]); } else { ans = $place_lib.coordinates(ans); radial = ans[1]; azimuth = ans[2]; } (> $place_lib.valid_coordinates(radial, azimuth) <); } with { s.tell((traceback()[1])[2]); continue; } } while (!dist) { ans = s.prompt(("Distance from center of room (metric) [" + ($place_lib.get_default('distance))) + "] "); if (!ans) dist = $place_lib.get_default('distance); else if (ans == "@skip") return set; else if ((m = match_regexp(ans, "^ *([0-9]+) *M *$"))) dist = toint(m[1]) * 100; else if ((m = match_regexp(ans, "^ *([0-9]+) *C?M? *$"))) dist = toint(m[1]); else s.tell("Distance must be either centimeters (cm) or meters (m)."); } coordinates = [radial, azimuth, dist]; return set.add('exit_coordinates); }; new method Replacing frob method $xor.unparse() frob method $xor.unparse() { arg xorlist; var str, x; str = ""; for x in (xorlist) { catch any str = (str + (x.unparse())) + " XOR "; with str = (str + tostr(x)) + " XOR "; } return ("(" + (str && (str.subrange(1, (str.length()) - 4)))) + ")"; }; new method Replacing frob method $and.unparse() frob method $and.unparse() { arg andlist; var str, x; str = ""; for x in (andlist) { catch any str += (x.unparse()) + " AND "; with str += x + " AND "; } return ("(" + (str && substr(str, 1, strlen(str) - 4))) + ")"; }; new method Replacing public method $lock_frob.parse() public method $lock_frob.parse() { arg s, who; var stack, lock, n, m, obj, type, i; stack = []; s = " " + s; s = strsed(s, "&([^&])", "&&%1", "g"); s = strsed(s, "\|([^\|])", "||%1", "g"); s = strsub(s, " or ", " || "); s = strsub(s, " and ", " && "); s = strsub(s, " not ", " !"); s = strsub(s, " xor ", " ^^"); while (1) { // Look for valid prefixes. while (1) { (s = s.trim()) || throw(~parse, "String ends unexpectedly."); if ((s[1]) == "(") { stack = ['open, @stack]; s = s.subrange(2); } else if ((s[1]) == "!") { if (stack && ((stack[1]) == 'not)) stack = stack.subrange(2); else stack = ['not, @stack]; s = s.subrange(2); } else { break; } } // Look for an object name or tag m = regexp(s, "^([^)&|]+)(.*)"); if (!m) throw(~parse, "Null object obj_name."); s = m[2]; lock = (m[1]).trim(); if (!lock) throw(~parse, "Null object obj_name."); // try and match it type = $object_lock_frob; for i in (lock_types) { if (lock.match_begin((i[1]) + ":")) { type = i[2]; lock = lock.subrange(((i[1]).length()) + 2); break; } } switch (lock) { case "any", "true", "anybody", "yes": lock = $true_lock_frob.new(); case "none", "false", "nobody", "no": lock = $false_lock_frob.new(); default: if ((obj = (| who.match_environment(lock) |))) lock = type.new_lock(obj); else throw(~parse, ("Invalid lock tag \"" + lock) + "\""); } stack = [lock, @stack]; // Loop until no more reduction to be done. while (1) { // Process negations, ands, ors. while (1) { if ((stack.length()) < 2) break; if ((stack[2]) == 'not) stack = [$not_lock_frob.new_lock(stack[1]), @stack.subrange(3)]; else if ((stack[2]) == 'and) stack = [$and_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)]; else if ((stack[2]) == 'or) stack = [$or_lock_frob.new_lock(stack[1], stack[3]), @stack.subrange(4)]; else break; } // Close parens, if necessary; otherwise stop. if ((!s) || ((s[1]) != ")")) break; while (s && ((s[1]) == ")")) { if (((stack.length()) < 2) || ((stack[2]) != 'open)) throw(~parse, "Misplaced right parenthesis."); stack = [stack[1], @stack.subrange(3)]; s = (s.subrange(2)).trim(); } } // Are we done? if (!s) { if ((stack.length()) > 1) throw(~parse, "Unmatched left parentheses."); return stack[1]; } // No, we're at a conjunction. if ((s[1]) == "&") { stack = ['and, @stack]; s = s.subrange(3); } else if ((s[1]) == "|") { stack = ['or, @stack]; s = s.subrange(3); } else { throw(~parse, "Illegal character following right parenthesis."); } } }; new method Adding public method $carry_lock_frob.unparse() public method $carry_lock_frob.unparse() { arg rep; return "carry:" + (rep[1]); }; new method Replacing frob method $not.unparse() frob method $not.unparse() { arg notlist; catch any { catch ~type, ~methodnf return "NOT " + ((notlist[1]).unparse()); with return "NOT " + tostr(notlist[1]); } with { return ""; } }; new method Replacing frob method $or.unparse() frob method $or.unparse() { arg orlist; var str, x; str = ""; for x in (orlist) { catch any str += (x.unparse()) + " OR "; with str += x + " OR "; } return ("(" + (str && substr(str, 1, strlen(str) - 4))) + ")"; }; new method Replacing public method $climate_frob.read_new() public method $climate_frob.read_new() { arg user; var attrs, seasons, i; attrs = user.prompt("Weather attribute names (default:visibility severity):"); if (attrs == "@abort") throw(~abort, "User aborted."); if (type(attrs) == 'symbol) throw(~engaged, "Already reading."); attrs = attrs || "visibility severity"; attrs = (attrs.explode()).mmap('to_symbol); seasons = user.prompt("Season list (default:winter spring summer fall):"); if (type(seasons) == 'symbol) throw(~engaged, "Already reading."); seasons = seasons || "winter spring summer fall"; seasons = (seasons.explode()).mmap('to_symbol); return .new_with(attrs, seasons); }; new method Replacing public method $climate_frob.read_weather() public method $climate_frob.read_weather() { arg self, user, weather; var attrs, probs, message, ch_messages, i; attrs = user.prompt("Attributes:"); if (((self[1]).length()) != ((attrs = attrs.explode_quoted()).length())) throw(~parse, "Wrong number of attributes"); attrs = map i in (attrs) to ((tostr(toint(i)) == i) ? toint(i) : i); probs = user.prompt("Seasonal probabilities [0-99]:"); if (((self[2]).length()) != ((probs = probs.explode()).length())) throw(~parse, "Wrong number of attributes"); probs = map i in (probs) to (toint(i)); message = user.prompt("Weather description:"); (> (message = $compiler.compile_cml(message)) <); ch_messages = user.read("Enter messages to be displayed during the change ('.' to finish)"); if (type(ch_messages) == 'symbol) throw(~stop, ""); (> (ch_messages = map i in (ch_messages) to ($compiler.compile_cml(i))) <); return .add_weather(self, weather, attrs, probs, message, ch_messages); }; new method Adding public method $connection_interface.log_traceback() public method $connection_interface.log_traceback() { arg @args; return $sys.log_traceback(@args); }; new method Replacing public method $connection_interface.parse_line() public method $connection_interface.parse_line() { arg line; var cmd, c, match, parsed, i, m, a, u; catch any { line = line.trim(); if (!line) { return .null_cmd(line); } else { cmd = line.explode(); cmd = [line, cmd[1], ((cmd.subrange(2)).join()) || ""]; c = (| .match_in_local_cache(@cmd) |); if (c && ((c[1]) == 'local)) { // screw duplicates, take the first match match = (c[2])[1]; m = match[2]; i = match[5]; parsed = i.keys(); for a in [1 .. m.length()] { if (a in parsed) m = m.replace(a + 2, (> $command_lib.convert_arg((i[a])[1], m[a + 2], $no_one, ((i[a])[2]) ? (((i[a])[2])[1]) : $no_one, $no_one) <)); } return (> .(match[4])(@m) <); } return (> .invalid_cmd(line) <); } } with { if (((traceback()[1])[3]) != 'no_traceback) { (this['connection]).write($parse_lib.traceback(traceback())); return 'disconnect; } } }; new method Replacing public method $connection_interface.set_connection() public method $connection_interface.set_connection() { arg c; if (caller() != definer()) (> .perms(sender()) <); connection = c; }; new method Replacing public method $connection_interface.write() public method $connection_interface.write() { arg what; return connection.write(what); }; new method Replacing protected method $login_interface.motd() protected method $login_interface.motd() { var out; // out = $motd.build('default) + ["", " ** Use 'H?elp' for a list of commands **".center(79), ""]; out = $motd.build(@$motd.get_setting("login-sequence", $motd)); return out; }; new method Replacing protected method $login_interface.create_cmd() protected method $login_interface.create_cmd() { arg cmdstr, cmd, args; var syn, msg, user, semail, len, name, pwd, email, result; if (!($login_daemon.get_setting("creation-allowed", $login_daemon))) return (> .tell_error("", $login_daemon.get_setting("creation-disabled-msg", $login_daemon)) <); syn = cmd + " <name> <password> <email@host>"; semail = $smtp.get_email_address('login); args = args.explode_quoted(); if ((args.length()) < 3) (> .tell_error(syn) <); if ((args.length()) > 3) { len = listlen(args); args = [sublist(args, 1, len - 2).join(), args[len - 1], args[len]]; } [name, pwd, email] = args; if ((| $user_db.search(name) |)) (> .tell_error(syn, ("The name '" + name) + "' is already taken.") <); if ($sys.validate_email_addresses()) { catch any { .print("Verifying Email Address.."); msg = $smtp.verify_email_address(email); .print("SMTP Response: " + (msg.join(" "))); } with { .print("Aborting: " + ((traceback()[1])[2])); return; } } catch any { user = $sys.create_user(name, pwd, email); } with { if (user) (| user.destroy() |); .log_traceback(traceback(), "LOGIN: " + cmdstr); msg = ["There was a problem creating you:"]; //// Too verbose. // msg += $parse_lib.traceback(traceback()); // msg += ["If there is a problem contact: " + semail]; (> .tell_error(syn, (msg + [" " + ((traceback()[1])[2])]).prefix("! ")) <); return; } (.connection()).change_interface(user); }; new method Replacing public method $http_interface.process_auth_info() public method $http_interface.process_auth_info() { arg str; var user, pwd; str = str.explode(); switch (str[1]) { case "Basic": [(user ?= ""), (pwd ?= "")] = ((str[2]).decode64()).explode(":"); .set_info('browser_auth, ['basic, [user, pwd]]); default: $sys.log("$security_db: Unknown authorization type '" + (str[1])); .set_info('browser_auth, ['unknown, str]); } }; add objvar Adding objvar $smtp_interface<$root>,trusted_by object $smtp_interface; var $root trusted_by = [$no_one]; new method Replacing public method $smtp_interface.send_mail() public method $smtp_interface.send_mail() { var l, subj, from; .set_name(mail_from, 'prop); subj = "<NO SUBJECT>"; for l in (header) { if ((l[1]) == "Subject") subj = l[2]; if ((l[1]) == "From") from = l[2]; } from ?= mail_from; catch any { $no_one.mail_as(from, header, subj, mail_body, @mail_to); (.connection()).write(("250 " + ($smtp_daemon.get_msg_id())) + " Message accepted for delivery"); } with { .log_traceback(traceback(), "SMTP: DATA"); (.connection()).write("550 Requested action not taken: Error delivering mail"); } .reset_interface(); }; update objvar Updating objvar $introtut_user_graffiti<$described>,prose object $introtut_user_graffiti; var $described prose = <$ctext_frob, [["This is a list of descriptions from people around ", <$generator, ["server_name", [], [], 'gen_servername]>, ". It is randomly sampled, and if you look at it again it will represent different descriptions."], #[]]>; old method Deleting normal method $introtut_user_graffiti.prose() object $introtut_user_graffiti; eval { del_method('prose); }; new method Adding public method $introtut_user_graffiti.set_users() public method $introtut_user_graffiti.set_users() { arg list; // specify a list of objects which have good descriptions for users, to // be used as examples. If this list exists then the descriptions will // not be randomly selected. If it is zero-length, they will be. (> .perms(sender()) <); users = list; }; new method Adding public method $introtut_user_graffiti.users() public method $introtut_user_graffiti.users() { return users; }; new method Replacing public method $introtut_user_graffiti.description() public method $introtut_user_graffiti.description() { arg flags; var p, i, lines, d, u, brake; p = $ctext_frob.new_with([$cml_lib.format_hr_tag()]); lines = []; if (users) { u = users; } else { u = []; d = ($user_db.database()).to_dict(); brake = 0; while ((listlen(u) < 4) && (brake++ < 20)) { i = dict_keys(d).random(); if (((d[i]).prose()) != "You see nothing special") { u += [d[i]]; d = dict_del(d, i); } } } for i in (u) lines += [p, i.prose()]; return (> pass(flags) <) + lines; }; update objvar Updating objvar $user_db<$root>,flags object $user_db; var $root flags = ['methods, 'code, 'core]; new method Replacing public method $user_db.connected() public method $user_db.connected() { var x; for x in (connected) { if ((!valid(x)) || (| !(x.connections()) |)) connected = setremove(connected, x); } return connected; }; new method Replacing public method $user_db.clean_user_db() public method $user_db.clean_user_db() { var key, db, invalid; db = (.database()).to_dict(); invalid = []; if (0) { // broken, not sure why, something is corrupting the trie --Brandon for key in (dict_keys(db)) { if (!valid(db[key])) { .remove(key); connected = setremove(connected, db[key]); invalid += [key]; } } } else { for key in (dict_keys(db)) { if (!valid(db[key])) { connected = setremove(connected, db[key]); db = dict_del(db, key); invalid += [key]; } } .set_database(db.to_trie()); } return ["Invalid $user_db entries: " + (invalid.to_english())]; }; update objvar Updating objvar $help_interface_format<$help_node>,body object $help_interface_format; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "By default your output format is plaintext (text/plain). You can change this to other formats by setting your Content-Type. Currently supported alternate types are:", <$format, ["p", [], [], 'do_p]>, <$format, ["ul", [], [<$format, ["li", [], ["Plain Text (text/plain)"], 'do_li]>, <$format, ["li", [], ["ANSI Text (text/ansi)"], 'do_li]>, <$format, ["li", [], ["HTML Text (text/html)"], 'do_li]>, <$format, ["li", [], ["Pueblo Browser Text (text/pueblo)"], 'do_li]>, <$format, ["li", [], ["TkMoo Text (text/tkmoo)"], 'do_li]>, <$format, ["li", [], ["Wrapped Text (text/wrapped)"], 'do_li]>], 'do_ul]>, <$format, ["np", [], [], 'do_np]>, "These formats can easilly be extended to include others. To change your output format use the command:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["@set content-type=type"], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "Where ", <$format, ["i", [], ["type"], 'do_i]>, " is one of the MIME encodings of the above types ie: text/plain. Use text/wrapped if your client doesn't wrap text automaticly."], #[]]>; chpar Changing parents for $help_theme [$help_building] => [$help_coldcore] object $help_theme: $help_coldcore; update objvar Updating objvar $help_places_realms<$help_node>,links object $help_places_realms; var $help_node links = #[["@spawn", $help_cmd_spawn], ["setting", $help_interface_settings], ["@def-setting", $help_cmd_defsetting]]; update objvar Updating objvar $help_places_realms<$help_node>,body object $help_places_realms; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "Realms are used to group places, and can exist in a heirarchy structure. For instance, all rooms within a building would exist within one realm for that building, and that realm would exist within a realm for that sector of the city, which exists within a realm for the entire city. Realms are useful not only for grouping, but also for events and searching. When an event occurs it can be broadcast to the entire realm, rather than just to the local room. ", <$format, ["np", [], [], 'do_np]>, "New realms are created with the command ", <$format, ["link", [["node", "$help_cmd_spawn"]], ["@spawn"], 'do_link]>, ", such as:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["@spawn $realm named the Clocktower"], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "When creating a realm make sure to create it from the right parent, so as to keep the heirarchy intact. For instance, the above realm might be better spawned from a realm for the city. ", <$format, ["np", [], [], 'do_np]>, "Realms keep track of all the rooms they contain. When room is created or destroyed, its realm is updated accordingly. You can change the room's realm using its :realm ", <$format, ["link", [["node", "$help_interface_settings"]], ["setting"], 'do_link]>, ". ", <$format, ["np", [], [], 'do_np]>, "Realms also keep track of realm properties. You can add your own realm property as you would add any other setting, but make sure that +get method is set to get_realm_setting (read ", <$format, ["link", [["node", "$help_cmd_defsetting"]], ["@def-setting"], 'do_link]>, " helpnode for information about this). Realm properties have special inheritance scheme: rooms inherit them from their realm, and realms inherit it from their parents. There are two default realm properties: propagate, which controls propagation mask from the parent realm, and weather-time, which sets the weather and time for the realm. ", <$format, ["np", [], [], 'do_np]>, "You can announce a message to all the players in a realm using realm_announce method on the realm object. Note that it will be propagated using the propagation masks."], #[['links, #[["@spawn", "$help_cmd_spawn"], ["setting", "$help_interface_settings"], ["@def-setting", "$help_cmd_defsetting"]]]]]>; update objvar Updating objvar $help_coldc_types_ints<$help_node>,body object $help_coldc_types_ints; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "An ", <$format, ["i", [], ["integer"], 'do_i]>, " is a rational number (in mathematical terms). Integers can reliably be from 2147483647 to -2147483647 (unless the driver has been compiled with BIG_NUMBERS, in which case they are larger). An integer is logically true if it is not zero (negative numbers are logically true). Integers are denoted in ColdC with a series of digits, optionally preceded with a plus (", <$format, ["tt", [], ["+"], 'do_tt]>, ") or minus (", <$format, ["tt", [], ["-"], 'do_tt]>, ") sign. ", <$format, ["np", [], [], 'do_np]>, "See also: ", <$format, ["link", [["node", "$help_funcs_num"]], ["Numeric Functions"], 'do_link]>], #[['links, #[["Numeric Functions", "$help_funcs_num"]]]]]>; update objvar Updating objvar $help_func_anticipate_assignment<$help_node>,links object $help_func_anticipate_assignment; var $help_node links = #[["Errors", $help_coldc_errors]]; update objvar Updating objvar $help_func_anticipate_assignment<$help_node>,body object $help_func_anticipate_assignment; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["INTEGER"], 'do_i]>, " anticipate_assignment()"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "Do not use this unless you know exactly what you are doing, and how stacks and frames work in the ColdC driver. ", <$format, ["np", [], [], 'do_np]>, "This function is used to reduce the amount of references to data on the stack, in order to keep from unecessarily copying data. It does this by breaking encapsulation and looking at the calling frame's execution stack. If an assignment will be made to data passed as an argument, as a result of the current method's return--the variable is cleared of any references before the data is modified in the current frame. ", <$format, ["np", [], [], 'do_np]>, "Because of how this works be careful to only call anticipate_assignment() after any ", <$format, ["link", [["node", "$help_coldc_errors"]], ["Errors"], 'do_link]>, " are thrown. Any errors thrown after this function is called will have the potential of losing data in the calling method."], #[['links, #[["Errors", "$help_coldc_errors"]]]]]>; update objvar Updating objvar $help_func_fread<$help_node>,body object $help_func_fread; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["STRING|BUFFER"], 'do_i]>, " fread([", <$format, ["i", [], ["INTEGER block"], 'do_i]>, "])"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "Read from the existing file bound to this object. If the file is a binary file, a buffer is returned. If the file is a text file (default), a string is returned. If the file is at the end, the ", <$format, ["tt", [], ["~eof"], 'do_tt]>, " error is thrown. With binary files an optional block size may be specified. The default block size is 512 characters. Example: ", <$format, ["dfn", [], [<$format, ["quote", [], ["\n catch ~eof {\n while (1) {\n line = fread();\n .tell(line);\n }\n }\n"], 'do_quote]>], 'do_dfn]>], #[]]>; update objvar Updating objvar $help_func_buf_to_str<$help_node>,body object $help_func_buf_to_str; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["BUFFER"], 'do_i]>, " buf_to_str(", <$format, ["i", [], ["BUFFER buf"], 'do_i]>, "[, ", <$format, ["i", [], ["BUFFER sep"], 'do_i]>, "])"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function converts the buffer specified by buf to a list of printable strings, with a final buffer element. Each string is a line in the buffer, terminated by a newline. If any characters remain unterminated, they are placed in the last element as a buffer. The last element will always be a buffer, regarless of whether any characters are in it. ", <$format, ["np", [], [], 'do_np]>, "buf_to_strings() will alternatively split the strings based off the optional second argument. Note: it is not necessary to specify both a carriage return and a newline as the seperator--if both exist--as the newline will be sufficient to break the string, and the carriage return will be discarded as an unprintable character in the string."], #[]]>; update objvar Updating objvar $help_func_buf_to_strings<$help_node>,body object $help_func_buf_to_strings; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["LIST"], 'do_i]>, " buf_to_strings(", <$format, ["i", [], ["BUFFER buf"], 'do_i]>, "[, ", <$format, ["i", [], ["BUFFER sep"], 'do_i]>, "])"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function converts the buffer specified by ", <$format, ["i", [], ["buf"], 'do_i]>, " to a list of printable strings, with a final buffer element. Each string is a line in the buffer, terminated by a newline. If any characters remain unterminated, they are placed in the last element as a buffer. The last element will always be a buffer, regardless of whether any characters are in it. ", <$format, ["np", [], [], 'do_np]>, <$format, ["tt", [], ["buf_to_strings()"], 'do_tt]>, " will alternatively split the strings based off the optional second argument. Note: it is not necessary to specify both a carriage return and a newline as the separator--if both exist--as the newline will be sufficient to break the string, and the carriage return will be discarded as an unprintable character in the string."], #[]]>; update objvar Updating objvar $help_func_dict_union<$help_node>,body object $help_func_dict_union; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["DICTIONARY"], 'do_i]>, " dict_union(", <$format, ["i", [], ["DICTIONARY dict1"], 'do_i]>, ", ", <$format, ["i", [], ["DICTIONARY dict2"], 'do_i]>, ")"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function merges the two dictionaries by adding each association from ", <$format, ["i", [], ["dict2"], 'do_i]>, " into ", <$format, ["i", [], ["dict1"], 'do_i]>, ". In the case of conflicts, the values in ", <$format, ["i", [], ["dict2"], 'do_i]>, " take precedence. Example:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["dict_union(#[[\"foo\", 1], ['baz, 3]], #[[\"foo\", 2], [\"bar\", 2]])", <$format, ["br", [], [], 'do_br]>, "=> #[[\"foo\", 2], ['baz, 3], [\"bar\", 2]]"], 'do_dfn]>], #[]]>; update objvar Updating objvar $help_func_crypt<$help_node>,body object $help_func_crypt; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["STRING"], 'do_i]>, " crypt(", <$format, ["i", [], ["STRING str"], 'do_i]>, "[, ", <$format, ["i", [], ["STRING salt"], 'do_i]>, "])"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function performs one-way encryption on ", <$format, ["i", [], ["str"], 'do_i]>, ", using the SHA encryption routine. If ", <$format, ["i", [], ["salt"], 'do_i]>, " is not specified, it is chosen randomly. The return value of ", <$format, ["tt", [], ["crypt()"], 'do_tt]>, " is the encrypted string. ", <$format, ["np", [], [], 'do_np]>, "The encryption performed by this function has the property that it is very difficult to find a string which will produce a given result; however, a given string and a given salt will always yield the same encrypted string. Example:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["crypt(\"foo\", \"ab\")", <$format, ["br", [], [], 'do_br]>, "=> \"$2$ab$TmSIW.xT3sTkwqUhTLxCH192J37\""], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "When matching an encrypted string versus a non-encrypted string, the function ", <$format, ["link", [["node", "$help_func_match_crypted"]], ["match_crypted()"], 'do_link]>, " should be used, as it will take into consideration any possible future changes to the crypt() implementation."], #[['links, #[["match_crypted()", "$help_func_match_crypted"]]]]]>; update objvar Updating objvar $help_func_strsed<$help_node>,body object $help_func_strsed; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["STR"], 'do_i]>, " strsed(", <$format, ["i", [], ["STR rx"], 'do_i]>, ", ", <$format, ["i", [], ["STR str"], 'do_i]>, ", ", <$format, ["i", [], ["STR replace"], 'do_i]>, "[, ", <$format, ["i", [], ["STR flags"], 'do_i]>, "[, ", <$format, ["i", [], ["INT count"], 'do_i]>, "]])"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This functions similar ", <$format, ["tt", [], ["sed"], 'do_tt]>, " in many unix systems. It searches for any occurances of ", <$format, ["i", [], ["regexp"], 'do_i]>, " in ", <$format, ["i", [], ["string"], 'do_i]>, " and replaces them with ", <$format, ["i", [], ["replace"], 'do_i]>, ", returning the result. The optional fourth argument is used to specify flags for sed. Flags are specified as a string containing any of the following alphabetic characters: ", <$format, ["dfn", [["nobound", 1], [" ", 1], ["ind", "4"]], [<$format, ["table", [["cols", "5%,95%"]], [<$format, ["tr", [], [<$format, ["td", [], [<$format, ["b", [], ["g"], 'do_b]>], 'do_td]>, <$format, ["td", [], ["Match the regular expression globally througout the string"], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["b", [], ["s"], 'do_b]>, "*"], 'do_td]>, <$format, ["td", [], ["Single match--Match the first occurance only (default)"], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["b", [], ["c"], 'do_b]>], 'do_td]>, <$format, ["td", [], ["Case matters when matching"], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["b", [], ["i"], 'do_b]>, "*"], 'do_td]>, <$format, ["td", [], ["Case doesn't matter when matching (default)"], 'do_td]>], 'do_tr]>], 'do_table]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "Flags followed by an asterisk (*) represent default behaviour if no flags are specified. For more information, see the section on ", <$format, ["link", [["node", "$help_coldc_regexp"]], ["Regular Expressions"], 'do_link]>, ". ", <$format, ["np", [], [], 'do_np]>, "Examples:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["strsed(\"foObar\", \"o+\", \"X\")", <$format, ["br", [], [], 'do_br]>, "=> \"fXbar\" ", <$format, ["np", [], [], 'do_np]>, "strsed(\"foObar\", \"o+\", \"X\", \"c\")", <$format, ["br", [], [], 'do_br]>, "=> \"fXObar\""], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "The string ranges matched by the regular expression n the first string may be re-inserted into the resulting string by using '%n' tokens, where n represents the branch, from one to nine. This currently only works with branched regular expressions. Future revisions will expand upon this functionality. ", <$format, ["np", [], [], 'do_np]>, "Example:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["strsed(\"foObar\", \"(o+)\", \"<%1>\")", <$format, ["br", [], [], 'do_br]>, "=> \"fXbar\" ", <$format, ["np", [], [], 'do_np]>, "strsed(\"foObar\", \"(o+)\", \"<%1>\", \"c\")", <$format, ["br", [], [], 'do_br]>, "=> \"fXObar\""], 'do_dfn]>, " ", <$format, ["np", [], [], 'do_np]>, "The fifth argument ", <$format, ["i", [], ["count"], 'do_i]>, " is intended to optimize the use of this function, and is generally not used. It is simply an optimizing guideline which specifies how many expected occurances of the regular expression are expected in the string. This value is used when computing the initial size of the resulting string, to lower the amount of memory allocations which may have to be performed."], #[['links, #[["Regular Expressions", "$help_coldc_regexp"]]]]]>; update objvar Updating objvar $help_func_math<$help_node>,body object $help_func_math; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["FLOAT"], 'do_i]>, " sin(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " exp(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " log(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " cos(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " tan(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " sqrt(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " asin(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " acos(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " atan(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " pow(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ", ", <$format, ["i", [], ["FLOAT y"], 'do_i]>, ")", <$format, ["br", [], [], 'do_br]>, <$format, ["i", [], ["FLOAT"], 'do_i]>, " atan2(", <$format, ["i", [], ["FLOAT x"], 'do_i]>, ", ", <$format, ["i", [], ["FLOAT y"], 'do_i]>, ")"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "These functions perform the relevant mathematic function on the argument(s) and returns the result. Further information on each function can be found in the unix man page on the same relative function, in C. The precision of the function may vary by the implementation. If a floating point exception occurs, the error ~fpe is thrown."], #[]]>; update objvar Updating objvar $help_func_max<$help_node>,body object $help_func_max; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["ANY"], 'do_i]>, " max(", <$format, ["i", [], ["ANY arg"], 'do_i]>, ", ", <$format, ["i", [], ["..."], 'do_i]>, ")"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function returns the maximum of its arguments. All of the arguments must be of the same type, and must be integers, floats, or strings.", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["max(3, 7, 9, 5)", <$format, ["br", [], [], 'do_br]>, "=> 9"], 'do_dfn]>, " ", <$format, ["dfn", [], ["max(\"Foo\", \"aardvark\", \"bar\", \"Quux\")", <$format, ["br", [], [], 'do_br]>, "=> \"Quux\""], 'do_dfn]>], #[]]>; update objvar Updating objvar $help_func_min<$help_node>,body object $help_func_min; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], [<$format, ["tt", [], [<$format, ["i", [], ["ANY"], 'do_i]>, " min(", <$format, ["i", [], ["ANY arg"], 'do_i]>, ", ", <$format, ["i", [], ["..."], 'do_i]>, ")"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This function returns the minimum of its arguments. All of the arguments must be of the same type, and must be integers, floats, or strings.", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["min(3, 7, 9, 5)", <$format, ["br", [], [], 'do_br]>, "=> 3"], 'do_dfn]>, " ", <$format, ["dfn", [], ["min(\"Foo\", \"aardvark\", \"bar\", \"Quux\")", <$format, ["br", [], [], 'do_br]>, "=> \"aardvark\""], 'do_dfn]>], #[]]>; update objvar Updating objvar $help_cmd_eval<$help_node>,links object $help_cmd_eval; var $help_node links = #[]; update objvar Updating objvar $help_cmd_eval<$help_node>,body object $help_cmd_eval; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, <$format, ["b", [], ["PROGRAMMER COMMAND"], 'do_b]>, <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["Syntax: ", <$format, ["tt", [], ["@eval [<code>]"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This command is a powerful tool given to programmers. Its primary function is to allow programmers to execute ColdC code without actually programming it as a method. Anything specified in <code> is compiled and executed immediately. Furthermore, it also provides profiling and debugging tools, and an alternate feature that will show the interpreter opcodes it becomes, rather than executing it. ", <$format, ["np", [], [], 'do_np]>, "The shortcut ", <$format, ["tt", [], [";"], 'do_tt]>, " can also be used in place of ", <$format, ["tt", [], ["@eval"], 'do_tt]>, ". ", <$format, ["np", [], [], 'do_np]>, <$format, ["b", [], ["Example:"], 'do_b]>, " ", <$format, ["dfn", [], [<$format, ["quote", [], [">; .location().announce(\"Testing.\")\nTesting.\n=> $courtyard (the Courtyard)\n[ seconds: 1.1022141; operations: 1506 (1506 ticks per second) ]\n"], 'do_quote]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "In this example, the .location() gives us the object name of where we currently are ($courtyard). The .announce() says that this location should announce to all the players in this location our message (\"Testing.\"). If the code executes correctly, our message is displayed to everybody, and the @eval command returns the result of the expression, as well as the amount of time, operations, and ticks per second it took to perform the execution. Note: when measuring performance, the actual time it takes to execute is more important than the number of operations (because this is an interpreted language, different operations can be faster than the others, so the actual count is not a true representation of performance). ", <$format, ["subj", [["level", "2"]], ["Execution Environment"], 'do_subj]>, <$format, ["p", [], [], 'do_p]>, "By default, @eval will assume the code you are specifying is an expression, and will prefix it with '", <$format, ["tt", [], ["return"], 'do_tt]>, "', so the value of the expression is returned. This is a problem if your code is a statement, instead of an expression (such as a looping statement). To avoid this you can define variables, or include 'return' in your code where it should be--and @eval will not prefix it. ", <$format, ["np", [], [], 'do_np]>, "Furthermore, @eval defines a set of variables which can be used by the ColdC code. These are: ", <$format, ["tt", [], ["me"], 'do_tt]>, " and ", <$format, ["tt", [], ["here"], 'do_tt]>, ", representing your own object and your current location, respectively. ", <$format, ["subj", [["level", "2"]], ["Environment Substitution"], 'do_subj]>, <$format, ["p", [], [], 'do_p]>, "Anywhere within the ColdC code (other than inside strings) you can use the carat character (", <$format, ["tt", [], ["^"], 'do_tt]>, ") followed by a string token of alphanumeric characters. If @eval finds this, it will try to match the token as a name against objects in your environment. If a match is found it will replace that token with the dbref for that object. ", <$format, ["subj", [["level", "2"]], ["Execution Flags"], 'do_subj]>, <$format, ["p", [], [], 'do_p]>, "One of the following flags can be defined before the ColdC code (seperated with a semi-colon), which will change the execution behaviour: ", <$format, ["tt", [], ["trace"], 'do_tt]>, ", ", <$format, ["tt", [], ["debug"], 'do_tt]>, ", ", <$format, ["tt", [], ["profile"], 'do_tt]>, " or ", <$format, ["tt", [], ["opcodes"], 'do_tt]>, ". ", <$format, ["np", [], [], 'do_np]>, "If ", <$format, ["tt", [], ["trace"], 'do_tt]>, " is defined, a trace of all method calls made during the execution will be printed after execution is complete--along with the tick number they were made at. If ", <$format, ["tt", [], ["debug"], 'do_tt]>, " is defined, the output is similar to ", <$format, ["tt", [], ["trace"], 'do_tt]>, " but the tick number of the return statement is also included. If ", <$format, ["tt", [], ["profile"], 'do_tt]>, " is defined, a breakdown of all method calls is provided, along with the number of ticks consumed by the method--sorted by the largest first. If ", <$format, ["tt", [], ["opcodes"], 'do_tt]>, " is defined, the code will not actually execute, but instead will return the interpreter's opcodes for the method."], #[]]>; update objvar Updating objvar $help_cmd_configsetting<$help_node>,body object $help_cmd_configsetting; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, <$format, ["b", [], ["PROGRAMMER COMMAND"], 'do_b]>, <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["Syntax: ", <$format, ["tt", [], ["@config-set?ting|@configure-set?ting <definer>:<setting>[=default] [options]"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This command displays how settings are currently setup, and can modify the options that were set when the setting was created with ", <$format, ["link", [["node", "$help_cmd_defsetting"]], ["@def-setting"], 'do_link]>, ". ", <$format, ["np", [], [], 'do_np]>, <$format, ["b", [], ["Example:"], 'do_b]>, " ", <$format, ["dfn", [], [<$format, ["quote", [], [">@config-set me:rl-email\nReconfigured setting $user_info:rl-email as:\n +get=get_user_info\n +set=set_user_info\n +clear=clear_user_info\n +format=format_user_info\n +access=public_user_info\n"], 'do_quote]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "The complete list of options and their definitions can be found by looking at the ", <$format, ["link", [["node", "$help_cmd_defsetting"]], ["@def-setting"], 'do_link]>, " help page."], #[['links, #[["@def-setting", "$help_cmd_defsetting"]]]]]>; update objvar Updating objvar $help_cmd_who<$help_node>,body object $help_cmd_who; var $help_node body = <$ctext_frob, [[<$format, ["dfn", [], ["Syntax: ", <$format, ["tt", [], ["@who [<options>] [<users>]"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "This command in it's default form lists all users currently connected to the system. The @who listing can be used to show information about various groups of users depending on what usernames and options are given.", <$format, ["p", [], [], 'do_p]>, "Users should be specified separated by commas (optionally, with \"and\" before the last one, as in english). ", <$format, ["np", [], [], 'do_np]>, " ", <$format, ["b", [], ["Example:"], 'do_b]>, <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], [<$format, ["quote", [], [">@who\n--- Connected Users (1) ---\nName On for Location\n---- ------ --------\nVampire 2 days Solar System (NASA, Space Wing)\n"], 'do_quote]>], 'do_dfn]>, " ", <$format, ["np", [], [], 'do_np]>, " ", <$format, ["b", [], ["Example:"], 'do_b]>, <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], [<$format, ["quote", [], [">@who vampire, scott, and brad\n--- Users (3) ---\nName On for Idle Location\n---- ------ ---- --------\nVampire 10 days Nowhere (<Creation>)\nBrad 3 days 22 hrs the Courtyard (Caislea'n, Taobh Thiar)\nScott 5 hrs 2 hrs the Courtyard (Caislea'n, Taobh Thiar)\n---\n"], 'do_quote]>], 'do_dfn]>, " ", <$format, ["np", [], [], 'do_np]>, " Options can be: ", <$format, ["dfn", [["nobound", 1], [" ", 1], ["ind", "4"]], [<$format, ["table", [["cols", "30%,70%"]], [<$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["+admin"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["List all connected admins."], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["+prog"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["List all connected programmers."], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["+all"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["List all users in the specified group (admins or programmers), connected or not."], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["+short"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["Display @who listing in short form."], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["+sort=<type>"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["Sort the users listed according to <type>:", <$format, ["dl", [], [<$format, ["dt", [], [<$format, ["tt", [], ["idle"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["How long they've been idle"], 'do_dd]>, <$format, ["dt", [], [<$format, ["tt", [], ["connected"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["How long they've been connected"], 'do_dd]>, <$format, ["dt", [], [<$format, ["tt", [], ["name"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["Alphabetically by name"], 'do_dd]>, <$format, ["dt", [], [<$format, ["tt", [], ["location"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["Grouped by location"], 'do_dd]>, <$format, ["dt", [], [<$format, ["tt", [], ["place"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["(same as ", <$format, ["tt", [], ["location"], 'do_tt]>, ")"], 'do_dd]>], 'do_dl]>], 'do_td]>], 'do_tr]>, <$format, ["tr", [], [<$format, ["td", [], [<$format, ["tt", [], ["-sort=<type>"], 'do_tt]>], 'do_td]>, <$format, ["td", [], ["Same as ", <$format, ["tt", [], ["+sort"], 'do_tt]>, ", but sort in descending order."], 'do_td]>], 'do_tr]>], 'do_table]>], 'do_dfn]>], #[]]>; update objvar Updating objvar $help_cmd_channel_purge<$help_node>,body object $help_cmd_channel_purge; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], ["Syntax: ", <$format, ["tt", [], ["@purge-channel <channel>"], 'do_tt]>], 'do_dfn]>, <$format, ["p", [], [], 'do_p]>, "Removes a channel from the world, but only if you are the channel manager.", <$format, ["p", [], [], 'do_p]>], #[]]>; update objvar Updating objvar $help_heap<$help_node>,body object $help_heap; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "The heap is an efficient implementation of the priority queue. It is currently used by $scheduler and $graph. When you use it only in assignment calls (", <$format, ["tt", [], ["list = $heap.method(args)"], 'do_tt]>, ", in other words), it will operate in the logarithmic time (very fast).", <$format, ["p", [], [], 'do_p]>, "Heap is a list with the property that ", <$format, ["i", [], ["i"], 'do_i]>, "-th element of the list has lower priority than either ", <$format, ["i", [], ["2*i"], 'do_i]>, "-th and ", <$format, ["i", [], ["2*i+1"], 'do_i]>, "-st element of the list. Obviously, the first element of the list will have the lowest priority.", <$format, ["p", [], [], 'do_p]>, <$format, ["dl", [], [<$format, ["dt", [], [<$format, ["tt", [], ["$heap.push(heap, element, priority_index)"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["Add a new element to the heap. In this implementation, heap is assumed to be list of lists, with priority_index determining the priority field of each element."], 'do_dd]>, <$format, ["dt", [], [<$format, ["tt", [], ["$heap.del(heap, index, priority_index)"], 'do_tt]>], 'do_dt]>, <$format, ["dd", [], ["Delete an element at index ", <$format, ["i", [], ["i"], 'do_i]>, " of the heap. if index is greater than length of the heap, the method will throw."], 'do_dd]>], 'do_dl]>, <$format, ["p", [], [], 'do_p]>, "Both methods assume that their first argument already is a heap."], #[]]>; update objvar Updating objvar $help_sys_event_send<$help_node>,body object $help_sys_event_send; var $help_node body = <$ctext_frob, [[<$format, ["p", [], [], 'do_p]>, "Sending events is quite simple, from a programming point of view. There is no registration or initialization involved in creating an event--they exist as they are sent. ", <$format, ["np", [], [], 'do_np]>, "The method used to Send an Event is:", <$format, ["p", [], [], 'do_p]>, <$format, ["dl", [], [<$format, ["dt", [], ["relay.", <$format, ["method", [["event_handler.send_event", 1]], ["send_event"], 'do_method]>, "(", <$format, ["i", [], ["event"], 'do_i]>, ", ", <$format, ["i", [], ["@args"], 'do_i]>, ")"], 'do_dt]>, <$format, ["dd", [], ["Used to send an event. The object ", <$format, ["tt", [], ["relay"], 'do_tt]>, " is the broadcaster of the event (usually the current object's location). Any arguments beyond the event name are sent to the receiving event handler."], 'do_dd]>], 'do_dl]>, <$format, ["p", [], [], 'do_p]>, "An example sending the event ", <$format, ["tt", [], ["'combat"], 'do_tt]>, " to the current object's location:", <$format, ["p", [], [], 'do_p]>, <$format, ["dfn", [], [".location().send_event('combat, target_obj, with_weapon)"], 'do_dfn]>], #[]]>; new method Replacing public method $world_time.from_english() public method $world_time.from_english() { arg string, @units; var words, len, nsec, n, i, entry, unit; [(units ?= time_units)] = units; words = string.explode(); words = words.setremove_all(["and"]); if (listlen(words) == 1) { if (!(words = regexp(words[1], "^([0-9]+)(.*)$"))) throw(~args, "Invalid time."); } len = listlen(words); if (len % 2) throw(~args, ("Unrecognized time '" + string) + "', no descriptor."); nsec = (n = 0); for i in [1 .. len] { if ((i % 2) == 1) { if ((words[i]).is_numeric()) n = (words[i]).to_number(); else if ((words[i]) in ["a", "an"]) n = 1; else if ((words[i]) == "no") n = 0; else throw(~invarg, ("Invalid time element '" + n) + "'."); } else { unit = words[i]; unit = unit.strip(","); nsec += (> (units[.parse_unit(unit, units)])[1] <) * n; } } return nsec; }; new method Replacing public method $world_time.parse_unit() public method $world_time.parse_unit() { arg unit, @units; var i; [(units ?= time_units)] = units; i = find i in [1 .. units.length()] where (unit in ((units[i]).subrange(2))); if (i) return i; throw(~invarg, ("Invalid time unit '" + unit) + "', no descriptor?"); }; new method Replacing public method $command_parser.convert_arg() public method $command_parser.convert_arg() { arg cmd, type, str, me, argargs, target; var obj, args, anc, out, x, y, list; switch (type) { case 'list: out = []; if (!str) return [(> .convert_arg(cmd, argargs[1], "", me, argargs[2], target) <)]; // or do the whole list if ("," in str) list = str.explode_english_list(","); else list = explode(str); for x in (list) { catch ~ambig { out = out.setadd(.convert_arg(cmd, argargs[1], x, me, argargs[2], target)); } with { if ((| (traceback()[1])[3] |) && (!((argargs[1]) in ['user, 'user_opt]))) { for y in ((traceback()[1])[3]) out = out.setadd((> .convert_arg(cmd, argargs[1], tostr(y), me, argargs[2], target) <)); } else { rethrow(error()); } } } return out; case 'any: return str; case 'any_opt: args = (> $parse_lib.opt(str, @argargs) <); return args; case 'object: return (> me.match_environment(str) <); case 'object_opt: args = (> $parse_lib.opt(str, @argargs) <); if (!(args[1])) throw(~syntax, "No reference specified for command \""); obj = (> me.match_environment((args[1])[1]) <); return [obj, delete(args[1], 1), args[2]]; case 'objref: return (> $parse_lib.ref(str, me) <); case 'objref_opt: args = (> $parse_lib.opt(str, @argargs) <); if (!(args[1])) throw(~syntax, "No reference specified for command \""); obj = (> $parse_lib.ref((args[1])[1], me) <); return [obj, delete(args[1], 1), args[2]]; case 'user: if (!str) throw(~match, "No user specified."); if (str == "me") return me; return (| $user_db.search(str) |) || throw(~match, ("Unable to find user " + str) + "."); case 'user_opt: args = (> $parse_lib.opt(str, @argargs) <); if (!(args[1])) throw(~syntax, "Nobody specified for command \""); if (str == "me") return me; return [(> $user_db.search((args[1])[1]) <), args[2]]; case 'number: return (> str.to_number() <); case 'number_opt: args = (> $parse_lib.opt(str, @argargs) <); if (!(args[1])) throw(~syntax, "No number specified for command \""); return [(> str.to_number() <), args[2]]; case 'descendant: obj = (> me.match_environment(str) <); anc = argargs ? (argargs[1]) : user; if (!(obj.has_ancestor(anc))) throw(~parse, strfmt("You cannot %s %s because it is not %s!", cmd, obj.name(), anc.name())); return obj; case 'descendant_opt: args = (> $parse_lib.opt(str, @argargs) <); if (!(args[1])) throw(~syntax, "No descendant specified for command \""); obj = (> me.match_environment((args[1])[1]) <); anc = argargs ? (argargs[1]) : user; if (!(obj.has_ancestor(anc))) throw(~parse, strfmt("You cannot %s %s because it is not %s!", cmd, obj.name(), anc.name())); return [obj, args[2]]; default: throw(~ack, ("Support for the type '" + type) + " is incomplete!"); } }; new method Replacing public method $editor_session.append_cmd() public method $editor_session.append_cmd() { arg cmd, tmpl, what; var offset; (> .perms(caller(), 'command) <); modified = 1; if (line > listlen(text)) { text += [what]; return ("Line " + listlen(text)) + " added."; } else if (line == 1) { text = [what] + text; line = 2; return "Line 1 added."; } else { text = replace(text, line, (text[line]) + what); return ("Appended to line " + tostr(line)) + "."; } }; new method Adding protected method $editor_session.format_line() protected method $editor_session.format_line() { arg lineno, @linelen__shownumbers; var linelen, shownumbers, prefix, prefix_size, indent, textlen; linelen = (| linelen__shownumbers[1] |) || (sender.linelen()); shownumbers = ((linelen__shownumbers.length()) > 1) ? (linelen__shownumbers[2]) : 1; if (shownumbers) { textlen = text.length(); if (textlen < 10) { prefix_size = 5; indent = " "; } else if (textlen < 1000) { prefix_size = 6; indent = " "; } else { prefix_size = (tostr(textlen).length()) + 3; indent = pad("", prefix_size); } prefix = ((((lineno == line) ? "=>" : "") + lineno) + ": ").right(prefix_size); return (prefix + (text[lineno])).wrap_lines(linelen, indent); } else { return (text[lineno]).wrap_lines(linelen, ""); } }; new method Replacing public method $editor_session.list_cmd() public method $editor_session.list_cmd() { arg cmd, tmpl, rangestr; var start, end, start_preview, end_postview, preview, middle, postview, linelen, i, l, lineno, rows, chop, diff, lines, first_preview_line; (> .perms(caller(), $user, definer()) <); if (text == []) return "There is no text."; rangestr = rangestr.trim(); rows = (| sender().get_rows() |) || 20; l = text.length(); if (!rangestr) { start = line; start_preview = (rows - 1) / 2; end = line; end_postview = rows / 2; } else { catch any [start, end] = ._parse_range(rangestr, 0, 1); with return "Illegal list range."; if (end < 1) { end_postview = (chop = -end); end = start; } } preview = (middle = (postview = [])); linelen = sender.linelen(); // sigh.. there's gotta be a better way to do this.. I'm still thinking. // this works for now, tho. -R // // get the explicitly specified bit of text. for i in [start .. min(end, l)] middle += .format_line(i, linelen); // count any wrapped lines as taking up part of the postview. if (end_postview == (middle.length())) end_postview = 0; else end_postview -= (middle.length()) - 1; // if it's too much for the postview, take it out of the preview, too. if (end_postview < 0) { start_preview = max(start_preview + end_postview, 0); end_postview = 0; } // the following will cause [End] to always show after the current line if // it's the last line when the user types 'list' by itself, even if there // wouldn't otherwise be any space for a postview. if ((!rangestr) && ((end_postview == 0) && (end == l))) { start_preview = max(start_preview - 1, 0); ++end_postview; } // get the preview text. i = start - 1; while (i && ((preview.length()) < start_preview)) { preview = (.format_line(i, linelen)) + preview; i -= 1; } first_preview_line = i; // if we're too close to the beginning for the full amount of preview, add // the excess to the postview length. if ((preview.length()) < start_preview) end_postview += start_preview - (preview.length()); // get the postview text. for i in [end + 1 .. end + end_postview] { if (i > l) { postview += [(((l + 1) == line) ? "=>" : "") + "[End]"]; break; } lines = .format_line(i, linelen); postview += lines; if ((postview.length()) == end_postview) { break; } else if ((postview.length()) > end_postview) { diff = ((postview.length()) - end_postview) + 1; postview = postview.subrange(1, end_postview - 1); if (diff == (lines.length())) postview += ["[..next line..]"]; else postview += [((("[.." + (diff.to_english_text())) + " more row") + ((diff > 1) ? "s" : "")) + "..]"]; break; } } // if we're too close to the end for the full amount of postview, add the // excess to the preview. if ((postview.length()) < end_postview) { start_preview += end_postview - (postview.length()); // add to the preview text if necessary to fill the enlarged demand. i = first_preview_line; while (i && ((preview.length()) < start_preview)) { preview = (.format_line(i, linelen)) + preview; i -= 1; } } // cut preview to size. if ((preview.length()) > start_preview) preview = preview.subrange(((preview.length()) - start_preview) + 1); // if the user specified a fixed number of lines, and even with no // preview/postview it's too much, chop off the end of the middle portion too if (chop && ((middle.length()) > chop)) { diff = (middle.length()) - chop; middle = (middle.subrange(1, chop)) + [((("[.." + (diff.to_english_text())) + " more row") + ((diff > 1) ? "s" : "")) + "..]"]; } return (preview + middle) + postview; }; new method Replacing public method $editor_session._parse_range() public method $editor_session._parse_range() { arg what, @args; var start, end, range, allow_pastend, colon; if (what == "%") what = "1-$"; what = strsub(what, "$", tostr(listlen(text))); what = strsub(what, ".", tostr(line)); what = strsub(what, ",", "-"); allow_pastend = (| args[1] |) ? 1 : 0; if ((| args[2] |) && stridx(what, ":")) { what = strsub(what, ":", "-"); colon = 1; } if (!what) { start = (end = line); } else { range = (> $parse_lib.range(what) <); start = range[1]; if (start == 'specific) throw(~range, "Illegal range."); end = ((range[2]) == 'single) ? start : (range[2]); } if ((start < 1) || ((colon && (end < 0)) || ((!colon) && ((end > (listlen(text) + allow_pastend)) || (end < start))))) throw(~range, "Illegal range."); return [start, colon ? (-end) : end]; }; new method Adding public method $place_lib.regions() public method $place_lib.regions() { var e, p, q, s, v, regions, source, visited; regions = []; visited = #[]; for source in ($place.children()) { if (visited.contains(source)) continue; q = [source]; v = []; while ((q.length()) > 0) { p = q[1]; q = q.delete(1); v = v + [p]; visited = visited.add(p, 1); for e in ((| p.visible_exits() |) || []) { s = e.dest(p); if (visited.contains(s)) continue; q = q + [s]; refresh(); } } regions = regions + [v]; } return regions; }; new method Adding public method $place_lib.bfs() public method $place_lib.bfs() { arg source, dest; var e, p, q, r, s, v; if (source == dest) return []; q = [[source, []]]; v = []; while ((q.length()) > 0) { p = q[1]; q = q.delete(1); r = p[1]; v = v + [r]; for e in ((| r.visible_exits() |) || []) { s = e.dest(r); if (s in v) continue; if (s == dest) return (p[2]) + [e]; q = q + [[s, (p[2]) + [e]]]; refresh(); } } throw(~noway, "I can't find a route."); }; new method Adding public method $place_lib.makemap() public method $place_lib.makemap() { arg source, @args; var dest, e, visited, indent, retval; visited = (| (args[1]) + [source] |) || [source]; indent = (| args[2] |) || 0; retval = []; for e in ((| source.visible_exits() |) || []) { dest = e.dest(source); retval = retval + [(((("| " * max(0, indent - 1)) + ("+-" * (indent > 0))) + (e.path_name(source))) + " to ") + (dest.name())]; if (!(dest in visited)) { retval = retval + (.makemap(dest, visited, indent + 1)); visited = visited + [dest]; } refresh(); } return retval; }; new method Adding public method $place_lib.region() public method $place_lib.region() { arg source; var e, p, q, s, v, visited; visited = #[]; q = [source]; v = []; while ((q.length()) > 0) { p = q[1]; q = q.delete(1); v = v + [p]; visited = visited.add(p, 1); for e in ((| p.visible_exits() |) || []) { s = e.dest(p); if (visited.contains(s)) continue; q = q + [s]; refresh(); } } return v; }; new method Adding public method $place_lib.find_invalid() public method $place_lib.find_invalid() { var l, o, r; r = []; for l in ($location.descendants()) { for o in (l.contents()) { if ((type(o) == 'objnum) && (!valid(o))) r = r + [[l, o]]; } } return r; }; new method Replacing public method $directories.find_page() public method $directories.find_page() { arg orig_url, interface; var found, script_name, url, dir, page, lock, meth, obj; script_name = ""; url = orig_url.explode("/"); if ((| ((url[1])[1]) == "~" |)) url = ["~", (url[1]).subrange(2), @url.subrange(2)]; dir = $directories; page = $directories; if ((url.length()) == 2) { if ((| (obj = $object_lib.to_dbref(url[1])) |)) { page = obj; script_name += "/" + (url[1]); url = url.subrange(2); if ((| (meth = tosym(url[1])) |)) { if ((| page.find_method(meth) |)) { interface.set_info('generate, meth); script_name += "/" + (url[1]); url = url.subrange(2); found = 1; if ((page.has_ancestor($page)) && (page.get_lock())) lock = page; } else { return 'pagenf; } } else { return 'pagenf; } } } if (!found) { if (dir.get_lock()) lock = dir; catch ~keynf { while (url && (page.has_ancestor($directories))) { page = dir.entry(url[1]); script_name += "/" + (url[1]); url = url.subrange(2); if (page.get_lock()) lock = page; if (page.has_ancestor($directories)) dir = page; } } if (page.has_ancestor($directories)) { if ((!url) && ((orig_url.last()) != "/")) { return ['redirect, orig_url + "/"]; } else { if (url) return 'pagenf; page = page.default_page(); if (page.get_lock()) lock = page; } } if (url && (| (meth = tosym(url[1])) |)) { if ((| page.find_method(meth) |)) { interface.set_info('generate, meth); script_name += "/" + (url[1]); url = url.subrange(2); } else { interface.set_info('generate, 'generate); } } else { interface.set_info('generate, 'generate); } } interface.set_info('script_name, script_name); interface.set_info('path_info, "/" + (url.join("/"))); interface.set_info('directory_object, dir); interface.set_info('lock_object, lock); return page; }; maintenance object $root; eval { del_method('__upgrade_handle_var); }; old obj Removing $help_cmd_addsetting... old object $help_cmd_addsetting; old obj Removing $login_log... old object $login_log; old obj Removing $reaper_log... old object $reaper_log; old obj Removing $http_log... old object $http_log; old obj Removing $log... old object $log;