parent $body
parent $interaction
parent $input
parent $command_aliases
parent $bad_commands
parent $user_data
parent $has_settings
parent $settings_ui
object $user
var $root child_index 47
var $root owners [$user]
var $root fertile 0
var $has_commands commands [["@quit", 'quit_cmd], ["i?nventory", 'inventory_cmd], ["@title *", 'title_cmd], ["@aliases *", 'aliases_cmd], ["@add-name-alias|@ana *", 'add_name_alias_cmd], ["@del-name-alias|@dna *", 'del_name_alias_cmd], ["@rename * to *", 'rename_cmd], ["@time *", 'time_cmd], ["@audit *", 'audit_cmd], ["@who *", 'who_cmd], ["@who-s?hort|@whos?hort", 'who_short_cmd], ["news", 'news_cmd], ["@del-command-a?lias|@dca?lias *", 'del_command_alias_cmd], ["@command-a?liases|@ca?liases *", 'command_aliases_cmd], ["@wrap *", 'wrap_cmd], ["@prompt *", 'prompt_cmd], ["@password *", 'password_cmd], ["@idle", 'idle_cmd], ["@who-a?dmins|@whoa?dmins *", 'who_admins_cmd], ["@add-command-a?lias|@aca?lias *", 'add_command_alias_cmd], ["@who-c?ount|@whoc?ount", 'who_count_cmd], ["@who-p?rogrammers|@whop?rogrammers *", 'who_progs_cmd], ["@login-watch *", 'watch_logins_cmd], ["@com?mands *", 'commands_cmd], ["@age *", 'age_cmd], ["@spawn|@create *", 'spawn_cmd], ["@prose|@describe *", 'prose_cmd], ["@status", 'status_cmd], ["@rehash?-commands", 'rehash_cmd]]
var $has_commands shortcuts []
var $has_verbs verbs #[]
var $location contents []
var $located location $nowhere
var $root inited 1
var $user password "*"
var $user connected_at 0
var $user last_command_at 0
var $user connections []
var $user linelen 0
var $user title 0
var $user email 0
var $user action 0
var $user creation_time 0
var $user home 0
var $user pagelen 0
var $user activity 0
var $user parsers []
var $user filters []
var $user watch_logins 0
var $user tell_traceback 0
var $user last_name 0
var $root dbref 'user
var $user prompt ""
var $root owned [$user]
var $command_aliases command_aliases []
var $gendered gender $gender_neuter
var $located obvious 1
var $described prose #[]
var $root manager $user
var $root writable [$user]
var $root readable ['parameters, 'methods, 'code]
var $user context 0
var $named name ['uniq, "Generic User Object"]
var $named name_aliases []
var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]]
var $has_settings setting_templates #[["terminated-tell", 'boolean], ["Content-type", 'string]]
method init_user
.perms(caller(), $root);
password = "*";
connected_at = 0;
last_command_at = 0;
connections = [];
creation_time = time();
parsers = [$command_parser, $verb_parser];
filters = [];
action = "";
prompt = "";
context = #[];
.set_quota($sys.user_starting_quota());
$user_db.insert(.namef(), this());
.set_readable([]);
.move_to($body_cave);
.
method uninit_user
var conn;
(> .perms(caller(), $root) <);
if (.connected())
(| (.location()).did_disconnect() |);
// and incase any are lying about
for conn in (connections)
(| conn.user_going_away() |);
password = 0;
connections = 0;
(| $user_db.remove(.name()) |);
.
method trusted
return pass() + ($parsers.children());
.
method will_move
arg mover, place;
(> pass(mover, place) <);
//if (!place.has_ancestor($room))
// throw(~perm, "Players can only move into rooms.");
.
method watch_logins
return watch_logins;
.
method connected_at
return connected_at;
.
method last_command_at
return last_command_at;
.
method tell
arg what;
var f;
if (filters) {
for f in (filters)
what = f.filter(what);
}
._tell(what);
.
method set_password
arg str;
var x, num;
.perms(sender(), 'manager);
if (strlen(str) < 5)
throw(~badpasswd, "Passwords must be at least 5 characters long.");
// this is assuming they have alphabetic characters as well (shrug).
// for x in [1 .. strlen(str)] {
// if (str[x] in "1234567890")
// num = num + 1;
// }
// if (num < 2)
// throw(~badpasswd, "Passwords must contain at least 2 numeric characters.");
password = crypt(str);
.
method check_password
arg str;
return crypt(str, substr(password, 1, 2)) == password;
.
method did_move
arg [args];
var loc;
(> pass(@args) <);
loc = .location();
(| loc.look_cmd("look") |);
.
method parsers
.perms(sender(), 'trusts);
return parsers;
.
method add_parser
arg parser, [position];
// adds a new $parser at 'position.
.perms(sender(), 'parser);
// do this in three steps, first make sure the posistion is valid,
// then check for it already, then figure its insert position.
position = [@position, 'first][1];
if (!(position in ['last, 'first]))
throw(~type, "Posistion types must be one of: 'last, 'first.");
// does it exist? If so remove it.
if (parser in parsers)
parsers = setremove(parsers, parser);
// figure position
if (position == 'last)
position = listlen(parsers) + 1;
else if (position == 'first)
position = 1;
parsers = insert(parsers, position, parser);
.
method del_parser
arg parser;
var keepers;
// removes a parser. Cannot remove $command_parser or $verb_parser
keepers = [$command_parser, $verb_parser];
if (!(parser in parsers))
throw(~parsernf, ($data.unparse(parser)) + " is not in the parser list.");
if (parser in keepers)
throw(~twink, ("You must always have " + ($list.map_to_english(keepers, 'namef))) + ".");
parsers = setremove(parsers, parser);
.
method parse_line
arg line;
var result;
.perms(caller(), $old_connection);
last_command_at = time();
catch any {
result = parsers ? (parsers[1]).parse(this(), line, @sublist(parsers, 2), $null_parser) | 'failed;
if (type(result) == 'list)
return (result[1]).(result[2])(@sublist(result, 3));
switch (result) {
case 'failed:
.tell(("I don't understand \"" + ($string.chop(line, (.linelen()) - 22))) + "\".");
case 'ok:
default:
.tell(tostr(result));
}
} with handler {
if (((traceback()[1])[3]) != 'no_traceback)
.tell_traceback(traceback(), line, 0, error());
}
return 0;
.
method connection_logged_in
arg addr, port;
var line;
if (caller() != $old_connection)
throw(~perm, "Caller is not $old_connection.");
connections = connections + [sender()];
if (listlen(connections) == 1)
.login(sender());
else
.login_again(sender());
line = ("CONNECT " + tostr(sender() in connections)) + ": ";
line = (((line + (.dbref())) + " <") + (sender().addr())) + "> ";
$sys.log(line);
.
method connection_logged_out
arg addr, port;
var con, line;
if (caller() != $old_connection)
throw(~perm, "Caller is not $old_connection.");
con = sender() in connections;
connections = setremove(connections, sender());
if (!connections)
.logout(sender());
else
.logout_connection(sender());
connections = setremove(connections, sender());
line = ("DISCONNECT " + tostr(sender() in connections)) + ": ";
line = (((line + (.dbref())) + " <") + (sender().addr())) + "> ";
$sys.log(line);
.
method login
arg connection;
var loc;
if ((sender() != this()) || (definer() != caller()))
throw(~perm, "Invalid access to private method.");
.tell(("* * * Login successful (" + (connection.addr())) + ") * * *");
connected_at = time();
last_command_at = time();
//
loc = .location();
if (loc == $body_cave) {
if ((.home()) != $body_cave)
(| .move_to(.home()) |);
else
(| .move_to($places.place('starting)) |);
} else if ((loc == (.home())) || (loc != $body_cave)) {
(| loc.look_cmd("look") |);
} else {
(| .move_to(.home()) |);
}
(| (.location()).did_connect() |);
(| .login_notify() |);
(| $login_watcher.did_connect() |);
(| $user_db.did_connect() |);
.rehash_command_environment();
.
method login_again
arg connection;
if ((sender() != this()) || (definer() != caller()))
throw(~perm, "Invalid access to private method.");
last_command_at = time();
.tell(((("* * * " + ($integer.n_to_nth(connection in (.connections())))) + " Login successful (") + (connection.addr())) + ") * * *");
.
method logout
arg connection;
if ((sender() != this()) || (definer() != caller()))
throw(~perm, "Invalid access to private method.");
(| (.location()).did_disconnect() |);
// user specific things
if (!($guest in (.parents()))) {
(| $housekeeper.did_disconnect() |);
(| $user_db.last_log_disconnect(this()) |);
} else {
(| $user_db.last_log_disconnect($guest) |);
}
(| $user_db.did_disconnect() |);
(| $login_watcher.did_disconnect() |);
.purge_command_environment();
.
method connections
return connections;
.
method connected
disallow_overrides;
return connections ? 1 | 0;
.
method who_cmd
arg com, [args];
var who, x, person, where, meths, header;
// just the basic who listing
.perms(sender(), 'parser);
who = [];
if (!(args[1])) {
who = $user_db.connected();
// looks like they want who in a room.
} else if (((args[1])[1]) == "@") {
where = $room.match_descendants(substr(args[1], 2));
if (!where)
$parse.tell_error(("I do not know where \"" + substr(args[1], 2)) + "\" is.");
for x in (where.contents()) {
if (x.has_ancestor($user))
who = [@who, x];
}
if (!who)
$parse.tell_error(("Nobody is in " + (where.namef())) + ".");
meths = [['namef, 'titled, " (", 'activity, ")"], ['time_poll]];
header = ["Name", "Times (idle)"];
.tell($code.generate_listing(who, "Users in " + (where.namef()), meths, header, [1, 1]));
return;
} else {
//
// user, or list of users
for x in ($string.explode_english_list(@args)) {
catch any {
person = $user_db.find(x);
} with handler {
switch (error()) {
case ~ambig:
.tell(((("The name \"" + x) + "\" can match any of: ") + ($list.to_english($list.map((traceback()[1])[3], 'namef)))) + ".");
default:
.tell(("I don't know who \"" + x) + "\" is.");
}
continue;
}
who = [@who, person];
}
if (!who)
return;
}
.tell($code.generate_listing(who));
.
method email
return email || "**no email address**";
.
method quit_cmd
arg dummy;
.perms(sender(), 'parser);
return 'disconnect;
.
method inventory_cmd
arg dummy;
var i;
.perms(sender(), 'parser);
if (.contents()) {
.tell("Carrying:");
for i in (.contents())
.tell(" " + (i.namef()));
} else {
.tell("You are empty-handed.");
}
.
method match_env_nice
arg name, [syntax];
var obj, args, line;
// calls .match_environment() returns nice errors. as well as stopping if it
// breaks. No returns neccessary
syntax = [@syntax, ""][1];
catch any {
obj = .match_environment(name);
} with handler {
switch (error()) {
case ~ambig:
args = (traceback()[1])[3];
line = ("\"" + (args[listlen(args)])) + "\" can match any of: ";
line = line + ($list.map_to_english(args[1], 'namef));
(> $parse.tell_error(line, syntax) <);
case ~objnf:
line = ("Nothing found by the name \"" + ((traceback()[1])[3])) + "\".";
(> $parse.tell_error(line, syntax) <);
default:
line = (traceback()[1])[2];
(> $parse.tell_error(line, syntax) <);
}
}
return obj;
.
method linelen
return linelen || 79;
.
method idle_seconds
return time() - last_command_at;
.
method who_short_cmd
arg com;
var user, tmp, who, namestr, total;
if (sender() != this())
throw(~perm, "Sender not this.");
who = [];
total = listlen($user_db.connected());
.tell((("Currently connected users (total of " + tostr(total)) + ((total == 1) ? " person" | " people")) + "):");
for user in ($user_db.connected()) {
namestr = (((((" " + (user.namef())) + " (") + ($time.elapsed(user.connected_at()))) + " ") + ($time.dhms(user.idle_seconds()))) + ")";
who = [@who, namestr];
if (tmp < (strlen(namestr) + 2))
tmp = strlen(namestr) + 2;
}
.tell($list.columnize(who, (.linelen()) / (tmp + 1), " ", .linelen()));
.
method who_admins_cmd
arg com, [who];
var admins, admin, title;
who = who[1];
// everybody, connected or not
if (who == "all") {
admins = $sys.admins();
title = "All Admins";
// ok, just the connected ones then
} else if (who == "") {
title = "All Connected Admins";
admins = [];
for admin in ($sys.admins()) {
if (admin.connected())
admins = [@admins, admin];
}
// hrm, possibly somebody specific
} else {
admins = [.match_object_nice(who, $admin, 'children)];
}
.tell($code.generate_listing(admins, title));
.
method who_progs_cmd
arg com, [args];
var progs, all_progs, x, title;
args = args[1];
if (args) {
if (match_begin(args, "all")) {
progs = $programmer.descendants();
title = "All Programmers";
} else {
title = "Programmer";
progs = [.find_object_nice(args, 'environment, 'user, 'grasp)];
}
} else {
progs = [];
title = "Connected Programmers";
for x in ($programmer.descendants()) {
if (x.connected())
progs = [@progs, x];
}
}
.tell($code.generate_listing(progs, title));
.
method who_count_cmd
arg com;
var len, rz, pz;
.perms(sender(), 'parser);
len = listlen($user_db.connected());
if (len == 1) {
rz = "is";
pz = "person";
} else {
rz = "are";
pz = "people";
}
.tell(((((("There " + rz) + " currently ") + tostr(len)) + " ") + pz) + " connected.");
.tell("Lag is <lag meter will eventually go here>");
.
method title
return title || "";
.
method action
// different from activity, returns a more accurate second to second action
if (.connected())
return action || "";
else
return "(asleep)";
.
method time_poll
arg [args];
var idle;
if (!(.connected()))
return "Last On: " + substr(ctime(last_command_at), 1, 10);
if (!args)
idle = ((.idle_seconds()) > 10) ? $time.dhms(.idle_seconds(), 'long) | "";
else
idle = ((.idle_seconds()) > 10) ? $time.dhms(.idle_seconds()) | "";
return ($time.elapsed(.connected_at())) + (idle ? " " + idle | "");
.
method title_cmd
arg com, str;
.perms(sender(), 'parser);
.tell("Temporary until the real title setup is working");
catch any {
.set_title(str);
} with handler {
$parse.tell_error((traceback()[1])[2]);
}
.tell(("Title Set as: \"" + str) + "\"");
.
method commands_cmd
arg cmd, args;
var obj, coms, c, len, lcoms, scoms, ulen, l, what, a, opts, lines;
// returns all commands in a nice format.
.perms(sender(), 'parser);
args = explode(args);
if (!args) {
what = .ancestors();
.tell("All commands: (prepare to be spammed)");
} else {
what = [.match_env_nice(args[1])];
.tell("Commands on " + ((what[1]).namef('ref)));
}
ulen = .linelen();
for obj in (what) {
if (!((obj.has_ancestor($has_commands)) || (obj.has_ancestor($has_verbs))))
continue;
coms = [];
coms = coms + ((| $list.slice(obj.shortcuts(), 1) |) || []);
coms = coms + ((| $list.slice(obj.commands(), 1) |) || []);
coms = coms + ((| obj.verb_templates() |) || []);
if (coms) {
scoms = [];
lcoms = [];
for c in (coms) {
len = strlen(c) + 2;
if (len > (ulen / 3))
lcoms = [@lcoms, " " + c];
else
scoms = [@scoms, " " + c];
}
lines = ($list.lcolumnize(scoms, ulen)) + ($list.lcolumnize(lcoms, ulen));
for l in (lines)
.tell($string.trim(l, 'right));
.tell(" -=-");
}
if (obj == $has_commands)
break;
}
.
method tell_commands
arg p, ps, pc, space;
var x, a, c;
// called by $builder.commands_cmd
.tell(((((space + "Commands on ") + (p.namef('ref))) + " (") + toliteral(p)) + ")");
pc = ps + pc;
if (!pc) {
.tell(space + " None");
return;
}
for x in [1 .. listlen(pc)] {
a = pad(tostr((pc[x])[1]), 30) + " ";
c = pad(toliteral((pc[x])[2]), 20) + " ";
.tell(((space + " ") + a) + c);
}
.
method set_email
arg email_str;
var syn, email, host;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
// kludgy way to check for semi valid email addresses:
email = explode(email_str, "@");
if (listlen(email) < 2)
throw(~invemail, "Invalid email: " + email_str);
// check hostname for at least 1 subnet and a machine name.
host = explode(email[2], ".");
if (listlen(host) < 2)
throw(~invemail, "Invalid hostname: " + (host[1]));
// email is purposefully constructed this way, as at one point it will
// be able to automatically tack on your host, if you do not provide it.
set_var('email, ((email[1]) + "@") + (email[2]));
.
method set_watch_logins
arg value;
// either have a single reference, or: 'none|'all
.perms(sender());
watch_logins = value;
.
method echo_file
arg str;
var con;
for con in (connections)
con.echo_file(str);
.
method set_home
arg obj;
// if (!obj.is_writable_by(sender()))
// return .tell("You do not own " + obj.namef() + ".");
home = obj;
.
method pagelen
return pagelen || 24;
.
method set_pagelen
arg len;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender not an owner.");
if (type(len) != 'integer)
throw(~type, "pagelength must be an integer");
pagelen = len;
.
method set_linelen
arg len;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender not an owner.");
if (type(len) != 'integer)
throw(~type, "Linelength must be an integer");
linelen = len;
.
method aliases_cmd
arg com, [obj];
if (!(.is_writable_by(sender())))
throw(~perm, "Sender not owner.");
obj = .match_env_nice((obj[1]) ? obj[1] | (.dbref()));
if (!(obj.has_ancestor($named))) {
.tell(("Object `" + (obj.dbref())) + "' is not a named object.");
throw(~stop, "", 'no_traceback);
}
.tell((("Aliases for " + (obj.namef())) + ": ") + ($list.to_english(obj.name_aliases(), "none")));
.
method activity
var idle;
// different from action, returns a broader version of your doings
if (!(.connected()))
return "asleep";
if (activity)
return activity;
idle = .idle_seconds();
if (idle < 180)
return "";
if (idle < 300)
return "daydreaming";
if (idle < 900)
return "zoned";
else
return "long gone";
.
method add_name_alias_cmd
arg com, [args];
var syn, obj, what;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender not this");
syn = ("`" + com) + " <alias> to <object>' (to <object> is optional)";
args = explode(args[1]);
what = args[1];
obj = .match_env_nice([@args, .dbref(), .dbref()][3]);
if (!what)
$parse.tell_error("You must name an alias.", syn);
if (what in (.name_aliases()))
$parse.tell_error(("You already have the name alias `" + what) + "'");
catch any {
obj.add_name_alias(what);
} with handler {
switch (error()) {
case ~methodnf:
$parse.tell_error((obj.namef('ref)) + " is not a descendant of $xxxxxxxxx", syn);
default:
$parse.tell_error((traceback()[1])[2], syn);
}
}
.tell(((("Name Alias `" + what) + "' added to ") + (obj.namef())) + ".");
.
method modes
return modes;
.
method del_name_alias_cmd
arg com, [args];
var syn, obj, what;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender not this");
syn = ("`" + com) + " <alias> from <object>' (from <object> is optional)";
args = explode(args[1]);
what = args[1];
obj = .match_env_nice([@args, .dbref(), .dbref()][3]);
if (!what)
$parse.tell_error("You must name an alias to delete.", syn);
if (!(what in (.name_aliases())))
$parse.tell_error((((obj.namef('ref)) + " doesn't have the name alias `") + what) + "'");
catch any {
obj.del_name_alias(what);
} with handler {
switch (error()) {
case ~methodnf:
$parse.tell_error((obj.namef('ref)) + " is not a descendant of $matchable", syn);
default:
$parse.tell_error((traceback()[1])[2], syn);
}
}
.tell(((((("Name Alias `" + what) + "' deleted from ") + (obj.namef())) + ", aliases are now: ") + ($list.to_english(.name_aliases()))) + ".");
.
method home
return home || $body_cave;
.
method set_dbref
arg new_dbref;
if ((caller() != $user) && (!(sender() in ($sys.system()))))
throw(~perm, "User dbrefs can only be changed by $user.");
(> pass(new_dbref) <);
.
method rename_cmd
arg com, what, prep, line;
var syn, x, article, name;
if (sender() != this())
throw(~perm, "Sender is not this");
syn = ((("`" + com) + " <object> ") + prep) + " <newname>'";
what = .match_env_nice(what);
if (!(what.has_ancestor($named)))
$parse.tell_error(("Object `" + ($data.unparse(what))) + "' is not descended from $named.", syn);
line = explode(line);
article = 'uniq;
for x in [1 .. listlen(line)] {
if (((line[x]) == "-prop") || (((line[x]) == "-p") || ((line[x]) == "-proper"))) {
article = 'prop;
line = delete(line, x);
break;
}
if (((line[x]) == "-uniq") || (((line[x]) == "-u") || ((line[x]) == "-unique"))) {
article = 'uniq;
line = delete(line, x);
break;
}
}
name = $list.to_string(line);
catch any {
what.set_name(name, article);
} with handler {
$parse.tell_error((traceback()[1])[2], syn);
}
.tell("Name is now: " + (what.name()));
.
method time_cmd
arg command, [args];
var rtime, itime, ptime;
.perms(sender(), 'parser);
// rtime = "Terran Time: " + $time.ltime('12hr, 'ampm) + " " +
$time.ltime();
rtime = "Terran Time: " + ctime();
itime = (("Ilraitheen Time: " + ($dark_time.ilraitheen_time())) + " day ") + tostr($dark_time.day());
ptime = "Paradisical Time: " + ($dark_time.paradise_time());
.tell([rtime, itime, ptime]);
.
method audit_cmd
arg com, [args];
var owner, obj, col, total, line, syntax, loc, size;
if (sender() != this())
throw(~perm, "Sender not this.");
syntax = "";
owner = (args[1]) ? args[1] | "me";
owner = .match_env_nice(owner, syntax);
if (!(owner.owned())) {
.tell(" None");
} else {
col = (.linelen()) / 2;
line = ("Objects owned by " + (owner.namef('ref))) + ":";
.tell((pad(line, col) + pad("bytes", -10)) + " Location");
for obj in (owner.owned()) {
if (!valid(obj)) {
.tell((" ** invalid object (" + toliteral(obj)) + ") **");
continue;
}
line = pad(" " + (obj.namef('ref)), col);
size = $integer.to_english(obj.size());
line = (line + pad(size, -((strlen(size) > 10) ? strlen(size) | 10))) + " ";
loc = (obj.has_ancestor($located)) ? ("[" + ((obj.location()).namef())) + "]" | "";
.tell(pad(line + loc, .linelen()));
total = total + (obj.size());
}
}
.tell(("Total usage: " + ($integer.to_english(total))) + " bytes");
size = owner.get_quota();
line = ("Total quota: " + ($integer.to_english(size))) + " bytes ";
line = ((line + "Remaining: ") + ($integer.to_english(size - total))) + " bytes";
.tell(line);
.
method login_notify
// called by .login, set items here that will 'notify' a user of varous
// different things, such as new mail, news, etc.
if ($news.new())
.tell("There is new News (use `news' to read it).");
if (.unread())
.tell("You have new mail (use `@Mm?ail on me' to list it).");
.mmail_lists_cmd("", "subscribed");
.
method _set_watch_logins
arg value;
if (sender() != this())
throw(~perm, "Invalid call to private method");
watch_logins = value;
.
method get_mode
arg mode;
// returns the variable for the mode
if (mode in dict_keys(modes))
return modes[mode];
throw(~modenf, ("Mode \"'" + tostr(mode)) + "\" is not found in the users dictionary");
.
method add_mode
arg mode, setting;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
if (type(mode) != 'symbol)
throw(~type, "Modes must be a symbol");
modes = dict_add(modes, mode, setting);
.
method news_cmd
arg [args];
(> .perms(sender(), 'parser) <);
$news.read_vrb("read", "news");
.
method del_mode
arg mode;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
if (mode in dict_keys(modes)) {
modes = dict_del(modes, mode);
return;
}
throw(~modenf, "Mode is not in users modes dictionary");
.
method add_command_alias_cmd
arg com, input;
var syn, alias, actual, tmpalias, tmpactual, num;
if (sender() != this())
throw(~perm, "Sender is not this");
input = explode(input, "\"");
// hell, i'll be nice and check for a few possibilities:
syn = com + " \"<alias>\" [to] \"<actual command>\"";
if (listlen(input) < 2)
$parse.tell_error("Not enough arguments (enclose each alias in quotes)", syn);
if (listlen(input) > 3)
$parse.tell_error("Too many arguments (enclose each alias in quotes)", syn);
// sort and get the alias and actual
if (listlen(input) == 3)
input = delete(input, 2);
alias = input[1];
actual = input[2];
// make sure the %foo's match up
tmpalias = alias;
tmpactual = actual;
while ("%" in tmpalias) {
num = tmpalias[("%" in tmpalias) + 1];
if (!toint(num))
$parse.tell_error("referece cards must be integers", syn);
num = "%" + num;
if (!(num in tmpactual))
$parse.tell_error("reference cards to not match up", syn);
tmpalias = strsub(tmpalias, num, "");
tmpactual = strsub(tmpactual, num, "");
}
if ("%" in tmpactual)
$parse.tell_error("reference cards do not match up", syn);
.add_command_alias(alias, actual);
.tell(((("New command alias \"" + alias) + "\" => \"") + actual) + "\" added.");
.
method del_command_alias_cmd
arg com, template;
if (sender() != this())
throw(~perm, "Sender is not this");
template = explode(template, "\"")[1];
catch ~aliasnf {
.del_command_alias(template);
} with handler {
$parse.tell_error(("No command alias is found matching the template \"" + template) + "\".");
}
.tell(("Command alias \"" + template) + "\" deleted.");
.
method command_aliases_cmd
arg com, what;
var aliases, a, line;
if (!what)
what = this();
else
what = .match_env_nice(what);
if ((what != this()) && (!(what.is_writable_by(this()))))
$parse.tell_error("You are not allowed to read the command aliases on " + (what.namef()));
.tell(("--- Command aliases on " + (what.namef('xref))) + ":");
aliases = what.command_aliases();
if (aliases) {
for a in (aliases) {
line = " " + pad(("\"" + (a[1])) + "\"", ((.linelen()) - 10) / 2);
.tell(((line + " => \"") + (a[2])) + "\"");
}
} else {
.tell(" <none>");
}
.tell("---");
.
method _tell
arg what;
var conn, line;
.perms(sender(), 'this);
if (type(what) == 'list) {
for line in (what)
._tell(line);
} else {
for conn in (connections)
conn.tell(what);
}
.
method add_filter
arg filter, [position];
if ((!(sender().has_ancestor($filters))) && (!(.is_writable_by(sender()))))
throw(~perms, "%O does not have permission to remove filters.", sender());
// do this in three steps, first make sure the posistion is valid,
// then check for it already, then figure its insert position.
position = [@position, 'first][1];
if (!(position in ['last, 'first]))
throw(~type, "Posistion types must be one of: 'last, 'first.");
// does it exist? If so remove it.
if (filter in filters)
filters = setremove(filters, filter);
// figure position
if (position == 'last)
position = listlen(filters) + 1;
else if (position == 'first)
position = 1;
filters = insert(filters, position, filter);
.
method del_filter
arg filter;
if ((!(sender().has_ancestor($filters))) && (!(.is_writable_by(sender()))))
throw(~perms, "%O does not have permission to remove filters.", sender());
if (filters) {
filters = setremove(filters, filter);
return;
} else {
throw(~nofilters, "You do not have any tell filters.");
}
.
method wrap_cmd
arg com, how;
var filters;
.perms(sender(), 'this);
if (!(how in ["on", "off"]))
return .tell("! You can either turn line wrapping `on' or `off'");
filters = .filters();
if (how == "on") {
if (filters && ($wrap_filter in filters))
return .tell("! You already have line wrapping on..");
.add_filter($wrap_filter);
return .tell("Line wrapping turned on.");
} else {
if (filters && (!($wrap_filter in filters)))
return .tell("! You dont have line wrapping turned on.");
.del_filter($wrap_filter);
return .tell("Line wrapping turned off.");
}
.
method filters
.perms(sender());
return filters;
.
method tell_traceback
arg traceback, [args];
var tt, name, eargs, error, str;
// tt = tell_traceback || ['verbose, 0, "! "];
str = [@args, ""][1];
eargs = [@args, 0, 0][2];
error = [@args, 0, 0, 0][3];
tt = ['verbose, -1, "! "];
switch (tt[1]) {
case 'verbose:
traceback = $parse.traceback(traceback, tt[2], tt[3], error);
if (args)
name = (| $list.to_english($list.map(args, 'namef, 'ref)) |);
if (!name)
name = "Object";
.tell(strsub(traceback[1], "%O", name));
.tell(sublist(traceback, 2));
default:
.tell(("! Internal error processing \"" + str) + "\", contact an administrator.");
}
.
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];
.
method namef
arg [args];
if (!args)
args = [['name]];
// first check for shortcuts, if so re-call this method correctly.
if ((args[1]) == 'nactivity) {
if (.activity())
args = [['name], " (", ['activity], ")"] + sublist(args, 2);
else
args = [['name]] + sublist(args, 2);
}
if ((args[1]) == 'titled) {
if (.title())
args = [['name], ", ", ['title]] + sublist(args, 2);
else
args = [['name]] + sublist(args, 2);
}
return pass(@args);
.
method get_prompt
return prompt;
.
method set_prompt
arg what;
.perms(sender(), 'this);
prompt = what;
.
method prompt_cmd
arg com, [args];
.perms(sender(), 'this);
if (!args)
args = [""];
.set_prompt(args[1]);
.tell(("Prompt set as \"" + (args[1])) + "\"");
.
method password_cmd
arg com, [args];
var syn;
.perms(sender(), 'parser);
syn = ("`" + com) + " <old password> <new password>'";
args = explode(@args);
if ((listlen(args) < 2) || (listlen(args) > 2))
$parse.tell_error("Not enough arguments specified (note: passwords cannot contain spaces).", syn);
if (!(.check_password(args[1])))
$parse.tell_error("Old password does not match up.", syn);
catch any {
.set_password(args[2]);
} with handler {
$parse.tell_error((traceback()[1])[2], syn);
}
.tell("Password changed.");
.
method set_title
arg str;
.perms(sender(), 'manager);
if (strlen(str) > 30)
throw(~type, "Titles must be under 30 characters.");
title = str;
.
method watch_logins_cmd
arg com, args;
args = explode(args);
if (!args)
return .tell("You must specify someone to watch (logging in/out).");
if ((args[1]) in ["all", "everybody", "everyone"]) {
.set_watch_logins(1);
.tell("You are now listening to login messages from everybody.");
} else if ((args[1]) in ["none", "noone"]) {
.set_watch_logins(0);
.tell("You are now ignoring login messages.");
} else {
.tell("nothing else on this command is progged yet.");
}
.
method delimited_tell
arg text;
var conn;
// will adjust perms etc later.
for conn in (.connections())
conn.enh_tell([text]);
.
method match_context
arg str;
return context[str];
.
method context
return context;
.
method match_environment
arg str;
var match, gend;
match = (> pass(str) <);
gend = (| match.gender() |);
if (gend)
context = dict_add(context, gend.pronoun('po), match);
return match;
.
method non_terminated_tell
arg text;
var conn;
if (.setting("terminated-tell")) {
for conn in (.connections())
conn.enh_tell([text]);
} else {
.tell(text);
}
.
method set_name
arg new_name, [ignore];
var old_name, part, sname;
.perms(sender(), 'manager);
// so it doesnt bomb on .set_dbref
if ((.namef()) == new_name)
return;
if ($user_db.valid_name(new_name))
old_name = .namef();
sname = $string.strip(new_name, $user_db.stripped_characters());
catch any {
pass(new_name);
$user_db.key_changed(old_name, new_name);
.set_dbref(tosym("user_" + sname));
} with handler {
(| pass(old_name) |);
rethrow(error());
}
.
method find_object_nice
arg str, [args];
var match;
catch any {
match = .find_object(str, @args);
} with handler {
.tell("! " + ((traceback()[1])[2]));
throw(~stop, "", 'no_traceback);
}
return match;
.
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.find(str) |);
case 'grasp:
match = (| $object.to_dbref(str) |);
}
if (match)
return match;
args = delete(args, 1);
}
throw(~objnf, ("No object found by the reference \"" + str) + "\".");
.
method creation_time
return creation_time;
.
method age_cmd
arg com, user;
var person, time;
.perms(sender(), 'parser);
person = (| $user_db.find(user) |);
if (!person) {
person = (| .match_environment(user) |);
if (!person)
return .tell(("No person can be found by the name \"" + user) + "\".");
}
time = person.creation_time();
.tell(((person.namef()) + " was created on ") + ($time.ldate(time)));
.tell(((((person.gender()).pronoun('psc)) + " is ") + ($time.elapsed(time() - time, 'long))) + " old.");
.
method spawn_cmd
arg com, args;
var syn, new_obj, moved, name, parent, builder;
if (sender() != this())
throw(~perm, "Sender not this.");
syn = ("`" + com) + " <parent> [named|called] <new object name>'";
args = explode(args);
builder = !($user in (.parents()));
if ((!args) || (((listlen(args) < 1) && builder) || (listlen(args) < 2)))
$parse.tell_error("Not enough arguments specified.", syn);
args = [@args, ""];
parent = args[1];
parent = .match_env_nice(parent, syn);
// users shouldn't be creating non VR objs.
if ((!(parent.has_ancestor($thing))) && (!builder))
$parse.tell_error("Parent is not a descendant of a Generic Thing ($thing).");
if (match_begin("named", args[2]) || match_begin("called", args[2]))
args = delete(args, 2);
name = $list.to_string(sublist(args, 2));
catch any {
new_obj = parent.spawn();
if (name) {
if (!(new_obj.has_ancestor($named)))
.tell("Object is not descended from $named.");
else
(> new_obj.set_name(name) <);
}
moved = (| new_obj.move_to(this()) |);
.tell(((("Object " + (new_obj.namef('ref))) + " spawned from ") + (parent.namef('ref))) + ".");
} with handler {
$parse.tell_error((traceback()[1])[2], syn);
}
.
method _prose_done
arg text, obj, which;
.perms(sender(), 'this);
(> obj.set_prose(which, text) <);
which = tostr(which);
.tell(((($string.capitalize(which)) + " prose description for ") + (obj.namef('ref))) + " set.");
.
method prose_cmd
arg cmd, args;
var syn, which, obj;
.perms(sender());
syn = ("`" + cmd) + " <object> [long|short]`";
args = explode(args);
obj = [@args, ""][1];
which = [@args, "short", "short"][2];
if (!(which in ["short", "long"]))
$parse.tell_error("Must either be \"short\" or \"long\" for the prose type.", syn);
which = tosym(which);
if (!obj)
$parse.tell_error("No object specified.", syn);
obj = .match_env_nice(obj);
if (!(obj.has_ancestor($described)))
$parse.tell_error((obj.namef('ref)) + " is not a describeable object!", syn);
if (!(| obj.perms(this()) |))
$parse.tell_error(("You do not have permission to write the prose description for " + (obj.namef('ref))) + ".", syn);
if (which == 'short) {
.prompt("Enter line: ", '_prose_done, obj, which);
} else {
.tell("Enter text for prose (end with a period or abort with `@abort`):");
.read('_prose_done, obj, which);
}
.
method status_cmd
arg com, [args];
var line;
(> .perms(sender(), 'this) <);
.tell(((($motd.server_name()) + ", ") + ($motd.server_title())) + ".");
.tell("Startup time: " + ($time.date($sys.startup_time())));
.tell((" (" + ($time.to_english($sys.uptime()))) + ")");
.tell("Last backup time: " + ($time.date($sys.last_backup())));
.tell("Driver: ColdMUD " + ($sys.version('driver)));
.tell("Core: the Cold Dark Core " + ($sys.version('core)));
.
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);
}
.
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, 'first);
}
.
method logout_connection
arg connection;
if ((sender() != this()) || (definer() != caller()))
throw(~perm, "Invalid access to private method.");
.tell(("* * * " + ($integer.n_to_nth(listlen(.connections()) + 1))) + " Logout sucessful * * *");
.
method tell_ctext
arg ctext, originator;
var output, type;
type = (.setting("content-type")) || "text/plain";
output = ctext.translate_to(type);
.tell(output);
.
method rehash_cmd
arg cmd;
.tell("Rehashing commands in your environment...");
.rehash_command_environment();
.