new object $user: $body, $mail_ui, $command_aliases, $bad_commands, $help_ui, $editor_reference, $channel_ui, $user_info, $menu; var $channel_ui active_channels = #[]; var $channel_ui channel_dict = #[]; var $command_aliases command_aliases = []; var $described prose = []; var $has_commands local = \ #[["@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, []]]]]]]]; var $has_commands shortcuts = #[["--*", ['remote_cmd, ["@page ", "", " with ", 1]]], ["-* *", ['remote_cmd, ["@page ", 1, " with ", 2]]]]; var $has_name name = ['prop, "Generic User Object", "Generic User Object"]; var $located location = $void; var $located obvious = 1; var $location contents = []; var $mail_list last_letter = 0; var $mail_list letters = #[]; var $mail_list letters_index = #[]; var $mail_list mail = []; var $mail_list notify = [$user]; var $mail_list readers = []; var $mail_list senders = 1; var $mail_ui current = #[['location, 0], ['list, $user]]; var $mail_ui subscribed = #[[$user, [791485891, 0]]]; var $root created_on = 796268969; var $root defined_settings = #[["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]]]]]; var $root flags = ['methods, 'code, 'core, 'command_cache, 'variables]; var $root inited = 1; var $root managed = [$user]; var $root manager = $user; var $root settings = #[["experienced", 0], ["exit-style", 'none], ["home", $body_cave], ["prompt", 0], ["extended-parsers", []]]; var $root trusted_by = [$user_db]; var $thing gender = $gender_neuter; var $user action = 0; var $user activity = 0; var $user auto_look = 0; var $user cols = 0; var $user connected_at = 0; var $user connected_seconds = 0; var $user connections = []; var $user content_type = 'plain; var $user context = #[['last, $root], ["it", $robot]]; var $user evaluator = 0; var $user ext_parsers = 0; var $user failed = 0; var $user formatter = $plain_format; var $user global_tell = 0; var $user last_command_at = 0; var $user monitor = 0; var $user parsers = [$command_parser]; var $user password = "*"; var $user reap_notified = 0; var $user registered = 0; var $user remembered = 0; var $user rows = 0; var $user task_connections = #[]; var $user title = 0; public method ._edit_mail_callback() { arg text, cdata; var list, subj, err, mail; // not necessarily safe perm checks (> .perms(caller(), $editor_session, $editor_reference) <); list = cdata[2]; subj = cdata[3]; if (!subj) { subj = .prompt("Subject: "); if (subj == "@abort") return "** Aborted mail send **"; if (subj == 'engaged) return "** Already reading input - mail send aborted **"; } mail = $mail_message.new_mail(); mail.set_subject(subj); mail.set_text(text); catch any mail.send(@list); with return ['failed, [(traceback()[1])[2]]]; return ['success, ["Mail sent to " + (list.map_to_english('mail_name))]]; }; protected method ._exam_sub() { arg name, plural, cmd, chop, obj, meth, @args; var list, line; list = (| obj.(meth)(@args) |) || []; if (!plural) line = pad(((name + " (") + cmd) + "):", 21) + (list.to_english("(none)")); else if (listlen(list) != 1) line = pad(((name + "s (") + cmd) + "):", 21) + (list.to_english("(none)")); else line = pad(((name + " (") + cmd) + "):", 21) + ((list[1]).namef('ref)); if (chop) line = line.chop(chop); return line; }; public method ._list_objects() { arg objs, multi, @args; var line, obj, c2, name, fmt, out, c1; if (!objs) { out = ["** None **"]; } else { c2 = ((| sender().linelen() |) || 79) / 10; c1 = c2 * 4; fmt = "%3L%*L %*L %*L"; out = [strfmt(fmt, "#", c1, "Name", c2, "Flags", c2, "Size") + "Manager"]; for obj in (objs) { line = strfmt(fmt, obj.(multi)(@args).length(), c1, obj.namef('xref), c2, $object_lib.see_perms(obj, ["", ""]), c2, obj.size()); name = (obj.manager()).namef('xref); if ((name.length()) > c1) name = name.pad(c1); out += [line + name]; } } return out; }; protected method ._tell() { arg what, @args; var line, conn, type, f; switch (type(what)) { case 'frob: what = $parse_lib.filter_ctext(what, #[['formatter, formatter]]); case 'string: if (content_type == 'html) what = (((what.replace("&", "&")).replace("<", "<")).replace(">", ">")) + "<br>"; // if (content_type == 'wrapped) { // what = strsub(what, "\\", "\\\\"); // what = str_to_buf(what.wrap_line(.linelen(), " ") + "\n"); // } case 'list: for line in (what) ._tell(line); return; case 'buffer: throw(~nobuf, "You are not allowed to send buffers."); } conn = (| .task_connection() |); if (conn && (!global_tell)) { conn.write(what); } else { for conn in (connections) (| conn.write(what) |); } }; public method ._tmp_wwmmmww() { $world.hook_into_event('realm_announce); }; protected method ._who_admins() { arg args, all; var out, admins, a, x, t; admins = []; if (args && (!all)) { for a in (args) { x = $user_db.search(a); if (!x) .tell(("I don't know who \"" + a) + "\" is."); else admins += [x]; } t = (("Admin" + (admins.length())) == 1) ? "" : "s"; } else if (all) { t = "All Admins"; admins = $sys.admins(); } else { t = "Connected Admins"; for a in ($user_db.connected()) { if (a.has_ancestor($admin)) admins += [a]; } } if (!admins) return 0; return [admins, t]; }; protected method ._who_at_place() { arg str; var place, thing, who, args; // This should actually be done with a global place dictionary and // a local place dictionary for each user. place = $place.match_descendants(str); if (!place) { .tell(("I do not know where \"" + str) + "\" is."); return 0; } who = []; for thing in (place.contents()) { if (thing.has_ancestor($user)) who += [thing]; } if (!who) { .tell(("Nobody is in " + (place.name())) + "."); return 0; } args = [who, "Users in " + (place.name())]; args = [@args, [['namef, 'titled], ['idle_time]]]; args = [@args, ["Name", "Times (idle)"], [1, 1]]; return args; }; protected method ._who_is() { arg @args; var person, p, who, x; who = []; args = ($string.explode_english_list(@args)) || []; for p in (args) { 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))))) + "."); default: .tell(("I don't know who \"" + p) + "\" is."); } continue; } who += [person]; } if (!who) return 0; return [who, ((who.length()) == 1) ? "User" : "Users"]; }; protected method ._who_programmers() { arg args, all; var out, progs, p, x, t; progs = []; if (args && (!all)) { for p in (args) { x = $user_db.search(p); if (!x) .tell(("I don't know who \"" + p) + "\" is."); else progs += [x]; } t = (("Programmer" + (progs.length())) == 1) ? "" : "s"; } else if (all) { t = "All Programmers"; progs = $programmer.descendants(); progs = progs.setremove($admin); } else { t = "Connected Programmers"; for p in ($user_db.connected()) { if (p.has_ancestor($programmer)) progs += [p]; } } if (!progs) return 0; return [progs, t]; }; protected method ._who_short() { var user, tmp, who, namestr, total; who = []; total = ($user_db.connected()).length(); .tell((("Currently connected users (total: " + tostr(total)) + ((total == 1) ? " person" : " people")) + "):"); for user in ($user_db.connected()) { 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.columnize(who, (.linelen()) / (tmp + 1), " ", .linelen())); }; public method .action() { // different from activity, returns a more accurate second to second action if (.connected()) return action || ""; else return "(asleep)"; }; public method .activity() { arg @noidle; var idle; // different from action, returns a broader version of your doings if (!(.connected())) return "asleep"; if (activity) return activity; if (noidle) return ""; idle = .idle_seconds(); if (idle < 180) return ""; if (idle < 300) return "daydreaming"; if (idle < 900) return "zoned"; else return "long gone"; }; public method .add_command_alias() { arg alias, actual; (> .perms(sender()) <); (> pass(alias, actual) <); if ((.command_aliases()) && (!($command_aliases_parser in (.parsers())))) { .tell("Adding $command_aliases_parser to your list of parsers.."); .add_parser($command_aliases_parser); } }; protected method .add_command_alias_cmd() { arg cmdstr, cmd, input; (> .perms(caller(), 'command) <); input = input.explode_quoted(); if (listlen(input) == 3) input = input.delete(2); if (listlen(input) != 2) return ("Syntax: `" + cmd) + " \"<alias>\" [to] \"<actual command>\"`"; catch any (> .add_command_alias(@input) <); with return (traceback()[1])[2]; return strfmt("New command alias %d => %d added.", @input); }; protected method .add_name_template_cmd() { arg cmdstr, cmd, args; var obj, template; (> .perms(caller(), 'command) <); args = args.explode_quoted(); if ((listlen(args) > 2) && ((args[2]) == "to")) args = delete(args, 2); if (listlen(args) > 2) args = [args[1], sublist(args, 2).join()]; if ((!args) || (listlen(args) != 2)) return ("Syntax: `" + cmd) + " \"<template>\" [to] \"<object>\"`"; obj = (> .match_env_nice(args[2]) <); template = args[1]; if (!(obj.has_ancestor($has_name))) return obj + " cannot have regular names."; catch any obj = (> obj.add_name_template(template) <); with return (traceback()[1])[2]; return ((((("Added name template \"" + template) + "\" to ") + (obj.namef('ref))) + ", templates: ") + ((obj.name_templates()).to_english())) + "."; }; protected method .add_parser() { arg parser, @over_pr; var x, pr; [(pr ?= parser.priority())] = over_pr; // does it exist? If so remove it. while (parser in parsers) parsers = setremove(parsers, parser); for x in [1 .. listlen(parsers)] { if (((parsers[x]).priority()) > pr) { parsers = insert(parsers, x, parser); return; } } parsers += [parser]; }; protected method .add_remembered() { arg what, name; remembered = (remembered || #[]).add(name, what); }; protected method .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); obj = (> .match_env_nice(args.join()) <); 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]; } }; protected method .add_writer_cmd() { arg cmdstr, cmd, args; var syn, obj, writer; (> .perms(caller(), 'command) <); args = (args.replace(" to ", " ")).explode(); if ((!args) || ((args.length()) != 2)) (> .tell_error(cmd + " <writer> [to] <object>") <); writer = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.add_writer(writer); return [(("Sucessfully added writer " + (writer.namef('xref))) + " to ") + (obj.namef('xref)), ("New writers list: " + ((((obj.writers('literal)).compress()).mmap('namef, 'xref)).to_english())) + "."]; } with { .tell((traceback()[1])[2]); } }; protected method .age_cmd() { arg cmdstr, com, obj; var time, gender, out; (> .perms(caller(), 'command) <); time = obj.created_on(); if (obj.is($thing)) gender = (obj.gender()).pronoun('psc); else gender = "It"; out = [((obj.name()) + " was created on ") + ($time.format("%A %B %d %Y", time)), ((gender + " is ") + ($time.elapsed(time() - time, 'long))) + " old."]; if (obj.is($user)) out += [((gender + " has logged ") + ($time.elapsed(obj.connected_seconds(), 'long))) + " online."]; return out; }; protected method .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; }; public method .check_password() { arg str, @cinfo; var match, warn; (> .perms(caller(), definer(), $login_interface, $security_lib) <); // no password means always match if (!password) return 1; // "*" means never match if (password == "*") return 0; match = match_crypted(password, str); // keep track of failed attempts, if its from a connection if ((!match) && cinfo) { if (.connected()) .tell("<Login> Failed Login Attempt from " + (cinfo[1])); else failed++; } // update old DES passwords to newer SHA passwords if (match && (!match_begin(password, "$2$"))) password = crypt(str); // done return match; }; public method .clear_content_type() { arg name; content_type = 'plain; }; protected method .command_aliases_cmd() { arg cmdstr, com, what; var aliases, a, line, str, num, out, left, right; (> .perms(caller(), 'command) <); if (!what) what = this(); else what = (> .match_env_nice(what) <); if ((what != this()) && (!(what.is_writable_by(this())))) return ("You are not allowed to read the command aliases on " + (what.namef('ref))) + "."; out = [("--- Command aliases on " + (what.namef('ref))) + ":"]; aliases = what.command_aliases(); if (aliases) { for a in (aliases) { str = a[1]; num = 0; while ("*" in str) { num++; left = str.subrange(1, ("*" in str) - 1); right = str.subrange(("*" in str) + 1); str = ((left + "%") + tostr(num)) + right; } out += [strfmt(" %30d => %d", str, $command_lib.format_relation(a[2]))]; } } else { out += [" <none>"]; } return out + ["---"]; }; protected method .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))); }; public method .connected() { return connections ? 1 : 0; }; public method .connected_at() { return connected_at; }; public method .connected_seconds() { return connected_seconds; }; public method .connected_time() { arg @args; [(args ?= 'dhms)] = args; if (connected_at < 0) return "Last on: " + ctime(abs(connected_at)); switch (args) { case 'dhms: return $time.dhms(time() - connected_at, 'long); case 'elapsed: return $time.elapsed(time() - connected_at); case 'seconds: return time() - connected_at; } }; public method .connection_going_away() { arg addr, port; var con, line; catch any { (> .perms(caller(), $connection) <); for con in (connections) { if (!valid(con)) connections = connections.setremove(con); } con = sender() in connections; connections = connections.setremove(sender()); 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())); } }; public method .connection_starting() { arg addr, port; var line, c; (> .perms(caller(), $connection) <); // shutoff our connection's timeout sender().set_timeout(0); // cleanup our connections list for c in (connections) { if (!valid(c)) connections = connections.setremove(c); } connections = [sender()].union(connections); if ((connections.length()) == 1) (| .login(sender()) |); else (| .login_again(sender()) |); line = ("CONNECT " + tostr(sender() in connections)) + " ("; line = (line + ((.parents())[1])) + "): "; line = (((line + this()) + " <") + (sender().address())) + "> "; (| $sys.log(line) |); }; public method .connections() { return connections; }; public method .context() { return context; }; protected method .context_cmd() { arg @args; var out; (> .perms(caller(), 'command) <); out = ["Last thing: " + ((| (context['last]).name() |) || "(nothing)")]; out += ["Last it: " + ((| (context["it"]).name() |) || "(nothing)")]; out += ["Last her: " + ((| (context["her"]).name() |) || "(nothing)")]; out += ["Last him: " + ((| (context["him"]).name() |) || "(nothing)")]; return out; }; root method .core_user() { // for now we dont core the bug system (| .del_command("@rep?ort", 'report_cmd) |); (| .del_method('report_cmd) |); }; public method .date_cmd() { arg @args; .tell($time.format("%I:%M %p %A, %B %d %Y %Z")); }; public method .del_command_alias() { arg alias; (> .perms(sender()) <); (> pass(alias) <); if ((!(.command_aliases())) && ($command_aliases_parser in (.parsers()))) { .tell("Removing $command_aliases_parser from your list of parsers."); .del_parser($command_aliases_parser); } }; protected method .del_command_alias_cmd() { arg cmdstr, com, template; (> .perms(caller(), 'command) <); template = template.explode_quoted(); if (listlen(template) == 0) return ("Syntax: " + com) + " <template>"; template = template[1]; catch ~aliasnf (> .del_command_alias(template) <); with return ("No command alias found matching \"" + template) + "\"."; return ("Deleted command alias \"" + template) + "\"."; }; protected method .del_name_template_cmd() { arg cmdstr, cmd, args; var syn, obj, template; (> .perms(caller(), 'command) <); args = args.explode_quoted(); if ((listlen(args) > 2) && ((args[2]) == "from")) args = delete(args, 2); if (listlen(args) > 2) args = [args[1], sublist(args, 2).join()]; if ((!args) || (listlen(args) != 2)) return ("Syntax: `" + cmd) + " \"<template>\" [from] \"<object>\"`"; obj = (> .match_env_nice(args[2]) <); template = args[1]; if (!(obj.has_ancestor($has_name))) return obj + " cannot have regular names."; if (!(template in (obj.name_templates()))) return (((obj.name()) + " does not have the name template \"") + template) + "\""; catch any obj = (> obj.del_name_template(template) <); with return (traceback()[1])[2]; return ((((("Deleted name template \"" + template) + "\" from ") + (obj.namef('ref))) + ", templates: ") + ((obj.name_templates()).to_english("none"))) + "."; }; public method .del_parser() { arg parser; var keepers; // removes a parser. Cannot remove $command_parser (put things in // front of it instead). if (parser == $command_parser) throw(~no, "You must always have the $command_parser."); parsers = parsers.setremove(parser); }; protected method .del_remembered() { arg name; remembered = (remembered || #[]).del(name); if (!remembered) clear_var('remembered); }; protected method .del_trustee_cmd() { arg cmdstr, cmd, args; var syn, obj, trustee; (> .perms(caller(), 'command) <); trustee = args[1]; args = args[2]; if (args && ((args[1]) == "from")) args = delete(args, 1); obj = (> .match_env_nice(args.join()) <); catch any { (> obj.del_trusted(trustee) <); return [(("Removed trustee " + (trustee.namef('ref))) + " from ") + (obj.namef('ref)), (((obj.namef('ref)) + " now trusts: ") + ((((obj.trusted('literal)).compress()).mmap('namef, 'ref)).to_english("nobody"))) + "."]; } with { .tell((traceback()[1])[2]); } }; protected method .del_writer_cmd() { arg cmdstr, cmd, args; var syn, obj, writer; (> .perms(caller(), 'command) <); args = (args.replace(" from ", " ")).explode(); if ((!args) || ((args.length()) != 2)) .tell_error(cmd + " <writer> [from] <object>"); writer = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.del_writer(writer); return [(("Sucessfully removed writer " + (writer.namef('xref))) + " from ") + (obj.namef('xref)), ("New writers list: " + ((((obj.writers('literal)).compress()).mmap('namef, 'xref)).to_english())) + "."]; } with { .tell((traceback()[1])[2]); } }; public method .description() { arg flags; var c, contents, ctext, pronoun, lines, p, br; br = $cml_lib.format_br_tag(); pronoun = (.gender()).pronoun('psc); if (connections) lines = [((pronoun + " is ") + ((.activity()) || "awake")) + ".", br]; else lines = [(pronoun + " is asleep, and was last connected ") + ($time.format("%d %B %y %H:%M", abs(connected_at))), br]; if ((contents = .contents())) { lines += [pronoun + " is holding:"]; lines += [(<$format, ["dfn", [["nobound", 1]], [(<$generator, ["join", [["separator", br]], map c in (contents) to ($cml_lib.format_obj_tag('look, c, c.name(), 'contained)), 'gen_join]>)], 'do_dfn]>)]; } return (> pass(flags) <) + [$ctext_frob.new_with(lines)]; }; protected method .description_cmd() { arg cmdstr, cmd, str; var args, obj, desc, long; (> .perms(caller(), 'command) <); if ((args = match_template(str, "* as *"))) { obj = (> .match_env_nice(args[1]) <); desc = ((args[3]).trim()).unquote(); } else { obj = (> .match_env_nice(str) <); if ((desc = .read()) == 'aborted) return; } if (!desc) return "You must specify a description."; catch any obj.set_prose(desc); with return (traceback()[1])[2]; return ("Description for " + (obj.namef('ref))) + " set."; }; public method .did_move() { arg @args; (| .reset_actions() |); (> pass(@args) <); if (auto_look != 'no) .tell((.location()).get_description(#[['actor, this()], ['exclude, [this()]]])); }; protected method .discard_cmd() { arg cmdstr, cmd, target; var msg, s, name; (> .perms(caller(), 'command) <); if ((cmdstr.trim()) == "discard") { s = .prompt(("Are you sure you want to discard " + (target.name())) + "? "); if (!(s in ["yes", "y"])) return ("Ok, not discarding " + (target.name())) + "."; } if (((target.location()) != this()) && (!(target.is($exit)))) return ("You are not holding " + (target.name())) + "."; name = target.name(); if (type(target) == 'frob) { catch ~perm target.discard(); with return (traceback()[1])[2]; } else if ((target.manager()) == this()) { target.destroy(); } else { target.move_to($trash); msg = $mail_message.new_mail(); msg.set_subject("Discarded Object"); msg.set_text([(((((((target.name()) + " has been discarded by ") + (.name())) + ". It currently exists in ") + ($trash.namef('ref))) + ", and will be destroyed in 15 days. You may retrieve it with the command `@move ") + target) + " to me`."]); (| msg.send(target.manager()) |); } return ("Discarding " + name) + "."; }; protected method .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]; } } }; public method .evaluator() { return evaluator; }; protected method .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: " + ((obj.size()).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(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() |) || []); }; public method .find_object() { arg str, @args; var trace, match; // comprehensive matching method. // args define what to match. if (!args) args = ['environment]; while (args) { switch (args[1]) { case 'environment: match = (| .match_environment(str) |); case 'user: match = (| $user_db.search(str) |); case 'grasp: match = (| $object_lib.to_dbref(str) |); } if (match) return match; args = args.delete(1); } throw(~objnf, ("No object found by the reference \"" + str) + "\"."); }; public method .find_object_nice() { arg str, @args; var match; catch any { match = .find_object(str, @args); } with { .tell("! " + ((traceback()[1])[2])); throw(~stop, ""); } return match; }; protected method .finger_cmd() { arg cmdstr, cmd, who; var out; (> .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()) 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())))]; }; protected method .forget_cmd() { arg cmdstr, cmd, str; var what; (> .perms(caller(), 'command) <); what = (| remembered[str] |); if (!what) return ("You don't remember what \"" + str) + "\" is..."; .del_remembered(str); return ((("Forgetting " + (what.namef('xref))) + " as \"") + str) + "\"."; }; protected method .forget_place() { arg place; if (type(place) != 'objnum) throw(~type, "Place must be submitted as an object."); remembered_places = remembered_places.setremove(place); }; public method .format_content_type() { arg value; return "text/" + value; }; public method .format_ext_parsers() { arg value; return value.to_english(); }; public method .format_settings() { arg target, @showdef; var sets, out, m, s, value, defs; if (showdef) showdef = showdef[1]; catch ~perm { if (type(showdef) == 'objnum) sets = hash s in (showdef.defined_settings()) to ([s[1], showdef]); else sets = target.all_defined_settings(); } with { return ["** Permission Denied"]; } out = sets; for s in (sets) { catch any value = target.format_setting(@s, target.get_setting(@s)); with value = (((traceback()[1])[1]) + ": ") + ((traceback()[1])[2]); out = dict_add(out, s[1], value); } if ((type(showdef) != 'objnum) && showdef) { defs = #[]; for s in (sets) defs = defs.setadd_elem(tostr(s[2]), s[1]); sets = out; out = []; for m in (defs) { out += [(m[1]) + ":"]; out += map s in ((m[2]).sort()) to ([((" " + s) + " = ") + (sets[s])]); } return out; } else if (type(showdef) == 'objnum) { return [showdef + ":"] + map s in ((out.keys()).sort()) to ([((" " + s) + " = ") + (out[s])]); } else { return map s in ((out.keys()).sort()) to ([((" " + s) + " = ") + (out[s])]); } }; public method .get_auto_look() { arg @args; // invert the logic, most people want it on (less clutter this way) return !auto_look; }; public method .get_base_parsers() { if (.command_aliases()) return [$command_aliases_parser, $command_parser, $channel_parser]; return [$command_parser, $channel_parser]; }; protected method .get_cmd() { arg cmdstr, cmd, what; var ol, l, isuser; (> .perms(caller(), 'command) <); ol = what.location(); if (ol == this()) { return ("You already have " + (what.name())) + "."; } else if (what == this()) { return "Ewww, its all twisty."; } else { l = .location(); if (l != ol) { isuser = ol.is($user); if ((| ol.location() |) != l) return ("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."); return (((what.name()) + " is locked to ") + ((what.lock()).lock_name('thing))) + "."; } else { return (traceback()[1])[2]; } } 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())) + "."; } }; public method .get_cols() { arg @args; return cols || 80; }; public method .get_content_type() { arg name, definer; return content_type || 'plain; }; protected method .get_from_cmd() { arg cmdstr, cmd, what, p, loc; var c, obj, l, wl, str; (> .perms(caller(), 'command) <); if (loc == this()) return ("You already have " + (what.name())) + "."; 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]; } } }; public method .get_global_tell() { arg @args; return global_tell; }; public method .get_rows() { arg @args; return rows || 19; // 19 is the number of display rows you have in tf, in // visual mode with a default display/terminal. }; protected method .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]; } }; protected method .go_cmd() { arg cmdstr, cmd, path; var m; (> .perms(caller(), 'command) <); if ((m = match_template(path, "to *"))) return cmd + " to support is pending completion."; 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"; }; public method .home() { arg @args; var home; if ((home = pass(@args)) == $lost_and_found) return $body_cave; return home; }; public method .idle_seconds() { return time() - last_command_at; }; public method .idle_time() { arg @args; var idle; [(args ?= 'dhms)] = args; idle = .idle_seconds(); if ((connected_at < 0) || (idle < 30)) return ""; switch (args) { case 'dhms: return $time.dhms(idle, 'long); case 'elapsed: return $time.elapsed(idle); case 'seconds: return idle; } }; root method .init_user() { password = "*"; connected_at = 0; last_command_at = 0; connections = []; parsers = [$command_parser, $channel_parser]; action = ""; context = #[]; .set_quota($sys.get_starting('quota)); $user_db.insert(.name(), this()); .set_flags([]); .move_to($body_cave); task_connections = #[]; formatter = $plain_format; }; protected method .inventory_cmd() { arg @args; var i; (> .perms(caller(), 'command) <); if (.contents()) { .tell("Carrying:"); for i in (.contents()) .tell(" " + (i.name())); } else { .tell("You are empty-handed."); } }; public method .is_tellable_by() { arg caller, sender; return (sender == this()) || (caller in [$place, $user, $programmer, $admin, $mail_ui, $help_ui]); }; public method .last_command_at() { return last_command_at; }; public method .linelen() { if (cols) return cols - 1; return 79; // backwards compatability, older tiny style systems // want linelen to actually be cols - 1 }; public method .login() { arg connection; var loc, cmd, p, c, last, tmp; if ((sender() != this()) || (definer() != caller())) throw(~perm, "Invalid access to private method."); task_connections = #[]; (| .reset_parsers() |); for cmd in (.local_commands()) { for c in (cmd[2]) .add_to_local_cache(c[1]); } (| .reset_help_history() |); for p in (parents()) (| p.cache_init() |); $user_db.did_connect(); if (reap_notified) clear_var('reap_notified); last = connected_at; connected_at = time(); last_command_at = time(); loc = .location(); if (loc == $body_cave) { if ((.home()) != $body_cave) (| .move_to(.home()) |); else (| .move_to($world.starting_place()) |); } else { .tell(.look_cmd("", "", "")); } $channel_ui._broadcast('Login, (((.namef('titled)) + " has connected (total: ") + ($user_db.total_connected())) + ")"); (| (.location()).did_connect() |); (| .login_notify(connection, last) |); (| .edit_sessions_notify() |); .hook_events('startup); $world.hook_into_event('realm_announce); context = #[]; }; public method .login_again() { arg connection; if ((sender() != this()) || (definer() != caller())) throw(~perm, "Invalid access to private method."); last_command_at = time(); (| .tell(("<Login> " + (((.connections()).length()).n_to_nth())) + " login.") |); if (failed) { (> .tell(("<Login> ** " + failed) + " failed login attempts **") <); (| clear_var('failed) |); } }; protected method .login_notify(): forked { arg connection, last; var l, sub, out, ans; sub = .subscribed(); out = []; for l in ((sub.keys()).setremove(this())) { if ((l.last_received_on()) > ((sub[l])[1])) out += [l.mail_name()]; } if (out) .tell("<Mail> New mail on lists: " + (out.to_english())); if ((.last_received_on()) > (((.subscribed())[this()])[1])) .tell("<Mail> You have new mail (use `@help mail` to learn about mail)"); if (last) .tell("<Login> Last connected at " + ($time.format("%A %B %d %I:%M %p %Y", abs(last)))); if (failed) { (| .tell(("<Login> ** " + failed) + " failed login attempts **") |); (| clear_var('failed) |); } }; public method .logout() { arg connection; var p; (| (.location()).did_disconnect() |); (| .reset_parsers() |); (| .reset_actions() |); (| .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) |); } (| .purge_caches() |); for p in (parents()) p.cache_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) |); }; public method .logout_connection() { arg connection; if ((sender() != this()) || (definer() != caller())) throw(~perm, "Invalid access to private method."); .tell(("<Login> " + ((((.connections()).length()) + 1).n_to_nth())) + " logout."); }; protected method .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()], ['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; } }; protected method .managed_cmd() { arg cmdstr, cmd, args; var manager, managed, obj, out, len; (> .perms(caller(), 'command) <); manager = (| .match_environment(args) |); if (!manager) { manager = (| $user_db.search(args) |); if (!manager) return ("Unable to find \"" + args) + "\"."; } managed = manager.managed(); if (!managed) return (manager.namef('ref)) + " does not manage any objects."; out = [(manager.namef('ref)) + " manages:"]; len = (.linelen()) / 2; for obj in (managed) out += [((" " + ((obj.namef('xref)).pad(len))) + " ") + ($object_lib.see_perms(obj, ["", ""]))]; return out; }; protected method .manager_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); return (((what.namef('ref)) + " is managed by ") + ((what.manager()).namef('ref))) + "."; }; protected method .map_cmd() { arg cmdstr, cmd; var l, obj, pos; (> .perms(caller(), 'command) <); l = .location(); pos = l.get_setting("map-position", $realm_settings); return (| (pos[4]).view(@pos.subrange(1, 3), 20, 79) |) || "This room doesn't have map defined for it."; }; public method .match_context() { arg str; return context[str]; }; public method .match_env_nice() { arg name, @syntax; var obj, args, line; catch any { return (> .match_environment(name) <); } with { if (syntax) (> .tell_error(syntax[1], (traceback()[1])[2]) <); else throw(~stop, (traceback()[1])[2]); } }; public method .match_environment() { arg str; var match, gend; if ((!str) && (match = (| context['last] |))) { if (valid(match)) return match; } if ((match = (| (.remembered())[str] |))) { if (!valid(match)) .del_remembered(str); else return match; } match = (> pass(str) <); if (match.has_ancestor($thing)) { gend = (| match.gender() |); if (gend) context = context.add(gend.pronoun('po), match); } context = context.add('last, match); return match; }; public method .match_name() { arg str; var m, n; if ((m = pass(str))) return m; for n in (registered || []) { if ((m = match_begin(n, str))) return m; } return 0; }; protected method .monitor() { return monitor; }; protected method .monitor_cmd() { arg cmdstr, cmd, @args; var e, out, line, len; (> .perms(caller(), 'command) <); if (!(args[1])) { if (monitor == 0) return "You are not monitoring what you hear."; out = []; len = .linelen(); for e in (monitor || []) { line = strfmt("%20S %30S ", (| (e[1]).namef('xref) |) || toliteral(e[1]), ((((e[2]) + ".") + (e[4])) + "() line ") + (e[5])) + (e[6]); if (strlen(line) > len) line = line.chop(len); out += [line]; } return out + ["---"]; } if ("on" in args) { monitor = []; return "You are now monitoring what you hear."; } else { (| clear_var('monitor) |); return "You are no longer monitoring what you hear."; } }; public method .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, "^([a-z0-9.-]+) *= *(.*)$"))) { name = (what[1]).trim(); args = (what[2]).trim(); } else { name = args; args = ""; } if (!name) return ([("-- Messages on " + (who.namef('ref))) + ":"] + (.format_messages(who))) + ["---"]; name = split(name, " *\. *"); if (listlen(name) == 1) { name = name[1]; branch = ""; } else if (listlen(name) == 2) { [name, branch] = name; } else { return ("Invalid Message name \"" + (name.join("."))) + "\""; } if (!($code_lib.valid_message_id(name))) return ("Invalid Message name \"" + name) + "\""; if (branch && (!($code_lib.valid_message_id(branch)))) return ((("Invalid Message branch \"" + name) + ".") + branch) + "\""; msg = args.unquote(); catch any { definer = who.msg_definer(name); branch ?= "general"; 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]; } }; protected method .name_templates_cmd() { arg cmdstr, com, obj; (> .perms(caller(), 'command) <); if (!(obj.has_ancestor($has_name))) return (obj.name()) + " is not descended from $has_name!"; return (("Name templates for " + (obj.namef('ref))) + ": ") + ((obj.name_templates()).to_english("none")); }; public method .namef() { arg type; var str; switch (type) { case 'doing: str = .activity('noidle); if (str) return (((.name()) + " (") + str) + ")"; return .name(); case 'nactivity, 'activity: str = .activity(); if (str) return (((.name()) + " (") + str) + ")"; return .name(); case 'titled: str = .title(); if (str) return (((.name()) + " (") + str) + ")"; return .name(); default: return (> pass(type) <); } }; protected method .new_cmd() { arg cmdstr, cmd, args; var match, name, parent, line, set, nprog, new, t; (> .perms(caller(), 'command) <); if ((match = match_template(args, "* named *"))) { name = match[3]; args = match[1]; } else { name = ""; } catch any parent = (> .match_env_nice(args) <); with return (traceback()[1])[2]; if (!(parent.is($physical))) return ((parent.namef('ref)).capitalize()) + " is not a VR object, you can only create new objects from VR objects (try @spawn)."; if (name) { catch any name = (> $code_lib.parse_name(name) <); with return (traceback()[1])[2]; } // spawn from the first parent, add the others catch any { new = (> parent.new() <); if (new.is($located)) new = (> new.move_to(this()) <); if (name) { new = (> new.set_name(@name[1]) <); for t in (name[2]) new = (> new.add_name_template(t) <); } return (("You create \"" + (new.namef('ref))) + "\"") + ((new.name_templates()) ? ((" (" + ((new.name_templates()).to_english())) + ")") : ""); } with { .tell((traceback()[1])[2]); if (valid(new)) { line = new.namef('xref); catch ~isfrob (> new.destroy() <); with (> new.discard() <); if (valid(new)) return ("Unable to destroy new object " + line) + "."; else return ("Sucessfully destroyed new object " + line) + "."; } } }; protected method .new_editor_session() { arg ref, opts, type; var p; switch (ref[1]) { case 'object: if (!(| (p = (ref[2]).all_edit_types()) |)) return "The object is not editable."; if (type == "any") type = p[1]; if (!(| (ref[2]).(tosym("edit_" + type))() |)) return ((("Could not edit " + (ref[2])) + "'s ") + type) + "."; default: return ("You cannot edit " + (ref[1])) + "s."; } if (.active_editor()) return [("Editor invoked with " + ((.active_editor()).session_name())) + ".", "Type 'help' to list available commands."]; else return ["Remote editing invoked."]; }; protected method .news_cmd() { arg @args; var line, x, mail, m, base, length, out; (> .perms(caller(), 'command) <); mail = $mail_list_news.recent_mail(); base = mail[1]; mail = mail[2]; length = mail.length(); .new_list($mail_list_news); out = [($motd.server_name()) + " news:", ""]; for x in [1 .. length] { m = mail[x]; out += [((((m.has_read(this())) ? " " : "NEW => ") + (tostr(x + base).pad(-3))) + ") ") + (m.subject())]; } return out + ["", "Use \"@read #\", where # is the news item number, such as \"@read 1\". All news items can be found on mail list *news.", "---"]; }; public method .non_terminated_tell() { arg text; var conn; if (.get_setting("prompt", $user)) { conn = (| .task_connection() |); if (conn && (!global_tell)) { conn.write(text, 'non_terminated); } else { for conn in (connections) (| conn.write(text, 'non_terminated) |); } } else { .tell(text); } }; public method .parse_content_type() { arg value, @args; var type, types, valid, f; value = strsed(value, "text/", ""); if (!match_regexp(value, "[^a-z]")) { if ((| lookup(tosym(value + "_format")) |)) return tosym(value); } valid = $formatter.descendants(); valid = map f in (valid) to ("text/" + (substr(tostr(f), 2).sed("_format$", ""))).sort(); throw(~check, "Content-type must be one of: " + (valid.to_english("", " or "))); }; public method .parse_exit_style() { arg value, @args; var styles, s; // verify it is correct styles = ["none", "brief", "template?s", "long", "verbose"]; for s in (styles) { if (match_template(value, s)) return tosym(s.strip("?")); } throw(~wrong, "Style must be one of: " + (styles.to_english("", " or "))); }; public method .parse_ext_parsers() { arg value, @args; var objs, o, r; objs = []; for o in (value.explode_english_list()) { o = o.trim(); if (!(r = (| $object_lib.to_dbref(o) |))) { if (!(r = $user_parsers.match_children(o))) throw(~type, ("\"" + o) + "\" is not a child of $user_parsers."); } objs = setadd(objs, r); } // sorry buddy, no choice--these come from .get_base_parsers() for o in ((.get_base_parsers()) + [$command_aliases_parser]) objs = setremove(objs, o); return objs; }; public method .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(); 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(), line, 0, error()); } } catch any task_connections = task_connections.del(task_id()); return rval; }; public method .parsers() { .perms(sender(), 'trusts); return parsers; }; protected method .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) { c.local_echo_off(); while (!curr) curr = (.prompt("Current Password (@abort to abort): ")).trim(); c.local_echo_on(); if (curr == "@abort") return "*** Aborted ***"; } else { curr = args[1]; } if (!(.check_password(curr))) return "Invalid Password"; if (listlen(args) < 2) { c.local_echo_off(); while (1) { while (!new) new = (.prompt("New Password (@abort to abort): ")).trim(); if (new == "@abort") { c.local_echo_on(); return "*** Aborted ***"; } while (!verify) verify = (.prompt("Retype New Password (@abort to abort): ")).trim(); if (verify == "@abort") { c.local_echo_on(); return "*** Aborted ***"; } if (new == verify) break; .tell("Passwords do not match!"); new = (verify = 0); } c.local_echo_on(); } 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."); }; protected method .paste_cmd() { arg cmdstr, com, args; var obj, text, who, w, target; (> .perms(caller(), 'command) <); if (args) { args = args.sed("^to +", ""); if ("," in args) args = args.explode_english_list(); else args = args.explode(); who = []; for w in (args) { catch ~ambig, ~namenf { target = (> $user_db.search(w) <); } with { catch any target = (> .match_environment(w) <); with .tell((traceback()[1])[2]); } if (target) who = setadd(who, target); } if (!who) return "No valid targets."; } text = .read(); if (text == 'aborted) return .tell("@paste aborted."); else if (!text) return .tell("@paste nothing?"); text = [((" " + (.name())) + " (@paste's) ").center(79, "-", 'both), @text, " + Finis + ".center(79, "-", 'both)]; if (who) { for w in (who) (| w.tell(text) |); .tell(((((text.length()) - 2) + " lines of text pasted to ") + (who.map_to_english('name))) + "."); } else { (.location()).announce(text); .tell(((text.length()) - 2) + " lines of text pasted"); } }; public method .personal_fields() { return #[["real-name", 1], ["email", 1], ["address", 1], ["affiliation", 1], ["position", 1], ["location", 1], ["interests", 1], ["plan", 1], ["projects", 1], ["home-page", 0]]; }; protected method .personal_info() { return info || #[]; }; public method .prompt() { arg prompt, @abort_msg; .non_terminated_tell(prompt); return (> .read_line("", @abort_msg) <); }; public method .prompt_yesno() { arg str, @def; var input, rx; // the second argument is an integer for the default value [(def ?= 1)] = def; input = .prompt(str); if (match_regexp(input, "^(y|ye|yes)$")) return 1; if (match_regexp(input, "^(n|no)$")) return 0; return def; }; public method .ptell() { arg what, flags; if (!(.is_tellable_by(caller(), sender()))) throw(~perm, "Only allowed objects may call protected tell."); // switch (flags['type]) { ._tell(what); }; public method .pueblo_cmd() { arg cmstr, cmd, args; (.connections()).mmap('write, "</xch_mudtext><img xch_mode=purehtml>"); (.connections()).mmap('write, "<h1>Rich-HTML text enabled</h1>"); }; protected method .quit_cmd() { arg @args; (> .perms(caller(), 'command) <); return 'disconnect; }; public method .read() { arg @args; var text, output, head, tail; if (!(.connections())) return 'not_connected; if ((.task_connection()).is_reading_block()) return 'engaged; if (args.length()) head = args[1]; else head = "Receiving input. Enter \".\" to finish or \"@abort\" to abort."; if ((args.length()) > 1) tail = args[2]; else tail = "** Aborted **; Text thrown away."; if (head) .tell(head); output = (.task_connection()).start_reading_block('multiple); if ((output == 'aborted) && tail) .tell(tail); return output; }; public method .read_line() { arg @args; var line, abort_msg, head, con; if (!(.connections())) return 'not_connected; con = (| .task_connection() |) || ((.connections())[1]); if (con.is_reading_block()) return 'engaged; [(head ?= ""), (abort_msg ?= "** Aborted **")] = args; if (head) .tell(head); line = con.start_reading_block('one); if ((line == 'aborted) && abort_msg) .tell(abort_msg); return line[1]; }; public method .reap_notified() { return reap_notified; }; public method .reap_status() { return reap_status; }; private method .register_name() { arg new; if (!(new in (registered || []))) { (> $user_db.valid_name(new) <); (> $user_db.insert(new, this()) <); if (registered) registered += [new]; else registered = [new]; } }; private method .register_name_cmd() { arg cmd, cmdstr, name; catch any (> .register_name(name) <); with return (traceback()[1])[2]; return [("Registered alternate name \"" + name) + "\".", ("Registered names: " + (registered.to_english("none"))) + "."]; }; private method .registered_cmd() { arg @args; return ("Registered names: " + ((registered || []).to_english("none"))) + "."; }; public method .registered_names() { return registered || []; }; protected method .rehash_cmd() { arg cmdstr, cmd; var c, p; (> .perms(caller(), 'command) <); .tell("Rehashing your command caches..."); pause(); // purge first (| .purge_caches() |); // let the parents know we are "going away" for p in (parents()) p.cache_uninit(); // now rehash, hand-pick our own commands for cmd in (.local_commands()) { for c in (cmd[2]) .add_to_local_cache(c[1]); } // let the parents know we are back for p in (parents()) p.cache_init(); }; protected method .remember_cmd() { arg cmdstr, cmd, what, as, str; (> .perms(caller(), 'command) <); .add_remembered(what, str); return ((("Remembering " + (what.namef('xref))) + " as \"") + str) + "\"."; }; public method .remembered() { return remembered || #[]; }; protected method .remembered_cmd() { arg cmdstr, cmd, args; var item, out; (> .perms(caller(), 'command) <); if (!(.remembered())) return .tell("You do not remember anything."); out = []; for item in (.remembered()) out += [((" " + (item[1])) + " is ") + ((item[2]).namef('xref))]; return ["Remembered Items:"] + (out.lcolumnize()); }; public method .remote_cmd() { arg cmdstr, com, who, prep, str; var target, line, fstr, wstr, type, bad; (> .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); }; protected method .rename_cmd() { arg cmdstr, cmd, args; var obj, name, templates, article, old, oldart, oldts, new, t; (> .perms(caller(), 'command) <); args = args.explode_quoted(); if ((listlen(args) > 2) && ((args[2]) == "to")) args = delete(args, 2); if (listlen(args) > 2) args = [args[1], sublist(args, 2).join()]; if ((!args) || (listlen(args) != 2)) return ("Syntax: `" + cmd) + " \"<object>\" [to] \"<newname>\" [+(proper|unique|normal)]`"; obj = (> .match_env_nice(args[1]) <); catch any { name = (> $code_lib.parse_name(sublist(args, 2).join()) <); templates = name[2]; article = (name[1])[2]; name = (name[1])[1]; if ((name[1]) == "$") { if (((obj.is($user)) || (obj.is($place))) && (!(.is($admin)))) return "User objnames can only be changed by administrators."; name = substr(name, 2); if (!(name.valid_ident())) return "Object names can only contain a-z, 0-9 and the underscore."; name = tosym(name); old = obj.namef('xref); (> obj.set_objname(name) <); return ((("Renamed " + old) + " to ") + obj) + "."; } else { if (!(obj.has_ancestor($has_name))) return ("Object \"" + obj) + "\" cannot have a regular name."; oldart = (obj.name('literal))[1]; oldts = obj.name_templates(); old = ((((" [" + article) + "] \"") + (obj.name())) + "\"") + (templates ? ((" (" + (oldts.to_english())) + ")") : ""); old = ("\"" + (obj.name())) + "\""; obj = (> obj.set_name(name, article) <); new = ("\"" + (obj.name())) + "\""; if (templates) { for t in (templates) obj = (> obj.add_name_template(t) <); new += (" (" + ((obj.name_templates()).to_english())) + ")"; old += (" (" + (oldts.to_english())) + ")"; } if (oldart != ((obj.name('literal))[1])) { old = (("[" + oldart) + "] ") + old; new = (("[" + ((obj.name('literal))[1])) + "] ") + new; } return ((("Renamed " + old) + " to ") + new) + "."; } } with { return (traceback()[1])[2]; } }; protected method .reset_parsers() { var p, list; parsers = []; list = (.get_setting("extended-parsers", $user)) || []; for p in ((.get_base_parsers()) + list) .add_parser(p); }; public method .set_activity() { arg str; (> .perms(sender()) <); activity = str; }; protected method .set_auto_look() { arg name, definer, value, @args; // invert the logic, most people want it on (less clutter this way) if (value) { if (auto_look) clear_var('auto_look); } else { auto_look = 'no; } }; protected method .set_closable() { arg name, definer, value; closable = value; }; public method .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, "^ *\+(def|definers|d) *= *\$?([a-z0-9_]+) *(.*)"))) { if (!(showdef = (| lookup(tosym(what[2])) |))) return "Invalid definer $" + (what[2]); args = what[3]; } if ((what = regexp(args, "^ *\+(def|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]; } }; protected method .set_cols() { arg name, definer, value, @args; if ((value == 80) || (!value)) (| clear_var('cols) |); else cols = value; }; protected method .set_content_type() { arg name, definer, value; var sets, meth; // a touch of Pueblo cruft crap if ((formatter == $pueblo_format) && (value != 'pueblo)) (.connections()).mmap('write, "<img xch_mode=text>Rich-HTML disabled"); content_type = value; formatter = lookup(tosym(value + "_format")); meth = tosym("set_content_type_" + value); if ((| .find_method(meth) |)) (> .(meth)() <); }; public method .set_content_type_pueblo(): forked { .tell("This world is Pueblo 1.10 enhanced."); .tell("Pueblo is annoyingly proprietary in that it requires this message to be printed, the administration appologizes for the disgustingness of this behaviour."); content_type = 'html; }; protected method .set_global_tell() { arg @args; if ((args[3]) == 0) clear_var('global_tell); else global_tell = 1; }; public method .set_name() { arg new_name, @ignore; var old_name, part, sname; (> .perms(sender(), 'manager) <); // so it doesnt bomb on .set_objname if ((> $user_db.valid_name(new_name) <)) old_name = .name(); catch any { (> pass(new_name, 'prop) <); if (new_name in (registered || [])) .unregister_name(new_name); if (!(| $user_db.key_changed(old_name, new_name) |)) $user_db.insert(new_name, this()); if (old_name != new_name) { sname = new_name.strip(); (> .set_objname(tosym("user_" + sname)) <); } } with { (| pass(old_name, 'prop) |); rethrow(error()); } }; public method .set_objname(): nooverride { arg new_objname; if ((caller() != $user) && (!(sender() in ($sys.system())))) throw(~perm, "User objnames can only be changed by $user."); (> pass(new_objname) <); }; public method .set_password() { arg str; (> .perms(sender(), 'manager) <); if ((str.length()) < 5) throw(~badpasswd, "Passwords must be at least 5 characters long."); password = crypt(str); }; public method .set_reap_notified() { arg date; (> .perms(sender(), 'system) <); if (date) reap_notified = date; else (| clear_var('reap_notified) |); }; public method .set_reap_status() { arg status; (> .perms(sender(), 'system) <); if (status) reap_status = status; else (| clear_var('reap_status) |); }; protected method .set_rows() { arg name, definer, value, @args; if ((value == 19) || (!value)) (| clear_var('rows) |); else rows = value; }; protected method .set_setting_title() { arg definer, name, value, @args; .set_title(value); }; public method .set_tell_traceback() { arg which, @lines; .perms(sender(), 'manager); if (!(which in ['verbose, 'brief, 'none])) throw(~type, "Which style must either be 'verbose, 'brief, or 'none."); if (lines && (type(lines[1]) != 'integer)) throw(~type, "You must specify the max lines as an integer."); if (!lines) lines = 0; else lines = lines[1]; tell_traceback = [which, lines]; }; root method .set_title() { arg name, definer, value; .perms(sender()); if (strlen(value) > 30) throw(~type, "Titles must be under 30 characters."); title = value; }; protected method .status_cmd() { arg cmdstr, com, @args; var line, s, x, out, utime, stime, nosys; (> .perms(caller(), 'command) <); s = $sys.status(); for x in [1 .. s.length()] { if ((s[x]) == (-1)) nosys++; } out = [("--- " + ($motd.server_name())) + " status report ---"]; if ($sys.dirty()) out += ["System is: dirty, will do normal backup."]; else out += ["System is: clean, will skip backup."]; utime = ((strsub($time.to_english(s[1]), " and", ",") + " and ") + ((s[2]) / 1000)) + " milliseconds"; stime = ((strsub($time.to_english(s[3]), " and", ",") + " and ") + ((s[4]) / 1000)) + " milliseconds"; out += ["System lag: " + ($lag_watcher.lag()), "Next dbref: " + ($sys.next_objnum()), "Driver: " + ($sys.server_info('driver_version, 'long)), "Core: " + ($sys.server_info('core_version, 'long)), ("Started: " + ($time.to_english(time() - ($sys.server_info('startup_time))))) + " ago", ("Backup: last: " + ($time.to_english(time() - (s[21])))) + " ago", (" next: " + ($time.to_english((s[22]) - time()))) + " from now", " interval: " + ($time.to_english(s[20]))]; if (!nosys) out += ["CPU time used: user: " + utime, " system: " + stime, ((("Page: " + (s[9])) + " reclaims ") + (s[10])) + " faults", ((("Context switches: " + (s[17])) + " voluntary ") + (s[18])) + " involuntary", "Signals: " + (s[16]), "---"]; return out; }; protected method .take_from_cmd() { arg cmdstr, cmd, what, p, loc; var c, obj, l, wl; (> .perms(caller(), 'command) <); if (loc == this()) return ("You already have " + (what.name())) + "."; for c in (loc.contents()) { if (c.match_name(what)) obj = c; } if (!obj) return ((.name()) + " does not have ") + what; if ((obj == this()) || (obj == loc)) return "Ewww, its all twisty."; catch any { l = .location(); wl = loc.location(); (> obj.move_to(this()) <); if (l != wl) wl.announce(((((((((.name()) + " ") + cmd) + "s ") + (obj.name())) + " ") + p) + " ") + (loc.name()), this()); l.announce(((((((((.name()) + " ") + cmd) + "s ") + (obj.name())) + " ") + p) + " ") + (loc.name()), this()); return ((((((("You " + cmd) + " ") + (obj.name())) + " ") + loc) + " ") + (loc.name())) + "."; } with { switch (error()) { case ~locked: if (loc.is($user)) loc.tell((((.name()) + " tried to take ") + (obj.name())) + " from you."); return (((obj.name()) + " is locked to ") + ((obj.lock()).lock_name('thing))) + "."; default: return (traceback()[1])[2]; } } }; public method .task_connection() { return task_connections[task_id()]; }; public method .task_connections() { return task_connections; }; public method .tell() { arg what, @who; if (!(.connected())) return; if (monitor != 0) { if (listlen(monitor) > 19) monitor = [[user(), @stack()[2], what], @delete(monitor, 10)]; else monitor = [[user(), @stack()[2], what], @monitor]; } ._tell(what); }; public method .tell_error() { arg syntax, @problem; var problem, line, sprefix, prefix, length; // arg 1 == syntax // arg 2 == problem lines length = .linelen(); if (syntax) .tell(("=> Syntax: `" + syntax) + "`"); if (problem) { for line in (problem) { if (type(line) == 'string) line = line.wrap_lines(length, "! ", 1); .tell(line); } } throw(~stop, ""); }; public method .tell_traceback() { arg traceback, @args; var tt, name, eargs, error, str; // tt = tell_traceback || ['verbose, 0, "! "]; [(str ?= ""), (eargs ?= 0), (error ?= 0)] = args; tt = ['verbose, -1, "! "]; traceback = $parse_lib.traceback(traceback, tt[2], tt[3], error); if (args) name = (| $list.to_english($list.mmap(args, 'namef, 'ref)) |); if (!name) name = "Object"; .tell((traceback[1]).replace("%O", name)); .tell(traceback.subrange(2)); }; public method .test() { var x, out; out = []; for x in (.look_cmd("", "look", "me")) { if (type(x) == 'frob) out += [$parse_lib.filter_ctext(x, #[['formatter, $plain_format]])]; else out += [x]; } return out; }; public method .title() { arg @args; return title || ""; }; protected method .trusted_by_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); return [(what.namef('ref)) + " is trusted by:"] + (._list_objects(what.trusted_by(), 'trusted)); }; protected method .trusts_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); return [(what.namef('ref)) + " trusts:"] + (._list_objects(what.trusted('literal), 'trusted_by)); }; root method .uninit_user() { var conn; if (.connected()) (| (.location()).did_disconnect() |); // and incase any are lying about for conn in (connections) (| conn.interface_going_away() |); password = 0; connections = 0; (| $user_db.remove(.name()) |); }; private method .unregister_name() { arg old; registered = setremove(registered || [], old); if (!registered) (| clear_var('registered) |); (| $user_db.remove(old) |); }; private method .unregister_name_cmd() { arg cmd, cmdstr, name; catch any (> .unregister_name(name) <); with return (traceback()[1])[2]; return [("Unregistered alternate name \"" + name) + "\".", ("Registered names: " + ((registered || []).to_english("none"))) + "."]; }; protected method .walk_path() { arg @path; var p, exit, exits, e, l, oal; if (!path) throw(~badpath, "Walk nowhere?"); oal = .get_auto_look(); .set_auto_look($user, "", 0); catch any { for p in (path) { // did we actually move? l = .location(); exits = l.exits(); if (!(exit = find e in (exits) where (e.match_name(p)))) .tell((("No exit \"" + p) + "\" from ") + (l.name())); else (exits[exit]).invoke(); pause(); } .set_auto_look(0, 0, oal); } with { .set_auto_look(0, 0, oal); rethrow(error()); } }; protected method .ways_cmd() { arg cmdstr, cmd, rest; var exits, e, line, out; (> .perms(caller(), 'command) <); exits = (.location()).visible_exits(); if (!exits) return "There are no visible exits from this room."; // come up with some settings to configure how to display exits // for now they can deal with the following out = []; if ((.get_setting("exit-style", $user)) == 'none) { out += ["Visible exits: "]; for e in (exits) out += [(((" " + (e.name())) + ((e.name_templates()) ? ((" (" + ((e.name_templates()).to_english())) + ")") : "")) + " to ") + ((e.dest()).name())]; } else { out += (.location()).format_exits(exits, #[['actor, this()]]); } return out + ["---"]; }; protected method .whereis_cmd() { arg cmdstr, cmd, who; var user, u; (> .perms(caller(), 'command) <); who = (who && (who.explode_english_list())) || []; if (who && ((who[1]) == "is")) who = who.delete(1); if (!who) return "You must specify somebody."; for user in [1 .. who.length()] { u = (| $user_db.search(who[user]) |); if (!u) { .tell(("I don't know who \"" + (who[user])) + "\" is."); who = who.replace(user, 0); } else { who = who.replace(user, u); } } for user in (who) { if (user) .tell(((user.namef('nactivity)) + " is in ") + ((user.location()).name())); } }; protected method .who_cmd() { arg cmdstr, com, @line; var who, opts, opt, args, all; (> .perms(caller(), 'command) <); // just the basic who listing who = []; if (!(line[1])) { args = [$user_db.connected(), "Connected Users"]; } else if (((line[1])[1]) == "@") { args = ._who_at_place((line[1]).subrange(2)); } else { args = $parse_lib.opt(line[1], "a?ll", "p?rogrammers", "a?dmins", "s?hort"); opts = args[2]; args = args[1]; if ((opt = "a?ll" in (opts.slice(1)))) all = (opts[opt])[3]; if ((opt = "p?rogrammers" in (opts.slice(1)))) args = ._who_programmers(args, all); else if ((opt = "a?dmins" in (opts.slice(1)))) args = ._who_admins(args, all); else if ((opt = "s?hort" in (opts.slice(1)))) return ._who_short(); else args = ._who_is(@line); } if (!args) return "Ack, nobody to list?"; .tell($code_lib.generate_listing(@args)); }; public method .will_move() { arg mover, place; (> pass(mover, place) <); if (place.is($user)) throw(~user, "Users cannot move into other users!"); if ((mover.is($user)) && ((mover != this()) && (!($sys.is_system(mover))))) throw(~user, "Only administrators can freely move users around."); }; protected method .writers_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); return [(what.namef('ref)) + " is a writer for:"] + (._list_objects(what.writers('literal), 'writes)); }; protected method .writes_cmd() { arg cmdstr, cmd, what; (> .perms(caller(), 'command) <); return [(what.namef('ref)) + " is a writer on:"] + (._list_objects(what.writes(), 'writers)); };