ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.86
Committed: Thu Dec 14 05:09:32 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.85: +6 -1 lines
Log Message:
- remove some old socket mode cruft
- preliminarily added attachable client_socket interface to perl
  (untested but also unreachable from perl code atm)

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