ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.92
Committed: Thu Dec 21 06:42:28 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.91: +30 -1 lines
Log Message:
- add perl parts to attach to clients (should be generalised)

File Contents

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