ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.103
Committed: Sat Dec 30 10:16:11 2006 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.102: +104 -28 lines
Log Message:
preliminary snapshot check-in, DO NOT USE IN PRODUCTION SYSTEMS
See the Changes file for details

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