ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.76
Committed: Mon Oct 2 15:28:36 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.75: +4 -0 lines
Log Message:
nuke metaserver code

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