ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.91
Committed: Sun Dec 17 22:03:44 2006 UTC (17 years, 5 months ago) by elmex
Branch: MAIN
Changes since 1.90: +4 -2 lines
Log Message:
added some functions to the safe environment in npc dialouges

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