#! perl use POSIX (); # miscellaneous commands sub rename_to($$$) { my ($ob, $from, $to) = @_; $to =~ /^[a-zA-Z0-9.,=#\/%$!^ ]*$/ or return $ob->message ("rename: name must consist only of letters, digits, spaces and a few other things."); 127 >= length $to or return $ob->message ("rename: new name must be <= 127 characters."); my $item; if (length $from) { $item = $ob->find_best_object_match ($from) or return $ob->message ("rename: could not find a matching item to rename."); } else { $item = $ob->find_marked_object or return $ob->message ("rename: no from name and no marked item found to rename."); } $item->custom_name (length $to ? $to : undef); if (length $to) { $item->custom_name ($to); $ob->message ("Your " . $item->base_name . " will now be called $to."); } else { $item->custom_name (undef); $ob->message ("You stop calling your " . $item->base_name . " with weird names."); } $ob->esrv_update_item (cf::UPD_NAME, $item); 1 } sub ext::schmorp_irc::users; # HACK: TODO: replace by signal sub who_listing(;$) { my ($privileged) = @_; my ($numwiz, $numafk) = (0, 0); my @pl; foreach my $pl (cf::player::list) { my $ns = $pl->ns or next; my $ob = $pl->ob; next unless $ob->map && ($privileged || !$pl->hidden); $numwiz++ if $ob->flag (cf::FLAG_WIZ); $numafk++ if $ns->afk; push @pl, $pl; } ( "Total Players in The World. (" . (scalar @pl) . ") -- WIZ($numwiz) AFK($numafk) BOT(0)", ( map { my ($pl, $ob, $ns) = ($_, $_->ob, $_->ns); "* " . $ob->name . "/" . $ob->level . " " . (length $pl->own_title ? $pl->own_title : "the " . $pl->title) . ($pl->peaceful ? " [peaceful]" : " [HOSTILE]") . ($ns->afk ? " [AFK]" : "") . ($ob->flag (cf::FLAG_WIZ) ? " [WIZ]" : "") . " [" . $pl->ns->version . "]" . " [" . ($pl->peaceful || $privileged ? $ob->map->visible_name : $ob->region->name) . "]" . (sprintf " [rtt %.3fs]", $pl->ns->rtt * 1e-6) . ($privileged ? " " . $pl->ns->host : "") } sort { (lc $a->ob->name) cmp (lc $b->ob->name) } @pl ), eval { "* IRC: " . join ", ", ext::schmorp_irc::users }, ) } cf::register_command who => sub { my ($ob, $arg) = @_; $ob->speed_left ($ob->speed_left - 0.25); $ob->reply (undef, (join "\n", who_listing $ob->may ("extended_who")), cf::NDI_UNIQUE | cf::NDI_DK_ORANGE); 1 }; cf::register_command body => sub { my ($ob) = @_; my @body_locations = ("in your range slot", "on your arm", "on your body", "on your head", "around your neck", "in your skill slot", "on your finger", "around your shoulders", "on your feet", "on your hands", "around your wrists", "around your waist"); # Too hard to try and make a header that lines everything up, so just # give a description. (comment from C++) $ob->reply (undef, "The first column is the name of the body location."); $ob->reply (undef, "The second column is how many of those locations your body has."); $ob->reply (undef, "The third column is how many slots in that location are available."); for (0 .. scalar @body_locations - 1) { $ob->reply (undef, (sprintf "%-30s %5d %5d", $body_locations[$_], $ob->body_info($_), $ob->body_used($_))) if $ob->body_info($_) or $ob->body_used($_); } $ob->reply (undef, "You are not allowed to wear armor") unless $ob->flag (cf::FLAG_USE_ARMOUR); $ob->reply (undef, "You are not allowed to use weapons") unless $ob->flag (cf::FLAG_USE_WEAPON); 1 }; cf::register_command mark => sub { my ($pl, $arg) = @_; if (length $arg) { my $ob = $pl->find_best_object_match ($arg); return $pl->reply (undef, "Could not find an object that matches $arg") unless $ob; $pl->contr->mark ($ob); $pl->reply (undef, (sprintf "Marked item %s", $ob->name, $ob->title)); } else { my $ob = $pl->find_marked_object; $pl->reply (undef, $ob ? (sprintf "%s %s * is marked.", $ob->name, $ob->title) : "You have no marked object."); } 1 }; cf::register_command who => sub { my ($ob, $arg) = @_; $ob->speed_left ($ob->speed_left - 0.25); $ob->reply (undef, (join "\n", who_listing $ob->may ("extended_who")), cf::NDI_UNIQUE | cf::NDI_DK_ORANGE); 1 }; for my $cmd ("run", "fire") { my $oncmd = "${cmd}_on"; cf::register_command $cmd => sub { my ($ob, $arg) = @_; $ob->contr->$oncmd (1); return $ob->reply (undef, "Can't $cmd into a non adjacent square.") if $arg < 0 or $arg >= 9; $ob->move ($arg); 1 }; cf::register_command "${cmd}_stop" => sub { my ($ob) = @_; $ob->contr->$oncmd (0); 1 }; } cf::register_command mapinfo => sub { my ($ob) = @_; my $map = $ob->map or return; $ob->reply (undef, (sprintf "%s (%s) %s", $map->name, $map->path, $ob->region->longname)); $ob->reply (undef, (sprintf "players: %d difficulty: %d size: %d start: %dx%d timeout: %d", $map->players, $map->difficulty, $map->width, $map->height, $map->enter_x, $map->enter_y, $map->timeout)) if $ob->flag (cf::FLAG_WIZ); $ob->reply (undef, $map->msg); 1 }; cf::register_command whereami => sub { my ($ob) = @_; my $reg = $ob->region; $ob->reply (undef, (sprintf "You are %s.\n%s", $reg->longname, $reg->msg)); 1 }; sub _set_mode($$$@) { my ($name, $ob, $arg, $slot, @choices) = @_; my $oldmode = $ob->contr->$slot; return $ob->reply (undef, "$name is set to $choices[$oldmode]") unless $arg; my ($idx) = grep $choices[$_] eq $arg, 0 .. $#choices or return $ob->reply (undef, "$name: Unknown options '$arg', valid options are @choices"), 1; $ob->contr->$slot ($idx); $ob->reply (undef, "$name" . ($oldmode == $ob->contr->unapply ? "" : " now") . " set to " . $choices[$ob->contr->$slot]); } cf::register_command applymode => sub { my ($ob, $arg) = @_; _set_mode "applymode", $ob, $arg, unapply => qw(nochoice never always); 1 }; cf::register_command petmode => sub { my ($ob, $arg) = @_; _set_mode "petmode", $ob, $arg, petmode => qw(normal sad defend arena); 1 }; cf::register_command usekeys => sub { my ($ob, $arg) = @_; _set_mode "usekeys", $ob, $arg, usekeys => qw(inventory keyrings containers); 1 }; cf::register_command afk => sub { my ($ob, $arg) = @_; $ob->contr->ns->afk ($ob->contr->ns->afk ? 0 : 1); $ob->reply (undef, $ob->contr->ns->afk ? "You are now AFK" : "You are no longer AFK"); 1 }; cf::register_command sound => sub { my ($ob, $arg) = @_; $ob->contr->ns->sound ($ob->contr->ns->sound ? 0 : 1); $ob->reply (undef, $ob->contr->ns->sound ? "The sounds are enabled." : "Silence is golden..."); 1 }; cf::register_command brace => sub { my ($ob, $arg) = @_; $ob->contr->braced ($ob->contr->braced ? 0 : 1); $ob->reply (undef, $ob->contr->braced ? "You are braced." : "Not braced."); 1 }; cf::register_command 'output-count' => sub { my ($ob, $arg) = @_; return $ob->reply (undef, "Output count is presently " . $ob->contr->outputs_count) unless $arg > 0; $ob->contr->outputs_count ($arg); $ob->reply (undef, "Output count now set to " . $ob->contr->outputs_count); 1 }; cf::register_command 'output-sync' => sub { my ($ob, $arg) = @_; return $ob->reply (undef, "Output sync time is presently " . $ob->contr->outputs_sync) unless $arg > 0; $ob->contr->outputs_sync ($arg); $ob->reply (undef, "Output sync time now set to " . $ob->contr->outputs_sync); 1 }; # XXX: This has a bug. After one sets his wimpy level to 0 and resets it to # some other level (which may also be 0), this does not get echoed, # but it does get set. cf::register_command wimpy => sub { my ($ob, $arg) = @_; my $wimpy = $ob->run_away; return $ob->reply (undef, "Your current wimpy level is $wimpy.") if $arg eq ""; return $ob->run_away ($arg) && $ob->reply (undef, "Your new wimpy level is $arg.") if $arg =~ /^\d+$/ and $arg <= 100; $ob->reply (undef, "Incorrect parameters for wimpy: $arg"); 1 }; cf::register_command peaceful => sub { my ($ob, $arg) = @_; $ob->reply (undef, "You cannot change your peaceful setting with this command." ." Please speak to the priest in the temple of Gorokh" ." if you want to become hostile or in temple of Valriel" ." if you want to become peaceful again."); #$ob->contr->peaceful ($ob->contr->peaceful ? 0 : 1); #$ob->reply (undef, $ob->contr->peaceful ? "You will attack other players." : "You will not attack other players."); 1 }; cf::register_command rename => sub { my ($ob, $arg) = @_; $ob->speed_left ($ob->speed_left - 0.25); if ($arg =~ /^\s* (?: <([^>]+)> \s+)? to \s+ <([^>]*)> \s*$/x) { # compatibility syntax rename_to $ob, $1, $2; } elsif ($arg =~ / ^\s* (?: (?: "((?:[^"]+|\\.)*)" | (\S+) ) \s+)? to \s+ (?: "((?:[^"]+|\\.)*)" | (\S+) ) \s*$ /x) { # does not unquote $1 or $3 rename_to $ob, $2||$1, $4||$3; } else { $ob->reply (undef, 'Syntax error. Rename usage: rename ["oldname"] to "newname"'); } 1 }; cf::register_command uptime => sub { my ($ob, $arg) = @_; my $startup = POSIX::strftime "%Y-%m-%d %H:%M:%S %Z", localtime $cf::UPTIME; my $runtime = sprintf "%.1f", (time - $cf::UPTIME) / 86400; $ob->reply (undef, "server started $startup, uptime ${runtime}\d"); 1 }; my %IN_MEMORY = ( cf::MAP_IN_MEMORY => "I", cf::MAP_SWAPPED => "S", cf::MAP_LOADING => "L", ); cf::register_command maps => sub { my ($ob, $arg) = @_; no re 'eval'; $arg = qr<$arg>; my $format = "%2s %1s %3s %5s %.60s\n"; $ob->reply (undef, (sprintf $format, "Pl", "I", "Svd", "Reset", "Name"), cf::NDI_BLACK | cf::NDI_UNIQUE); for (sort keys %cf::MAP) { my $map = $cf::MAP{$_} or next; next unless $map->path =~ $arg; next if $map->{deny_list}; my $svd = int $cf::RUNTIME - $map->{last_save}; $svd = "++" if $svd > 99; $ob->reply (undef, (sprintf $format, (scalar $map->players), $IN_MEMORY{$map->in_memory} || "?", $svd, (int $map->reset_at - $cf::RUNTIME), $map->visible_name), cf::NDI_BLACK | cf::NDI_UNIQUE); } 1 };