ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.102
Committed: Wed Dec 27 15:20:54 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.101: +23 -20 lines
Log Message:
doh

File Contents

# User Rev Content
1 root 1.1 package cf;
2    
3 root 1.96 use utf8;
4     use strict;
5    
6 root 1.1 use Symbol;
7     use List::Util;
8 root 1.6 use Storable;
9 root 1.23 use Opcode;
10     use Safe;
11     use Safe::Hole;
12 root 1.19
13 root 1.96 use Coro;
14     use Coro::Event;
15     use Coro::Timer;
16     use Coro::Signal;
17     use Coro::Semaphore;
18    
19 root 1.99 use IO::AIO 2.3;
20 root 1.72 use YAML::Syck ();
21 root 1.32 use Time::HiRes;
22 root 1.96
23     use Event; $Event::Eval = 1; # no idea why this is required, but it is
24 root 1.1
25 root 1.72 # work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
26     $YAML::Syck::ImplicitUnicode = 1;
27    
28 root 1.96 $Coro::main->prio (Coro::PRIO_MIN);
29 root 1.1
30 root 1.87 sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload
31    
32 root 1.85 our %COMMAND = ();
33     our %COMMAND_TIME = ();
34     our %EXTCMD = ();
35    
36 root 1.1 our @EVENT;
37 root 1.88 our $LIBDIR = datadir . "/ext";
38 root 1.1
39 root 1.35 our $TICK = MAX_TIME * 1e-6;
40     our $TICK_WATCHER;
41     our $NEXT_TICK;
42    
43 root 1.70 our %CFG;
44    
45 root 1.84 our $UPTIME; $UPTIME ||= time;
46 root 1.76
47 root 1.70 #############################################################################
48    
49     =head2 GLOBAL VARIABLES
50    
51     =over 4
52    
53 root 1.83 =item $cf::UPTIME
54    
55     The timestamp of the server start (so not actually an uptime).
56    
57 root 1.70 =item $cf::LIBDIR
58    
59     The perl library directory, where extensions and cf-specific modules can
60     be found. It will be added to C<@INC> automatically.
61    
62     =item $cf::TICK
63    
64     The interval between server ticks, in seconds.
65    
66     =item %cf::CFG
67    
68     Configuration for the server, loaded from C</etc/crossfire/config>, or
69     from wherever your confdir points to.
70    
71     =back
72    
73     =cut
74    
75 root 1.1 BEGIN {
76     *CORE::GLOBAL::warn = sub {
77     my $msg = join "", @_;
78     $msg .= "\n"
79     unless $msg =~ /\n$/;
80    
81     print STDERR "cfperl: $msg";
82     LOG llevError, "cfperl: $msg";
83     };
84     }
85    
86 root 1.93 @safe::cf::global::ISA = @cf::global::ISA = 'cf::attachable';
87     @safe::cf::object::ISA = @cf::object::ISA = 'cf::attachable';
88     @safe::cf::player::ISA = @cf::player::ISA = 'cf::attachable';
89     @safe::cf::client::ISA = @cf::client::ISA = 'cf::attachable';
90     @safe::cf::map::ISA = @cf::map::ISA = 'cf::attachable';
91 root 1.41 @safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
92 root 1.25
93 root 1.41 # we bless all objects into (empty) derived classes to force a method lookup
94 root 1.25 # within the Safe compartment.
95 root 1.86 for my $pkg (qw(
96 root 1.100 cf::global cf::attachable
97 root 1.86 cf::object cf::object::player
98 root 1.89 cf::client cf::player
99 root 1.86 cf::arch cf::living
100     cf::map cf::party cf::region
101     )) {
102 root 1.25 no strict 'refs';
103 root 1.41 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
104 root 1.25 }
105 root 1.1
106 root 1.18 $Event::DIED = sub {
107     warn "error in event callback: @_";
108     };
109    
110 root 1.5 my %ext_pkg;
111 root 1.1 my @exts;
112     my @hook;
113    
114 root 1.70 =head2 UTILITY FUNCTIONS
115    
116     =over 4
117    
118     =cut
119 root 1.44
120 root 1.45 use JSON::Syck (); # TODO# replace by JSON::PC once working
121 root 1.44
122 root 1.70 =item $ref = cf::from_json $json
123    
124     Converts a JSON string into the corresponding perl data structure.
125    
126     =cut
127    
128 root 1.45 sub from_json($) {
129     $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs
130     JSON::Syck::Load $_[0]
131 root 1.44 }
132    
133 root 1.70 =item $json = cf::to_json $ref
134    
135     Converts a perl data structure into its JSON representation.
136    
137     =cut
138    
139 root 1.45 sub to_json($) {
140     $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs
141     JSON::Syck::Dump $_[0]
142 root 1.44 }
143    
144 root 1.70 =back
145    
146 root 1.71 =cut
147    
148 root 1.44 #############################################################################
149 root 1.39
150 root 1.93 =head2 ATTACHABLE OBJECTS
151    
152 root 1.94 Many objects in crossfire are so-called attachable objects. That means you can
153     attach callbacks/event handlers (a collection of which is called an "attachment")
154     to it. All such attachable objects support the following methods.
155    
156     In the following description, CLASS can be any of C<global>, C<object>
157     C<player>, C<client> or C<map> (i.e. the attachable objects in
158     crossfire+).
159 root 1.55
160     =over 4
161    
162 root 1.94 =item $attachable->attach ($attachment, key => $value...)
163    
164     =item $attachable->detach ($attachment)
165    
166     Attach/detach a pre-registered attachment to a specific object and give it
167     the specified key/value pairs as arguments.
168    
169     Example, attach a minesweeper attachment to the given object, making it a
170     10x10 minesweeper game:
171 root 1.46
172 root 1.94 $obj->attach (minesweeper => width => 10, height => 10);
173 root 1.53
174 root 1.93 =item $bool = $attachable->attached ($name)
175 root 1.46
176 root 1.93 Checks wether the named attachment is currently attached to the object.
177 root 1.46
178 root 1.94 =item cf::CLASS->attach ...
179 root 1.46
180 root 1.94 =item cf::CLASS->detach ...
181 root 1.92
182 root 1.94 Define an anonymous attachment and attach it to all objects of the given
183     CLASS. See the next function for an explanation of its arguments.
184 root 1.92
185 root 1.93 You can attach to global events by using the C<cf::global> class.
186 root 1.92
187 root 1.94 Example, log all player logins:
188    
189     cf::player->attach (
190     on_login => sub {
191     my ($pl) = @_;
192     ...
193     },
194     );
195    
196     Example, attach to the jeweler skill:
197    
198     cf::object->attach (
199     type => cf::SKILL,
200     subtype => cf::SK_JEWELER,
201     on_use_skill => sub {
202     my ($sk, $ob, $part, $dir, $msg) = @_;
203     ...
204     },
205     );
206    
207     =item cf::CLASS::attachment $name, ...
208    
209     Register an attachment by C<$name> through which attachable objects of the
210     given CLASS can refer to this attachment.
211    
212     Some classes such as crossfire maps and objects can specify attachments
213     that are attached at load/instantiate time, thus the need for a name.
214    
215     These calls expect any number of the following handler/hook descriptions:
216 root 1.46
217     =over 4
218    
219     =item prio => $number
220    
221     Set the priority for all following handlers/hooks (unless overwritten
222     by another C<prio> setting). Lower priority handlers get executed
223     earlier. The default priority is C<0>, and many built-in handlers are
224     registered at priority C<-1000>, so lower priorities should not be used
225     unless you know what you are doing.
226    
227 root 1.93 =item type => $type
228    
229     (Only for C<< cf::object->attach >> calls), limits the attachment to the
230     given type of objects only (the additional parameter C<subtype> can be
231     used to further limit to the given subtype).
232    
233 root 1.46 =item on_I<event> => \&cb
234    
235     Call the given code reference whenever the named event happens (event is
236     something like C<instantiate>, C<apply>, C<use_skill> and so on, and which
237     handlers are recognised generally depends on the type of object these
238     handlers attach to).
239    
240     See F<include/eventinc.h> for the full list of events supported, and their
241     class.
242    
243     =item package => package::
244    
245     Look for sub functions of the name C<< on_I<event> >> in the given
246     package and register them. Only handlers for eevents supported by the
247     object/class are recognised.
248    
249     =back
250    
251 root 1.94 Example, define an attachment called "sockpuppet" that calls the given
252     event handler when a monster attacks:
253    
254     cf::object::attachment sockpuppet =>
255     on_skill_attack => sub {
256     my ($self, $victim) = @_;
257     ...
258     }
259     }
260    
261 root 1.96 =item $attachable->valid
262    
263     Just because you have a perl object does not mean that the corresponding
264     C-level object still exists. If you try to access an object that has no
265     valid C counterpart anymore you get an exception at runtime. This method
266     can be used to test for existence of the C object part without causing an
267     exception.
268    
269 root 1.39 =cut
270    
271 root 1.40 # the following variables are defined in .xs and must not be re-created
272 root 1.100 our @CB_GLOBAL = (); # registry for all global events
273     our @CB_ATTACHABLE = (); # registry for all attachables
274     our @CB_OBJECT = (); # all objects (should not be used except in emergency)
275     our @CB_PLAYER = ();
276     our @CB_CLIENT = ();
277     our @CB_TYPE = (); # registry for type (cf-object class) based events
278     our @CB_MAP = ();
279 root 1.39
280 root 1.45 my %attachment;
281    
282 root 1.93 sub _attach_cb($$$$) {
283     my ($registry, $event, $prio, $cb) = @_;
284 root 1.39
285     use sort 'stable';
286    
287     $cb = [$prio, $cb];
288    
289     @{$registry->[$event]} = sort
290     { $a->[0] cmp $b->[0] }
291     @{$registry->[$event] || []}, $cb;
292     }
293    
294 root 1.100 # hack
295     my %attachable_klass = map +($_ => 1), KLASS_OBJECT, KLASS_CLIENT, KLASS_PLAYER, KLASS_MAP;
296    
297 root 1.39 # attach handles attaching event callbacks
298     # the only thing the caller has to do is pass the correct
299     # registry (== where the callback attaches to).
300 root 1.93 sub _attach {
301 root 1.45 my ($registry, $klass, @arg) = @_;
302 root 1.39
303 root 1.93 my $object_type;
304 root 1.39 my $prio = 0;
305     my %cb_id = map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == $klass, 0 .. $#EVENT;
306    
307 root 1.100 #TODO: get rid of this hack
308     if ($attachable_klass{$klass}) {
309     %cb_id = (%cb_id, map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == KLASS_ATTACHABLE, 0 .. $#EVENT);
310     }
311    
312 root 1.45 while (@arg) {
313     my $type = shift @arg;
314 root 1.39
315     if ($type eq "prio") {
316 root 1.45 $prio = shift @arg;
317 root 1.39
318 root 1.93 } elsif ($type eq "type") {
319     $object_type = shift @arg;
320     $registry = $CB_TYPE[$object_type] ||= [];
321    
322     } elsif ($type eq "subtype") {
323     defined $object_type or Carp::croak "subtype specified without type";
324     my $object_subtype = shift @arg;
325     $registry = $CB_TYPE[$object_type + $object_subtype * NUM_SUBTYPES] ||= [];
326    
327 root 1.39 } elsif ($type eq "package") {
328 root 1.45 my $pkg = shift @arg;
329 root 1.39
330     while (my ($name, $id) = each %cb_id) {
331     if (my $cb = $pkg->can ($name)) {
332 root 1.93 _attach_cb $registry, $id, $prio, $cb;
333 root 1.39 }
334     }
335    
336     } elsif (exists $cb_id{$type}) {
337 root 1.93 _attach_cb $registry, $cb_id{$type}, $prio, shift @arg;
338 root 1.39
339     } elsif (ref $type) {
340     warn "attaching objects not supported, ignoring.\n";
341    
342     } else {
343 root 1.45 shift @arg;
344 root 1.39 warn "attach argument '$type' not supported, ignoring.\n";
345     }
346     }
347     }
348    
349 root 1.93 sub _object_attach {
350 root 1.48 my ($obj, $name, %arg) = @_;
351 root 1.46
352 root 1.55 return if exists $obj->{_attachment}{$name};
353    
354 root 1.46 if (my $attach = $attachment{$name}) {
355     my $registry = $obj->registry;
356    
357 root 1.47 for (@$attach) {
358     my ($klass, @attach) = @$_;
359 root 1.93 _attach $registry, $klass, @attach;
360 root 1.47 }
361 root 1.46
362 root 1.48 $obj->{$name} = \%arg;
363 root 1.46 } else {
364     warn "object uses attachment '$name' that is not available, postponing.\n";
365     }
366    
367 root 1.50 $obj->{_attachment}{$name} = undef;
368 root 1.46 }
369    
370 root 1.93 sub cf::attachable::attach {
371     if (ref $_[0]) {
372     _object_attach @_;
373     } else {
374     _attach shift->_attach_registry, @_;
375     }
376 root 1.55 };
377 root 1.46
378 root 1.54 # all those should be optimised
379 root 1.93 sub cf::attachable::detach {
380 root 1.54 my ($obj, $name) = @_;
381 root 1.46
382 root 1.93 if (ref $obj) {
383     delete $obj->{_attachment}{$name};
384     reattach ($obj);
385     } else {
386     Carp::croak "cannot, currently, detach class attachments";
387     }
388 root 1.55 };
389    
390 root 1.93 sub cf::attachable::attached {
391 root 1.55 my ($obj, $name) = @_;
392    
393     exists $obj->{_attachment}{$name}
394 root 1.39 }
395    
396 root 1.100 for my $klass (qw(ATTACHABLE GLOBAL OBJECT PLAYER CLIENT MAP)) {
397 root 1.93 eval "#line " . __LINE__ . " 'cf.pm'
398     sub cf::\L$klass\E::_attach_registry {
399     (\\\@CB_$klass, KLASS_$klass)
400     }
401 root 1.45
402 root 1.93 sub cf::\L$klass\E::attachment {
403     my \$name = shift;
404 root 1.39
405 root 1.93 \$attachment{\$name} = [[KLASS_$klass, \@_]];
406     }
407     ";
408     die if $@;
409 root 1.52 }
410    
411 root 1.39 our $override;
412 root 1.45 our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals?
413 root 1.39
414 root 1.45 sub override {
415     $override = 1;
416     @invoke_results = ();
417 root 1.39 }
418    
419 root 1.45 sub do_invoke {
420 root 1.39 my $event = shift;
421 root 1.40 my $callbacks = shift;
422 root 1.39
423 root 1.45 @invoke_results = ();
424    
425 root 1.39 local $override;
426    
427 root 1.40 for (@$callbacks) {
428 root 1.39 eval { &{$_->[1]} };
429    
430     if ($@) {
431     warn "$@";
432 root 1.64 warn "... while processing $EVENT[$event][0](@_) event, skipping processing altogether.\n";
433 root 1.39 override;
434     }
435    
436     return 1 if $override;
437     }
438    
439     0
440     }
441    
442 root 1.96 =item $bool = cf::global::invoke (EVENT_CLASS_XXX, ...)
443 root 1.55
444 root 1.96 =item $bool = $attachable->invoke (EVENT_CLASS_XXX, ...)
445 root 1.55
446 root 1.96 Generate an object-specific event with the given arguments.
447 root 1.55
448 root 1.96 This API is preliminary (most likely, the EVENT_CLASS_xxx prefix will be
449 root 1.55 removed in future versions), and there is no public API to access override
450     results (if you must, access C<@cf::invoke_results> directly).
451    
452     =back
453    
454 root 1.71 =cut
455    
456 root 1.70 #############################################################################
457 root 1.45 # object support
458    
459 root 1.102 sub reattach {
460     # basically do the same as instantiate, without calling instantiate
461     my ($obj) = @_;
462    
463     my $registry = $obj->registry;
464    
465     @$registry = ();
466    
467     delete $obj->{_attachment} unless scalar keys %{ $obj->{_attachment} || {} };
468    
469     for my $name (keys %{ $obj->{_attachment} || {} }) {
470     if (my $attach = $attachment{$name}) {
471     for (@$attach) {
472     my ($klass, @attach) = @$_;
473     _attach $registry, $klass, @attach;
474     }
475     } else {
476     warn "object uses attachment '$name' that is not available, postponing.\n";
477     }
478     }
479     }
480    
481 root 1.100 cf::attachable->attach (
482     prio => -1000000,
483     on_instantiate => sub {
484     my ($obj, $data) = @_;
485 root 1.45
486 root 1.100 $data = from_json $data;
487 root 1.45
488 root 1.100 for (@$data) {
489     my ($name, $args) = @$_;
490 root 1.49
491 root 1.100 $obj->attach ($name, %{$args || {} });
492     }
493     },
494 root 1.102 on_reattach => \&reattach,
495 root 1.100 on_clone => sub {
496     my ($src, $dst) = @_;
497    
498     @{$dst->registry} = @{$src->registry};
499    
500     %$dst = %$src;
501    
502     %{$dst->{_attachment}} = %{$src->{_attachment}}
503     if exists $src->{_attachment};
504     },
505     );
506 root 1.45
507 root 1.46 sub object_freezer_save {
508 root 1.59 my ($filename, $rdata, $objs) = @_;
509 root 1.46
510 root 1.60 if (length $$rdata) {
511     warn sprintf "saving %s (%d,%d)\n",
512     $filename, length $$rdata, scalar @$objs;
513 root 1.59
514 root 1.60 if (open my $fh, ">:raw", "$filename~") {
515 root 1.59 chmod SAVE_MODE, $fh;
516 root 1.60 syswrite $fh, $$rdata;
517 root 1.59 close $fh;
518 root 1.60
519     if (@$objs && open my $fh, ">:raw", "$filename.pst~") {
520     chmod SAVE_MODE, $fh;
521     syswrite $fh, Storable::nfreeze { version => 1, objs => $objs };
522     close $fh;
523     rename "$filename.pst~", "$filename.pst";
524     } else {
525     unlink "$filename.pst";
526     }
527    
528     rename "$filename~", $filename;
529 root 1.59 } else {
530 root 1.60 warn "FATAL: $filename~: $!\n";
531 root 1.59 }
532 root 1.46 } else {
533 root 1.60 unlink $filename;
534     unlink "$filename.pst";
535 root 1.45 }
536     }
537    
538 root 1.80 sub object_freezer_as_string {
539     my ($rdata, $objs) = @_;
540    
541     use Data::Dumper;
542    
543 root 1.81 $$rdata . Dumper $objs
544 root 1.80 }
545    
546 root 1.46 sub object_thawer_load {
547     my ($filename) = @_;
548    
549 root 1.61 local $/;
550    
551     my $av;
552    
553     #TODO: use sysread etc.
554     if (open my $data, "<:raw:perlio", $filename) {
555     $data = <$data>;
556     if (open my $pst, "<:raw:perlio", "$filename.pst") {
557     $av = eval { (Storable::thaw <$pst>)->{objs} };
558     }
559     return ($data, $av);
560     }
561 root 1.45
562 root 1.61 ()
563 root 1.45 }
564    
565     #############################################################################
566 root 1.85 # command handling &c
567 root 1.39
568 root 1.85 =item cf::register_command $name => \&callback($ob,$args);
569 root 1.1
570 root 1.85 Register a callback for execution when the client sends the user command
571     $name.
572 root 1.5
573 root 1.85 =cut
574 root 1.5
575 root 1.85 sub register_command {
576     my ($name, $cb) = @_;
577 root 1.5
578 root 1.85 my $caller = caller;
579     #warn "registering command '$name/$time' to '$caller'";
580 root 1.1
581 root 1.85 push @{ $COMMAND{$name} }, [$caller, $cb];
582 root 1.1 }
583    
584 root 1.85 =item cf::register_extcmd $name => \&callback($pl,$packet);
585 root 1.1
586 root 1.85 Register a callbackf ro execution when the client sends an extcmd packet.
587 root 1.1
588 root 1.85 If the callback returns something, it is sent back as if reply was being
589     called.
590 root 1.1
591 root 1.85 =cut
592 root 1.1
593 root 1.16 sub register_extcmd {
594     my ($name, $cb) = @_;
595    
596     my $caller = caller;
597     #warn "registering extcmd '$name' to '$caller'";
598    
599 root 1.85 $EXTCMD{$name} = [$cb, $caller];
600 root 1.16 }
601    
602 root 1.93 cf::player->attach (
603 root 1.85 on_command => sub {
604     my ($pl, $name, $params) = @_;
605    
606     my $cb = $COMMAND{$name}
607     or return;
608    
609     for my $cmd (@$cb) {
610     $cmd->[1]->($pl->ob, $params);
611     }
612    
613     cf::override;
614     },
615     on_extcmd => sub {
616     my ($pl, $buf) = @_;
617    
618     my $msg = eval { from_json $buf };
619    
620     if (ref $msg) {
621     if (my $cb = $EXTCMD{$msg->{msgtype}}) {
622     if (my %reply = $cb->[0]->($pl, $msg)) {
623     $pl->ext_reply ($msg->{msgid}, %reply);
624     }
625     }
626     } else {
627     warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
628     }
629    
630     cf::override;
631     },
632 root 1.93 );
633 root 1.85
634 root 1.6 sub register {
635     my ($base, $pkg) = @_;
636    
637 root 1.45 #TODO
638 root 1.6 }
639    
640 root 1.1 sub load_extension {
641     my ($path) = @_;
642    
643     $path =~ /([^\/\\]+)\.ext$/ or die "$path";
644 root 1.5 my $base = $1;
645 root 1.1 my $pkg = $1;
646     $pkg =~ s/[^[:word:]]/_/g;
647 root 1.41 $pkg = "ext::$pkg";
648 root 1.1
649     warn "loading '$path' into '$pkg'\n";
650    
651     open my $fh, "<:utf8", $path
652     or die "$path: $!";
653    
654     my $source =
655     "package $pkg; use strict; use utf8;\n"
656     . "#line 1 \"$path\"\n{\n"
657     . (do { local $/; <$fh> })
658     . "\n};\n1";
659    
660     eval $source
661 root 1.82 or die $@ ? "$path: $@\n"
662     : "extension disabled.\n";
663 root 1.1
664     push @exts, $pkg;
665 root 1.5 $ext_pkg{$base} = $pkg;
666 root 1.1
667 root 1.6 # no strict 'refs';
668 root 1.23 # @{"$pkg\::ISA"} = ext::;
669 root 1.1
670 root 1.6 register $base, $pkg;
671 root 1.1 }
672    
673     sub unload_extension {
674     my ($pkg) = @_;
675    
676     warn "removing extension $pkg\n";
677    
678     # remove hooks
679 root 1.45 #TODO
680     # for my $idx (0 .. $#PLUGIN_EVENT) {
681     # delete $hook[$idx]{$pkg};
682     # }
683 root 1.1
684     # remove commands
685 root 1.85 for my $name (keys %COMMAND) {
686     my @cb = grep $_->[0] ne $pkg, @{ $COMMAND{$name} };
687 root 1.1
688     if (@cb) {
689 root 1.85 $COMMAND{$name} = \@cb;
690 root 1.1 } else {
691 root 1.85 delete $COMMAND{$name};
692 root 1.1 }
693     }
694    
695 root 1.15 # remove extcmds
696 root 1.85 for my $name (grep $EXTCMD{$_}[1] eq $pkg, keys %EXTCMD) {
697     delete $EXTCMD{$name};
698 root 1.15 }
699    
700 root 1.43 if (my $cb = $pkg->can ("unload")) {
701 elmex 1.31 eval {
702     $cb->($pkg);
703     1
704     } or warn "$pkg unloaded, but with errors: $@";
705     }
706    
707 root 1.1 Symbol::delete_package $pkg;
708     }
709    
710     sub load_extensions {
711     for my $ext (<$LIBDIR/*.ext>) {
712 root 1.3 next unless -r $ext;
713 root 1.2 eval {
714     load_extension $ext;
715     1
716     } or warn "$ext not loaded: $@";
717 root 1.1 }
718     }
719    
720 root 1.8 #############################################################################
721     # load/save/clean perl data associated with a map
722    
723 root 1.39 *cf::mapsupport::on_clean = sub {
724 root 1.13 my ($map) = @_;
725 root 1.7
726     my $path = $map->tmpname;
727     defined $path or return;
728    
729 root 1.46 unlink "$path.pst";
730 root 1.7 };
731    
732 root 1.93 cf::map->attach (prio => -10000, package => cf::mapsupport::);
733 root 1.39
734 root 1.8 #############################################################################
735     # load/save perl data associated with player->ob objects
736    
737 root 1.33 sub all_objects(@) {
738     @_, map all_objects ($_->inv), @_
739     }
740    
741 root 1.60 # TODO: compatibility cruft, remove when no longer needed
742 root 1.93 cf::player->attach (
743 root 1.39 on_load => sub {
744     my ($pl, $path) = @_;
745    
746     for my $o (all_objects $pl->ob) {
747     if (my $value = $o->get_ob_key_value ("_perl_data")) {
748     $o->set_ob_key_value ("_perl_data");
749 root 1.8
750 root 1.39 %$o = %{ Storable::thaw pack "H*", $value };
751     }
752 root 1.11 }
753 root 1.39 },
754 root 1.93 );
755 root 1.6
756 root 1.22 #############################################################################
757 root 1.70
758     =head2 CORE EXTENSIONS
759    
760     Functions and methods that extend core crossfire objects.
761    
762 root 1.95 =head3 cf::player
763    
764 root 1.70 =over 4
765 root 1.22
766 root 1.23 =item cf::player::exists $login
767    
768     Returns true when the given account exists.
769    
770     =cut
771    
772     sub cf::player::exists($) {
773     cf::player::find $_[0]
774     or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2;
775     }
776    
777 root 1.95 =item $player->ext_reply ($msgid, $msgtype, %msg)
778    
779     Sends an ext reply to the player.
780    
781     =cut
782    
783     sub cf::player::ext_reply($$$%) {
784     my ($self, $id, %msg) = @_;
785    
786     $msg{msgid} = $id;
787    
788     $self->send ("ext " . to_json \%msg);
789     }
790    
791     =back
792    
793     =head3 cf::object::player
794    
795     =over 4
796    
797 root 1.79 =item $player_object->reply ($npc, $msg[, $flags])
798 root 1.28
799     Sends a message to the player, as if the npc C<$npc> replied. C<$npc>
800     can be C<undef>. Does the right thing when the player is currently in a
801     dialogue with the given NPC character.
802    
803     =cut
804    
805 root 1.22 # rough implementation of a future "reply" method that works
806     # with dialog boxes.
807 root 1.95 #TODO: the first argument must go, split into a $npc->reply_to ( method
808 root 1.23 sub cf::object::player::reply($$$;$) {
809     my ($self, $npc, $msg, $flags) = @_;
810    
811     $flags = cf::NDI_BROWN | cf::NDI_UNIQUE unless @_ >= 4;
812 root 1.22
813 root 1.24 if ($self->{record_replies}) {
814     push @{ $self->{record_replies} }, [$npc, $msg, $flags];
815     } else {
816     $msg = $npc->name . " says: $msg" if $npc;
817     $self->message ($msg, $flags);
818     }
819 root 1.22 }
820    
821 root 1.79 =item $player_object->may ("access")
822    
823     Returns wether the given player is authorized to access resource "access"
824     (e.g. "command_wizcast").
825    
826     =cut
827    
828     sub cf::object::player::may {
829     my ($self, $access) = @_;
830    
831     $self->flag (cf::FLAG_WIZ) ||
832     (ref $cf::CFG{"may_$access"}
833     ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}}
834     : $cf::CFG{"may_$access"})
835     }
836 root 1.70
837 root 1.95 =head3 cf::client
838    
839     =over 4
840    
841     =item $client->send_drawinfo ($text, $flags)
842    
843     Sends a drawinfo packet to the client. Circumvents output buffering so
844     should not be used under normal circumstances.
845    
846 root 1.70 =cut
847    
848 root 1.95 sub cf::client::send_drawinfo {
849     my ($self, $text, $flags) = @_;
850    
851     utf8::encode $text;
852     $self->send_packet (sprintf "drawinfo %d %s", $flags, $text);
853     }
854    
855    
856     =item $success = $client->query ($flags, "text", \&cb)
857    
858     Queues a query to the client, calling the given callback with
859     the reply text on a reply. flags can be C<cf::CS_QUERY_YESNO>,
860     C<cf::CS_QUERY_SINGLECHAR> or C<cf::CS_QUERY_HIDEINPUT> or C<0>.
861    
862     Queries can fail, so check the return code. Or don't, as queries will become
863     reliable at some point in the future.
864    
865     =cut
866    
867     sub cf::client::query {
868     my ($self, $flags, $text, $cb) = @_;
869    
870     return unless $self->state == ST_PLAYING
871     || $self->state == ST_SETUP
872     || $self->state == ST_CUSTOM;
873    
874     $self->state (ST_CUSTOM);
875    
876     utf8::encode $text;
877     push @{ $self->{query_queue} }, [(sprintf "query %d %s", $flags, $text), $cb];
878    
879     $self->send_packet ($self->{query_queue}[0][0])
880     if @{ $self->{query_queue} } == 1;
881     }
882    
883     cf::client->attach (
884     on_reply => sub {
885     my ($ns, $msg) = @_;
886    
887     # this weird shuffling is so that direct followup queries
888     # get handled first
889     my $queue = delete $ns->{query_queue};
890    
891     (shift @$queue)->[1]->($msg);
892    
893     push @{ $ns->{query_queue} }, @$queue;
894    
895     if (@{ $ns->{query_queue} } == @$queue) {
896     if (@$queue) {
897     $ns->send_packet ($ns->{query_queue}[0][0]);
898     } else {
899 root 1.98 $ns->state (ST_PLAYING) if $ns->state == ST_CUSTOM;
900 root 1.95 }
901     }
902     },
903     );
904    
905 root 1.96 =item $client->coro (\&cb)
906    
907     Create a new coroutine, running the specified callback. The coroutine will
908     be automatically cancelled when the client gets destroyed (e.g. on logout,
909     or loss of connection).
910    
911     =cut
912    
913     sub cf::client::coro {
914     my ($self, $cb) = @_;
915    
916     my $coro; $coro = async {
917     eval {
918     $cb->();
919     };
920     warn $@ if $@;
921     delete $self->{_coro}{$coro+0};
922     };
923    
924     $self->{_coro}{$coro+0} = $coro;
925     }
926    
927     cf::client->attach (
928     on_destroy => sub {
929     my ($ns) = @_;
930    
931 root 1.97 $_->cancel for values %{ (delete $ns->{_coro}) || {} };
932 root 1.96 },
933     );
934    
935 root 1.95 =back
936    
937 root 1.70
938     =head2 SAFE SCRIPTING
939    
940     Functions that provide a safe environment to compile and execute
941     snippets of perl code without them endangering the safety of the server
942     itself. Looping constructs, I/O operators and other built-in functionality
943     is not available in the safe scripting environment, and the number of
944 root 1.79 functions and methods that can be called is greatly reduced.
945 root 1.70
946     =cut
947 root 1.23
948 root 1.42 our $safe = new Safe "safe";
949 root 1.23 our $safe_hole = new Safe::Hole;
950    
951     $SIG{FPE} = 'IGNORE';
952    
953     $safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
954    
955 root 1.25 # here we export the classes and methods available to script code
956    
957 root 1.70 =pod
958    
959     The following fucntions and emthods are available within a safe environment:
960    
961 elmex 1.91 cf::object contr pay_amount pay_player map
962 root 1.70 cf::object::player player
963     cf::player peaceful
964 elmex 1.91 cf::map trigger
965 root 1.70
966     =cut
967    
968 root 1.25 for (
969 elmex 1.91 ["cf::object" => qw(contr pay_amount pay_player map)],
970 root 1.25 ["cf::object::player" => qw(player)],
971     ["cf::player" => qw(peaceful)],
972 elmex 1.91 ["cf::map" => qw(trigger)],
973 root 1.25 ) {
974     no strict 'refs';
975     my ($pkg, @funs) = @$_;
976 root 1.41 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
977 root 1.25 for @funs;
978     }
979 root 1.23
980 root 1.70 =over 4
981    
982     =item @retval = safe_eval $code, [var => value, ...]
983    
984     Compiled and executes the given perl code snippet. additional var/value
985     pairs result in temporary local (my) scalar variables of the given name
986     that are available in the code snippet. Example:
987    
988     my $five = safe_eval '$first + $second', first => 1, second => 4;
989    
990     =cut
991    
992 root 1.23 sub safe_eval($;@) {
993     my ($code, %vars) = @_;
994    
995     my $qcode = $code;
996     $qcode =~ s/"/‟/g; # not allowed in #line filenames
997     $qcode =~ s/\n/\\n/g;
998    
999     local $_;
1000 root 1.41 local @safe::cf::_safe_eval_args = values %vars;
1001 root 1.23
1002 root 1.42 my $eval =
1003 root 1.23 "do {\n"
1004     . "my (" . (join ",", map "\$$_", keys %vars) . ") = \@cf::_safe_eval_args;\n"
1005     . "#line 0 \"{$qcode}\"\n"
1006     . $code
1007     . "\n}"
1008 root 1.25 ;
1009    
1010     sub_generation_inc;
1011 root 1.42 my @res = wantarray ? $safe->reval ($eval) : scalar $safe->reval ($eval);
1012 root 1.25 sub_generation_inc;
1013    
1014 root 1.42 if ($@) {
1015     warn "$@";
1016     warn "while executing safe code '$code'\n";
1017     warn "with arguments " . (join " ", %vars) . "\n";
1018     }
1019    
1020 root 1.25 wantarray ? @res : $res[0]
1021 root 1.23 }
1022    
1023 root 1.69 =item cf::register_script_function $function => $cb
1024    
1025     Register a function that can be called from within map/npc scripts. The
1026     function should be reasonably secure and should be put into a package name
1027     like the extension.
1028    
1029     Example: register a function that gets called whenever a map script calls
1030     C<rent::overview>, as used by the C<rent> extension.
1031    
1032     cf::register_script_function "rent::overview" => sub {
1033     ...
1034     };
1035    
1036     =cut
1037    
1038 root 1.23 sub register_script_function {
1039     my ($fun, $cb) = @_;
1040    
1041     no strict 'refs';
1042 root 1.41 *{"safe::$fun"} = $safe_hole->wrap ($cb);
1043 root 1.23 }
1044    
1045 root 1.70 =back
1046    
1047 root 1.71 =cut
1048    
1049 root 1.23 #############################################################################
1050 root 1.65
1051     =head2 EXTENSION DATABASE SUPPORT
1052    
1053     Crossfire maintains a very simple database for extension use. It can
1054     currently store anything that can be serialised using Storable, which
1055     excludes objects.
1056    
1057     The parameter C<$family> should best start with the name of the extension
1058     using it, it should be unique.
1059    
1060     =over 4
1061    
1062     =item $hashref = cf::db_get $family
1063    
1064     Return a hashref for use by the extension C<$family>, which can be
1065     modified. After modifications, you have to call C<cf::db_dirty> or
1066     C<cf::db_sync>.
1067    
1068     =item $value = cf::db_get $family => $key
1069    
1070     Returns a single value from the database
1071    
1072     =item cf::db_put $family => $hashref
1073    
1074     Stores the given family hashref into the database. Updates are delayed, if
1075     you want the data to be synced to disk immediately, use C<cf::db_sync>.
1076    
1077     =item cf::db_put $family => $key => $value
1078    
1079     Stores the given C<$value> in the family hash. Updates are delayed, if you
1080     want the data to be synced to disk immediately, use C<cf::db_sync>.
1081    
1082     =item cf::db_dirty
1083    
1084     Marks the database as dirty, to be updated at a later time.
1085    
1086     =item cf::db_sync
1087    
1088     Immediately write the database to disk I<if it is dirty>.
1089    
1090     =cut
1091    
1092 root 1.78 our $DB;
1093    
1094 root 1.65 {
1095 root 1.66 my $path = cf::localdir . "/database.pst";
1096 root 1.65
1097     sub db_load() {
1098     warn "loading database $path\n";#d# remove later
1099 root 1.78 $DB = stat $path ? Storable::retrieve $path : { };
1100 root 1.65 }
1101    
1102     my $pid;
1103    
1104     sub db_save() {
1105     warn "saving database $path\n";#d# remove later
1106     waitpid $pid, 0 if $pid;
1107 root 1.67 if (0 == ($pid = fork)) {
1108 root 1.78 $DB->{_meta}{version} = 1;
1109     Storable::nstore $DB, "$path~";
1110 root 1.65 rename "$path~", $path;
1111     cf::_exit 0 if defined $pid;
1112     }
1113     }
1114    
1115     my $dirty;
1116    
1117     sub db_sync() {
1118     db_save if $dirty;
1119     undef $dirty;
1120     }
1121    
1122 root 1.87 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, data => WF_AUTOCANCEL, cb => sub {
1123 root 1.65 db_sync;
1124     });
1125    
1126     sub db_dirty() {
1127     $dirty = 1;
1128     $idle->start;
1129     }
1130    
1131     sub db_get($;$) {
1132     @_ >= 2
1133 root 1.78 ? $DB->{$_[0]}{$_[1]}
1134     : ($DB->{$_[0]} ||= { })
1135 root 1.65 }
1136    
1137     sub db_put($$;$) {
1138     if (@_ >= 3) {
1139 root 1.78 $DB->{$_[0]}{$_[1]} = $_[2];
1140 root 1.65 } else {
1141 root 1.78 $DB->{$_[0]} = $_[1];
1142 root 1.65 }
1143     db_dirty;
1144     }
1145 root 1.67
1146 root 1.93 cf::global->attach (
1147     prio => 10000,
1148 root 1.67 on_cleanup => sub {
1149     db_sync;
1150     },
1151 root 1.93 );
1152 root 1.65 }
1153    
1154     #############################################################################
1155 root 1.34 # the server's main()
1156    
1157 root 1.73 sub cfg_load {
1158 root 1.72 open my $fh, "<:utf8", cf::confdir . "/config"
1159     or return;
1160    
1161     local $/;
1162     *CFG = YAML::Syck::Load <$fh>;
1163     }
1164    
1165 root 1.39 sub main {
1166 root 1.73 cfg_load;
1167 root 1.65 db_load;
1168 root 1.61 load_extensions;
1169 root 1.34 Event::loop;
1170     }
1171    
1172     #############################################################################
1173 root 1.22 # initialisation
1174    
1175 root 1.65 sub _perl_reload(&) {
1176     my ($msg) = @_;
1177    
1178     $msg->("reloading...");
1179    
1180     eval {
1181     # cancel all watchers
1182 root 1.87 for (Event::all_watchers) {
1183     $_->cancel if $_->data & WF_AUTOCANCEL;
1184     }
1185 root 1.65
1186     # unload all extensions
1187     for (@exts) {
1188     $msg->("unloading <$_>");
1189     unload_extension $_;
1190     }
1191    
1192     # unload all modules loaded from $LIBDIR
1193     while (my ($k, $v) = each %INC) {
1194     next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
1195    
1196     $msg->("removing <$k>");
1197     delete $INC{$k};
1198    
1199     $k =~ s/\.pm$//;
1200     $k =~ s/\//::/g;
1201    
1202     if (my $cb = $k->can ("unload_module")) {
1203     $cb->();
1204     }
1205    
1206     Symbol::delete_package $k;
1207     }
1208    
1209     # sync database to disk
1210     cf::db_sync;
1211    
1212     # get rid of safe::, as good as possible
1213     Symbol::delete_package "safe::$_"
1214     for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
1215    
1216     # remove register_script_function callbacks
1217     # TODO
1218    
1219     # unload cf.pm "a bit"
1220     delete $INC{"cf.pm"};
1221    
1222     # don't, removes xs symbols, too,
1223     # and global variables created in xs
1224     #Symbol::delete_package __PACKAGE__;
1225    
1226     # reload cf.pm
1227     $msg->("reloading cf.pm");
1228     require cf;
1229 root 1.100 cf::_connect_to_perl; # nominally unnecessary, but cannot hurt
1230    
1231 root 1.73 # load config and database again
1232     cf::cfg_load;
1233 root 1.65 cf::db_load;
1234    
1235     # load extensions
1236     $msg->("load extensions");
1237     cf::load_extensions;
1238    
1239     # reattach attachments to objects
1240     $msg->("reattach");
1241     _global_reattach;
1242     };
1243     $msg->($@) if $@;
1244    
1245     $msg->("reloaded");
1246     };
1247    
1248     sub perl_reload() {
1249     _perl_reload {
1250     warn $_[0];
1251     print "$_[0]\n";
1252     };
1253     }
1254    
1255 root 1.85 register "<global>", __PACKAGE__;
1256    
1257     register_command "perl-reload" => sub {
1258 root 1.65 my ($who, $arg) = @_;
1259    
1260     if ($who->flag (FLAG_WIZ)) {
1261     _perl_reload {
1262     warn $_[0];
1263     $who->message ($_[0]);
1264     };
1265     }
1266     };
1267    
1268 root 1.27 unshift @INC, $LIBDIR;
1269 root 1.17
1270 root 1.35 $TICK_WATCHER = Event->timer (
1271 root 1.90 prio => 0,
1272 root 1.77 at => $NEXT_TICK || 1,
1273 root 1.87 data => WF_AUTOCANCEL,
1274 root 1.77 cb => sub {
1275 root 1.35 cf::server_tick; # one server iteration
1276    
1277     my $NOW = Event::time;
1278     $NEXT_TICK += $TICK;
1279    
1280 root 1.78 # if we are delayed by four ticks or more, skip them all
1281 root 1.37 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1282 root 1.35
1283     $TICK_WATCHER->at ($NEXT_TICK);
1284     $TICK_WATCHER->start;
1285     },
1286     );
1287    
1288 root 1.80 IO::AIO::max_poll_time $TICK * 0.2;
1289 root 1.77
1290     Event->io (fd => IO::AIO::poll_fileno,
1291     poll => 'r',
1292     prio => 5,
1293 root 1.87 data => WF_AUTOCANCEL,
1294 root 1.77 cb => \&IO::AIO::poll_cb);
1295    
1296 root 1.1 1
1297