ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/commands.ext
Revision: 1.56
Committed: Sun Jul 22 17:10:06 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.55: +3 -3 lines
Log Message:
fix mapinfo?

File Contents

# Content
1 #! perl # mandatory depends=irc
2
3 use POSIX ();
4
5 # miscellaneous commands
6
7 sub rename_to($$$) {
8 my ($ob, $from, $to) = @_;
9
10 $to =~ /^[a-zA-Z0-9.,=#\/%$!^ ]*$/
11 or return $ob->message ("rename: name must consist only of letters, digits, spaces and a few other things.");
12
13 127 >= length $to
14 or return $ob->message ("rename: new name must be <= 127 characters.");
15
16 my $item;
17
18 if (length $from) {
19 $item = $ob->find_best_object_match ($from)
20 or return $ob->message ("rename: could not find a matching item to rename.");
21 } else {
22 $item = $ob->find_marked_object
23 or return $ob->message ("rename: no from name and no marked item found to rename.");
24 }
25
26 $item->custom_name (length $to ? $to : undef);
27
28 if (length $to) {
29 $item->custom_name ($to);
30 $ob->message ("Your " . $item->base_name . " will now be called $to.");
31 } else {
32 $item->custom_name (undef);
33 $ob->message ("You stop calling your " . $item->base_name . " with weird names.");
34 }
35
36 $ob->esrv_update_item (cf::UPD_NAME, $item);
37
38 1
39 }
40
41 sub who_listing(;$$) {
42 my ($privileged, $select) = @_;
43
44 my ($numwiz, $numafk) = (0, 0);
45 my @pl;
46
47 foreach my $pl (cf::player::list) {
48 my $ns = $pl->ns or next;
49 my $ob = $pl->ob;
50
51 next unless $ob->map
52 && ($privileged || !$pl->hidden);
53
54 $numwiz++ if $ob->flag (cf::FLAG_WIZ);
55 $numafk++ if $ns->afk;
56
57 push @pl, $pl;
58 }
59
60 (
61 "Total Players in The World. (" . (scalar @pl) . ") -- WIZ($numwiz) AFK($numafk) BOT(0)",
62 (grep /$select/,
63 map {
64 my ($pl, $ob, $ns) = ($_, $_->ob, $_->ns);
65
66 "* " . $ob->name . "/" . $ob->level . " " . (length $pl->own_title ? $pl->own_title : "the " . $pl->title)
67 . ($pl->gender ? " [f]" : " [m]")
68 . ($pl->peaceful ? " [peaceful]" : " [HOSTILE]")
69 . ($ns->afk ? " [AFK]" : "")
70 . ($ob->flag (cf::FLAG_WIZ) ? " [WIZ]" : "")
71 . " [" . $pl->ns->version . "]"
72 . " [" . ($pl->peaceful || $privileged ? $ob->map->visible_name : $ob->region->name) . "]"
73 . (sprintf " [rtt %.3fs]", $pl->ns->rtt * 1e-6)
74 . ($privileged ? " " . $pl->ns->host : "")
75 } sort { (lc $a->ob->name) cmp (lc $b->ob->name) } @pl
76 ),
77 eval { "* IRC: " . join ", ", ext::irc::users },
78 )
79 }
80
81 cf::register_command who => sub {
82 my ($ob, $arg) = @_;
83
84 $ob->speed_left ($ob->speed_left - 4);
85
86 $ob->reply (undef, (join "\n", who_listing $ob->may ("extended_who"), $arg), cf::NDI_UNIQUE | cf::NDI_DK_ORANGE);
87
88 1
89 };
90
91 cf::register_command seen => sub {
92 my ($pl, $args) = @_;
93
94 if (my ($login) = $args =~ /(\S+)/) {
95 if ($login eq $pl->name) {
96 $pl->message ("Very funny, $login. Ha. Ha.", cf::NDI_UNIQUE);
97 } elsif (cf::player::find_active $login) {
98 $pl->message ("$login is right here on this server!", cf::NDI_UNIQUE);
99 } elsif (cf::player::exists $login
100 and stat cf::player::path $login) {
101 my $time = (stat _)[9];
102
103 $pl->message ("$login was last seen here "
104 . (POSIX::strftime "%Y-%m-%d %H:%M:%S +0000", gmtime $time)
105 . " which was " . (int +(time - $time) / 3600) . " hours ago.", cf::NDI_UNIQUE);
106 } else {
107 $pl->message ("No player named $login is known to me.", cf::NDI_UNIQUE);
108 }
109 } else {
110 $pl->message ("Usage: seen <player>", cf::NDI_UNIQUE);
111 }
112 };
113
114 cf::register_command body => sub {
115 my ($ob) = @_;
116
117 # Too hard to try and make a header that lines everything up, so just
118 # give a description. (comment from C++)
119 my $reply =
120 "The first column is the name of the body location.\n\n"
121 . "The second column is how many of those locations your body has.\n\n"
122 . "The third column is how many slots in that location are available.\n\n";
123
124 $reply .= sprintf " %-20s %3s %5s\n", "Location", "You", "Avail";
125 for (0 .. cf::NUM_BODY_LOCATIONS - 1) {
126 my $msg = cf::object::slot_nonuse_name $_;
127 $msg =~ s/^.*? a //;
128 $reply .= sprintf " %-20s %3d %5d\n", $msg, $ob->slot_info ($_), $ob->slot_used ($_)
129 if $ob->slot_info ($_) or $ob->slot_used ($_);
130 }
131
132 $reply .= "You are not allowed to wear armor\n\n"
133 unless $ob->flag (cf::FLAG_USE_ARMOUR);
134 $reply .= "You are not allowed to use weapons\n\n"
135 unless $ob->flag (cf::FLAG_USE_WEAPON);
136
137 $ob->reply (undef, $reply);
138
139 1
140 };
141
142 cf::register_command mark => sub {
143 my ($pl, $arg) = @_;
144
145 if (length $arg) {
146 my $ob = $pl->find_best_object_match ($arg);
147
148 return $pl->reply (undef, "Could not find an object that matches $arg")
149 unless $ob;
150
151 $pl->contr->mark ($ob);
152 $pl->reply (undef, (sprintf "Marked item %s", $ob->name, $ob->title));
153 } else {
154 my $ob = $pl->find_marked_object;
155
156 $pl->reply (undef, $ob
157 ? (sprintf "%s %s * is marked.", $ob->name, $ob->title)
158 : "You have no marked object.");
159 }
160
161 1
162 };
163
164 for my $cmd ("run", "fire") {
165 my $oncmd = "${cmd}_on";
166 cf::register_command $cmd => sub {
167 my ($ob, $arg) = @_;
168
169 $ob->reply (undef, "Can't $cmd into a non adjacent square.")
170 if $arg < 0 or $arg >= 9;
171
172 $ob->contr->$oncmd (1);
173 $ob->move_player ($arg);
174
175 1
176 };
177
178 cf::register_command "${cmd}_stop" => sub {
179 my ($ob) = @_;
180
181 $ob->contr->$oncmd (0);
182
183 1
184 };
185 }
186
187 cf::register_command mapinfo => sub {
188 my ($ob) = @_;
189
190 my $observe = $ob->contr->observe;
191
192 my $map = $observe->map
193 or return;
194 $ob->reply (undef, (sprintf "%s (%s) %s", $map->name, $map->path, $observe->region->longname));
195 $ob->reply (undef, (sprintf "players: %d difficulty: %d size: %d start: %dx%d timeout: %d",
196 (scalar $map->players), $map->difficulty, $map->width, $map->height, $map->enter_x, $map->enter_y, $map->timeout))
197 if $ob->flag (cf::FLAG_WIZ);
198 $ob->reply (undef, $map->msg);
199
200 1
201 };
202
203 cf::register_command whereami => sub {
204 my ($ob) = @_;
205
206 my $reg = $ob->contr->observe->region;
207 $ob->reply (undef, (sprintf "You are %s.\n%s", $reg->longname, $reg->msg));
208
209 1
210 };
211
212 sub _set_mode($$$@) {
213 my ($name, $ob, $arg, $slot, @choices) = @_;
214
215 my $oldmode = $ob->contr->$slot;
216
217 return $ob->reply (undef, "$name is set to $choices[$oldmode]")
218 unless $arg;
219
220 my ($idx) = grep $choices[$_] eq $arg, 0 .. $#choices
221 or return $ob->reply (undef, "$name: Unknown options '$arg', valid options are @choices"), 1;
222
223 $ob->contr->$slot ($idx);
224 $ob->reply (undef, "$name" . ($oldmode == $ob->contr->unapply ? "" : " now") . " set to " . $choices[$ob->contr->$slot]);
225 }
226
227 cf::register_command applymode => sub {
228 my ($ob, $arg) = @_;
229
230 _set_mode "applymode", $ob, $arg, unapply => qw(nochoice never always);
231
232 1
233 };
234
235 cf::register_command petmode => sub {
236 my ($ob, $arg) = @_;
237
238 _set_mode "petmode", $ob, $arg, petmode => qw(normal sad defend arena);
239
240 1
241 };
242
243 cf::register_command usekeys => sub {
244 my ($ob, $arg) = @_;
245
246 _set_mode "usekeys", $ob, $arg, usekeys => qw(inventory keyrings containers);
247
248 1
249 };
250
251 cf::register_command hintmode => sub {
252 my ($ob, $arg) = @_;
253
254 _set_mode "hintmode", $ob, $arg, hintmode => qw(show mark hide);
255
256 1
257 };
258
259 cf::register_command afk => sub {
260 my ($ob, $arg) = @_;
261
262 $ob->contr->ns->afk ($ob->contr->ns->afk ? 0 : 1);
263 $ob->reply (undef, $ob->contr->ns->afk ? "You are now AFK" : "You are no longer AFK");
264
265 1
266 };
267
268 cf::register_command sound => sub {
269 my ($ob, $arg) = @_;
270
271 $ob->contr->ns->sound ($ob->contr->ns->sound ? 0 : 1);
272 $ob->reply (undef, $ob->contr->ns->sound ? "The sounds are enabled." : "Silence is golden...");
273
274 1
275 };
276
277 cf::register_command brace => sub {
278 my ($ob, $arg) = @_;
279
280 $ob->contr->braced ($ob->contr->braced ? 0 : 1);
281 $ob->reply (undef, $ob->contr->braced ? "You are braced." : "Not braced.");
282
283 1
284 };
285
286 cf::register_command 'output-rate' => sub {
287 my ($ob, $arg) = @_;
288
289 return $ob->reply (undef, sprintf "Output rate is presently %dbps.", $ob->contr->ns->max_rate / $cf::TICK)
290 unless $arg > 0;
291
292 # minimum is 5k/s
293 $ob->contr->ns->max_rate ((List::Util::max 5000, $arg) * $cf::TICK);
294 $ob->reply (undef, sprintf "Output rate now set to %dbps.", $ob->contr->ns->max_rate / $cf::TICK);
295
296 1
297 };
298
299 cf::register_command 'output-count' => sub {
300 my ($ob, $arg) = @_;
301
302 return $ob->reply (undef, "Output count is presently " . $ob->contr->outputs_count)
303 unless $arg > 0;
304
305 $arg = 4 if $arg < 4;
306
307 $ob->contr->outputs_count ($arg);
308 $ob->reply (undef, "Output count now set to " . $ob->contr->outputs_count);
309
310 1
311 };
312
313 cf::register_command 'output-sync' => sub {
314 my ($ob, $arg) = @_;
315
316 return $ob->reply (undef, sprintf "Output sync time is presently %.1fs", $ob->contr->outputs_sync * $cf::TICK)
317 unless length $arg;
318
319 $arg = 0.5 if $arg < 0.5;
320
321 $ob->contr->outputs_sync ($arg / $cf::TICK);
322 $ob->reply (undef, sprintf "Output sync time now set to %.1fs", $ob->contr->outputs_sync * $cf::TICK);
323
324 1
325 };
326
327 # XXX: This has a bug. After one sets his wimpy level to 0 and resets it to
328 # some other level (which may also be 0), this does not get echoed,
329 # but it does get set.
330 cf::register_command wimpy => sub {
331 my ($ob, $arg) = @_;
332
333 my $wimpy = $ob->run_away;
334 return $ob->reply (undef, "Your current wimpy level is $wimpy.")
335 if $arg eq "";
336
337 return $ob->run_away ($arg) && $ob->reply (undef, "Your new wimpy level is $arg.")
338 if $arg =~ /^\d+$/ and $arg <= 100;
339
340 $ob->reply (undef, "Incorrect parameters for wimpy: $arg");
341
342 1
343 };
344
345 cf::register_command peaceful => sub {
346 my ($ob, $arg) = @_;
347
348 $ob->reply (undef, "You cannot change your peaceful setting with this command."
349 ." Please speak to the priest in the temple of Gorokh"
350 ." if you want to become hostile or in temple of Valriel"
351 ." if you want to become peaceful again.");
352
353 #$ob->contr->peaceful ($ob->contr->peaceful ? 0 : 1);
354 #$ob->reply (undef, $ob->contr->peaceful ? "You will attack other players." : "You will not attack other players.");
355
356 1
357 };
358
359 cf::register_command rename => sub {
360 my ($ob, $arg) = @_;
361
362 $ob->speed_left ($ob->speed_left - 0.25);
363
364 if ($arg =~ /^\s* (?: <([^>]+)> \s+)? to \s+ <([^>]*)> \s*$/x) {
365 # compatibility syntax
366 rename_to $ob, $1, $2;
367 } elsif ($arg =~ /
368 ^\s*
369 (?:
370 (?: "((?:[^"]+|\\.)*)" | (\S+) )
371 \s+)?
372 to \s+
373 (?: "((?:[^"]+|\\.)*)" | (\S+) )
374 \s*$
375 /x) {
376 # does not unquote $1 or $3
377 rename_to $ob, $2||$1, $4||$3;
378 } else {
379 $ob->reply (undef, 'Syntax error. Rename usage: rename ["oldname"] to "newname"');
380 }
381
382 1
383 };
384
385 cf::register_command uptime => sub {
386 my ($ob, $arg) = @_;
387
388 my $startup = POSIX::strftime "%Y-%m-%d %H:%M:%S %Z", localtime $cf::UPTIME;
389 my $runtime = sprintf "%.1f", (time - $cf::UPTIME) / 86400;
390 $ob->reply (undef, "server started $startup, uptime ${runtime}\d");
391
392 1
393 };
394
395 my %IN_MEMORY = (
396 cf::MAP_IN_MEMORY => "I",
397 cf::MAP_SWAPPED => "S",
398 cf::MAP_LOADING => "L",
399 );
400
401 cf::register_command maps => sub {
402 my ($ob, $arg) = @_;
403
404 no re 'eval'; $arg = qr<$arg>;
405
406 my $format = "%2s %1s %3s %5s %.60s\n";
407
408 $ob->reply (undef, (sprintf $format, "Pl", "I", "Svd", "Reset", "Name"), cf::NDI_BLACK | cf::NDI_UNIQUE);
409
410 for (sort keys %cf::MAP) {
411 my $map = $cf::MAP{$_}
412 or next;
413
414 next unless $map->path =~ $arg;
415 next if $map->{deny_list};
416
417 my $svd = int $cf::RUNTIME - $map->{last_save};
418 $svd = "++" if $svd > 99;
419
420 $ob->reply (undef,
421 (sprintf $format,
422 (scalar $map->players),
423 $IN_MEMORY{$map->in_memory} || "?",
424 $svd,
425 (int $map->reset_at - $cf::RUNTIME),
426 $map->visible_name),
427 cf::NDI_BLACK | cf::NDI_UNIQUE);
428 }
429
430 1
431 };
432