ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/commands.ext
Revision: 1.40
Committed: Fri Apr 13 05:32:12 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.39: +23 -0 lines
Log Message:
move seen to commands.ext and fix it while doing so

File Contents

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