ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.108
Committed: Sun Dec 31 21:02:05 2006 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.107: +171 -15 lines
Log Message:
more use of shstr where it makes sense naturally

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