ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.96
Committed: Fri Dec 22 06:02:29 2006 UTC (17 years, 6 months ago) by root
Branch: MAIN
Changes since 1.95: +57 -34 lines
Log Message:
- add preliminary per-client coroutine support (I do not threaten, I act :)
- moved global events to cf::global

File Contents

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