ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
Revision: 1.98
Committed: Fri Dec 22 16:34:00 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.97: +1 -1 lines
Log Message:
- preliminary check in, stuff is rudimentarily working
- moved most of the player creation process into a perl coroutine
- changed internal design of player management to not reuse
  and morph the object in funny ways. should be safer and much
  nicer to handle.
- got rid of some annoying hacks, such as clear()
  (TODO: get rid of player_pod and other stuff now unnecessary?)

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 root 1.98 $ns->state (ST_PLAYING) if $ns->state == ST_CUSTOM;
892 root 1.95 }
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     delete $self->{_coro}{$coro+0};
914     };
915    
916     $self->{_coro}{$coro+0} = $coro;
917     }
918    
919     cf::client->attach (
920     on_destroy => sub {
921     my ($ns) = @_;
922    
923 root 1.97 $_->cancel for values %{ (delete $ns->{_coro}) || {} };
924 root 1.96 },
925     );
926    
927 root 1.95 =back
928    
929 root 1.70
930     =head2 SAFE SCRIPTING
931    
932     Functions that provide a safe environment to compile and execute
933     snippets of perl code without them endangering the safety of the server
934     itself. Looping constructs, I/O operators and other built-in functionality
935     is not available in the safe scripting environment, and the number of
936 root 1.79 functions and methods that can be called is greatly reduced.
937 root 1.70
938     =cut
939 root 1.23
940 root 1.42 our $safe = new Safe "safe";
941 root 1.23 our $safe_hole = new Safe::Hole;
942    
943     $SIG{FPE} = 'IGNORE';
944    
945     $safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
946    
947 root 1.25 # here we export the classes and methods available to script code
948    
949 root 1.70 =pod
950    
951     The following fucntions and emthods are available within a safe environment:
952    
953 elmex 1.91 cf::object contr pay_amount pay_player map
954 root 1.70 cf::object::player player
955     cf::player peaceful
956 elmex 1.91 cf::map trigger
957 root 1.70
958     =cut
959    
960 root 1.25 for (
961 elmex 1.91 ["cf::object" => qw(contr pay_amount pay_player map)],
962 root 1.25 ["cf::object::player" => qw(player)],
963     ["cf::player" => qw(peaceful)],
964 elmex 1.91 ["cf::map" => qw(trigger)],
965 root 1.25 ) {
966     no strict 'refs';
967     my ($pkg, @funs) = @$_;
968 root 1.41 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
969 root 1.25 for @funs;
970     }
971 root 1.23
972 root 1.70 =over 4
973    
974     =item @retval = safe_eval $code, [var => value, ...]
975    
976     Compiled and executes the given perl code snippet. additional var/value
977     pairs result in temporary local (my) scalar variables of the given name
978     that are available in the code snippet. Example:
979    
980     my $five = safe_eval '$first + $second', first => 1, second => 4;
981    
982     =cut
983    
984 root 1.23 sub safe_eval($;@) {
985     my ($code, %vars) = @_;
986    
987     my $qcode = $code;
988     $qcode =~ s/"/‟/g; # not allowed in #line filenames
989     $qcode =~ s/\n/\\n/g;
990    
991     local $_;
992 root 1.41 local @safe::cf::_safe_eval_args = values %vars;
993 root 1.23
994 root 1.42 my $eval =
995 root 1.23 "do {\n"
996     . "my (" . (join ",", map "\$$_", keys %vars) . ") = \@cf::_safe_eval_args;\n"
997     . "#line 0 \"{$qcode}\"\n"
998     . $code
999     . "\n}"
1000 root 1.25 ;
1001    
1002     sub_generation_inc;
1003 root 1.42 my @res = wantarray ? $safe->reval ($eval) : scalar $safe->reval ($eval);
1004 root 1.25 sub_generation_inc;
1005    
1006 root 1.42 if ($@) {
1007     warn "$@";
1008     warn "while executing safe code '$code'\n";
1009     warn "with arguments " . (join " ", %vars) . "\n";
1010     }
1011    
1012 root 1.25 wantarray ? @res : $res[0]
1013 root 1.23 }
1014    
1015 root 1.69 =item cf::register_script_function $function => $cb
1016    
1017     Register a function that can be called from within map/npc scripts. The
1018     function should be reasonably secure and should be put into a package name
1019     like the extension.
1020    
1021     Example: register a function that gets called whenever a map script calls
1022     C<rent::overview>, as used by the C<rent> extension.
1023    
1024     cf::register_script_function "rent::overview" => sub {
1025     ...
1026     };
1027    
1028     =cut
1029    
1030 root 1.23 sub register_script_function {
1031     my ($fun, $cb) = @_;
1032    
1033     no strict 'refs';
1034 root 1.41 *{"safe::$fun"} = $safe_hole->wrap ($cb);
1035 root 1.23 }
1036    
1037 root 1.70 =back
1038    
1039 root 1.71 =cut
1040    
1041 root 1.23 #############################################################################
1042 root 1.65
1043     =head2 EXTENSION DATABASE SUPPORT
1044    
1045     Crossfire maintains a very simple database for extension use. It can
1046     currently store anything that can be serialised using Storable, which
1047     excludes objects.
1048    
1049     The parameter C<$family> should best start with the name of the extension
1050     using it, it should be unique.
1051    
1052     =over 4
1053    
1054     =item $hashref = cf::db_get $family
1055    
1056     Return a hashref for use by the extension C<$family>, which can be
1057     modified. After modifications, you have to call C<cf::db_dirty> or
1058     C<cf::db_sync>.
1059    
1060     =item $value = cf::db_get $family => $key
1061    
1062     Returns a single value from the database
1063    
1064     =item cf::db_put $family => $hashref
1065    
1066     Stores the given family hashref into the database. Updates are delayed, if
1067     you want the data to be synced to disk immediately, use C<cf::db_sync>.
1068    
1069     =item cf::db_put $family => $key => $value
1070    
1071     Stores the given C<$value> in the family hash. Updates are delayed, if you
1072     want the data to be synced to disk immediately, use C<cf::db_sync>.
1073    
1074     =item cf::db_dirty
1075    
1076     Marks the database as dirty, to be updated at a later time.
1077    
1078     =item cf::db_sync
1079    
1080     Immediately write the database to disk I<if it is dirty>.
1081    
1082     =cut
1083    
1084 root 1.78 our $DB;
1085    
1086 root 1.65 {
1087 root 1.66 my $path = cf::localdir . "/database.pst";
1088 root 1.65
1089     sub db_load() {
1090     warn "loading database $path\n";#d# remove later
1091 root 1.78 $DB = stat $path ? Storable::retrieve $path : { };
1092 root 1.65 }
1093    
1094     my $pid;
1095    
1096     sub db_save() {
1097     warn "saving database $path\n";#d# remove later
1098     waitpid $pid, 0 if $pid;
1099 root 1.67 if (0 == ($pid = fork)) {
1100 root 1.78 $DB->{_meta}{version} = 1;
1101     Storable::nstore $DB, "$path~";
1102 root 1.65 rename "$path~", $path;
1103     cf::_exit 0 if defined $pid;
1104     }
1105     }
1106    
1107     my $dirty;
1108    
1109     sub db_sync() {
1110     db_save if $dirty;
1111     undef $dirty;
1112     }
1113    
1114 root 1.87 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, data => WF_AUTOCANCEL, cb => sub {
1115 root 1.65 db_sync;
1116     });
1117    
1118     sub db_dirty() {
1119     $dirty = 1;
1120     $idle->start;
1121     }
1122    
1123     sub db_get($;$) {
1124     @_ >= 2
1125 root 1.78 ? $DB->{$_[0]}{$_[1]}
1126     : ($DB->{$_[0]} ||= { })
1127 root 1.65 }
1128    
1129     sub db_put($$;$) {
1130     if (@_ >= 3) {
1131 root 1.78 $DB->{$_[0]}{$_[1]} = $_[2];
1132 root 1.65 } else {
1133 root 1.78 $DB->{$_[0]} = $_[1];
1134 root 1.65 }
1135     db_dirty;
1136     }
1137 root 1.67
1138 root 1.93 cf::global->attach (
1139     prio => 10000,
1140 root 1.67 on_cleanup => sub {
1141     db_sync;
1142     },
1143 root 1.93 );
1144 root 1.65 }
1145    
1146     #############################################################################
1147 root 1.34 # the server's main()
1148    
1149 root 1.73 sub cfg_load {
1150 root 1.72 open my $fh, "<:utf8", cf::confdir . "/config"
1151     or return;
1152    
1153     local $/;
1154     *CFG = YAML::Syck::Load <$fh>;
1155     }
1156    
1157 root 1.39 sub main {
1158 root 1.73 cfg_load;
1159 root 1.65 db_load;
1160 root 1.61 load_extensions;
1161 root 1.34 Event::loop;
1162     }
1163    
1164     #############################################################################
1165 root 1.22 # initialisation
1166    
1167 root 1.65 sub _perl_reload(&) {
1168     my ($msg) = @_;
1169    
1170     $msg->("reloading...");
1171    
1172     eval {
1173     # cancel all watchers
1174 root 1.87 for (Event::all_watchers) {
1175     $_->cancel if $_->data & WF_AUTOCANCEL;
1176     }
1177 root 1.65
1178     # unload all extensions
1179     for (@exts) {
1180     $msg->("unloading <$_>");
1181     unload_extension $_;
1182     }
1183    
1184     # unload all modules loaded from $LIBDIR
1185     while (my ($k, $v) = each %INC) {
1186     next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
1187    
1188     $msg->("removing <$k>");
1189     delete $INC{$k};
1190    
1191     $k =~ s/\.pm$//;
1192     $k =~ s/\//::/g;
1193    
1194     if (my $cb = $k->can ("unload_module")) {
1195     $cb->();
1196     }
1197    
1198     Symbol::delete_package $k;
1199     }
1200    
1201     # sync database to disk
1202     cf::db_sync;
1203    
1204     # get rid of safe::, as good as possible
1205     Symbol::delete_package "safe::$_"
1206     for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
1207    
1208     # remove register_script_function callbacks
1209     # TODO
1210    
1211     # unload cf.pm "a bit"
1212     delete $INC{"cf.pm"};
1213    
1214     # don't, removes xs symbols, too,
1215     # and global variables created in xs
1216     #Symbol::delete_package __PACKAGE__;
1217    
1218     # reload cf.pm
1219     $msg->("reloading cf.pm");
1220     require cf;
1221    
1222 root 1.73 # load config and database again
1223     cf::cfg_load;
1224 root 1.65 cf::db_load;
1225    
1226     # load extensions
1227     $msg->("load extensions");
1228     cf::load_extensions;
1229    
1230     # reattach attachments to objects
1231     $msg->("reattach");
1232     _global_reattach;
1233     };
1234     $msg->($@) if $@;
1235    
1236     $msg->("reloaded");
1237     };
1238    
1239     sub perl_reload() {
1240     _perl_reload {
1241     warn $_[0];
1242     print "$_[0]\n";
1243     };
1244     }
1245    
1246 root 1.85 register "<global>", __PACKAGE__;
1247    
1248     register_command "perl-reload" => sub {
1249 root 1.65 my ($who, $arg) = @_;
1250    
1251     if ($who->flag (FLAG_WIZ)) {
1252     _perl_reload {
1253     warn $_[0];
1254     $who->message ($_[0]);
1255     };
1256     }
1257     };
1258    
1259 root 1.27 unshift @INC, $LIBDIR;
1260 root 1.17
1261 root 1.35 $TICK_WATCHER = Event->timer (
1262 root 1.90 prio => 0,
1263 root 1.77 at => $NEXT_TICK || 1,
1264 root 1.87 data => WF_AUTOCANCEL,
1265 root 1.77 cb => sub {
1266 root 1.35 cf::server_tick; # one server iteration
1267    
1268     my $NOW = Event::time;
1269     $NEXT_TICK += $TICK;
1270    
1271 root 1.78 # if we are delayed by four ticks or more, skip them all
1272 root 1.37 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
1273 root 1.35
1274     $TICK_WATCHER->at ($NEXT_TICK);
1275     $TICK_WATCHER->start;
1276     },
1277     );
1278    
1279 root 1.80 IO::AIO::max_poll_time $TICK * 0.2;
1280 root 1.77
1281     Event->io (fd => IO::AIO::poll_fileno,
1282     poll => 'r',
1283     prio => 5,
1284 root 1.87 data => WF_AUTOCANCEL,
1285 root 1.77 cb => \&IO::AIO::poll_cb);
1286    
1287 root 1.1 1
1288