ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.81
Committed: Tue Nov 7 17:38:22 2006 UTC (17 years, 6 months ago) by root
Branch: MAIN
Changes since 1.80: +1 -1 lines
Log Message:
*** empty log message ***

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