ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.109
Committed: Sun Dec 31 22:23:12 2006 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.108: +9 -4 lines
Log Message:
- random maps seem to work now
- had to move map parameters into files because we need constant-sized map path lengths
  as the full map stack history would have to be included.

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