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));
};