ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.86 by root, Thu Dec 14 05:09:32 2006 UTC vs.
Revision 1.94 by root, Thu Dec 21 23:02:54 2006 UTC

16# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode? 16# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
17$YAML::Syck::ImplicitUnicode = 1; 17$YAML::Syck::ImplicitUnicode = 1;
18 18
19use strict; 19use strict;
20 20
21sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload
22
21our %COMMAND = (); 23our %COMMAND = ();
22our %COMMAND_TIME = (); 24our %COMMAND_TIME = ();
23our %EXTCMD = (); 25our %EXTCMD = ();
24 26
25_init_vars; 27_init_vars;
26 28
27our @EVENT; 29our @EVENT;
28our $LIBDIR = maps_directory "perl"; 30our $LIBDIR = datadir . "/ext";
29 31
30our $TICK = MAX_TIME * 1e-6; 32our $TICK = MAX_TIME * 1e-6;
31our $TICK_WATCHER; 33our $TICK_WATCHER;
32our $NEXT_TICK; 34our $NEXT_TICK;
33 35
72 print STDERR "cfperl: $msg"; 74 print STDERR "cfperl: $msg";
73 LOG llevError, "cfperl: $msg"; 75 LOG llevError, "cfperl: $msg";
74 }; 76 };
75} 77}
76 78
79@safe::cf::global::ISA = @cf::global::ISA = 'cf::attachable';
80@safe::cf::object::ISA = @cf::object::ISA = 'cf::attachable';
81@safe::cf::player::ISA = @cf::player::ISA = 'cf::attachable';
82@safe::cf::client::ISA = @cf::client::ISA = 'cf::attachable';
83@safe::cf::map::ISA = @cf::map::ISA = 'cf::attachable';
77@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 84@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
78 85
79# we bless all objects into (empty) derived classes to force a method lookup 86# we bless all objects into (empty) derived classes to force a method lookup
80# within the Safe compartment. 87# within the Safe compartment.
81for my $pkg (qw( 88for my $pkg (qw(
89 cf::global
82 cf::object cf::object::player 90 cf::object cf::object::player
83 cf::client_socket cf::player 91 cf::client cf::player
84 cf::arch cf::living 92 cf::arch cf::living
85 cf::map cf::party cf::region 93 cf::map cf::party cf::region
86)) { 94)) {
87 no strict 'refs'; 95 no strict 'refs';
88 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; 96 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
130 138
131=cut 139=cut
132 140
133############################################################################# 141#############################################################################
134 142
135=head2 EVENTS AND OBJECT ATTACHMENTS 143=head2 ATTACHABLE OBJECTS
144
145Many objects in crossfire are so-called attachable objects. That means you can
146attach callbacks/event handlers (a collection of which is called an "attachment")
147to it. All such attachable objects support the following methods.
148
149In the following description, CLASS can be any of C<global>, C<object>
150C<player>, C<client> or C<map> (i.e. the attachable objects in
151crossfire+).
136 152
137=over 4 153=over 4
138 154
139=item $object->attach ($attachment, key => $value...)
140
141=item $object->detach ($attachment)
142
143Attach/detach a pre-registered attachment to an object.
144
145=item $player->attach ($attachment, key => $value...)
146
147=item $player->detach ($attachment)
148
149Attach/detach a pre-registered attachment to a player.
150
151=item $map->attach ($attachment, key => $value...) 155=item $attachable->attach ($attachment, key => $value...)
152 156
153=item $map->detach ($attachment) 157=item $attachable->detach ($attachment)
154 158
155Attach/detach a pre-registered attachment to a map. 159Attach/detach a pre-registered attachment to a specific object and give it
160the specified key/value pairs as arguments.
156 161
157=item $bool = $object->attached ($name) 162Example, attach a minesweeper attachment to the given object, making it a
16310x10 minesweeper game:
158 164
159=item $bool = $player->attached ($name) 165 $obj->attach (minesweeper => width => 10, height => 10);
160 166
161=item $bool = $map->attached ($name) 167=item $bool = $attachable->attached ($name)
162 168
163Checks wether the named attachment is currently attached to the object. 169Checks wether the named attachment is currently attached to the object.
164 170
165=item cf::attach_global ... 171=item cf::CLASS->attach ...
166 172
167Attach handlers for global events. 173=item cf::CLASS->detach ...
168 174
169This and all following C<attach_*>-functions expect any number of the 175Define an anonymous attachment and attach it to all objects of the given
170following handler/hook descriptions: 176CLASS. See the next function for an explanation of its arguments.
177
178You can attach to global events by using the C<cf::global> class.
179
180Example, log all player logins:
181
182 cf::player->attach (
183 on_login => sub {
184 my ($pl) = @_;
185 ...
186 },
187 );
188
189Example, attach to the jeweler skill:
190
191 cf::object->attach (
192 type => cf::SKILL,
193 subtype => cf::SK_JEWELER,
194 on_use_skill => sub {
195 my ($sk, $ob, $part, $dir, $msg) = @_;
196 ...
197 },
198 );
199
200=item cf::CLASS::attachment $name, ...
201
202Register an attachment by C<$name> through which attachable objects of the
203given CLASS can refer to this attachment.
204
205Some classes such as crossfire maps and objects can specify attachments
206that are attached at load/instantiate time, thus the need for a name.
207
208These calls expect any number of the following handler/hook descriptions:
171 209
172=over 4 210=over 4
173 211
174=item prio => $number 212=item prio => $number
175 213
177by another C<prio> setting). Lower priority handlers get executed 215by another C<prio> setting). Lower priority handlers get executed
178earlier. The default priority is C<0>, and many built-in handlers are 216earlier. The default priority is C<0>, and many built-in handlers are
179registered at priority C<-1000>, so lower priorities should not be used 217registered at priority C<-1000>, so lower priorities should not be used
180unless you know what you are doing. 218unless you know what you are doing.
181 219
220=item type => $type
221
222(Only for C<< cf::object->attach >> calls), limits the attachment to the
223given type of objects only (the additional parameter C<subtype> can be
224used to further limit to the given subtype).
225
182=item on_I<event> => \&cb 226=item on_I<event> => \&cb
183 227
184Call the given code reference whenever the named event happens (event is 228Call the given code reference whenever the named event happens (event is
185something like C<instantiate>, C<apply>, C<use_skill> and so on, and which 229something like C<instantiate>, C<apply>, C<use_skill> and so on, and which
186handlers are recognised generally depends on the type of object these 230handlers are recognised generally depends on the type of object these
195package and register them. Only handlers for eevents supported by the 239package and register them. Only handlers for eevents supported by the
196object/class are recognised. 240object/class are recognised.
197 241
198=back 242=back
199 243
200=item cf::attach_to_type $object_type, $subtype, ... 244Example, define an attachment called "sockpuppet" that calls the given
245event handler when a monster attacks:
201 246
202Attach handlers for a specific object type (e.g. TRANSPORT) and 247 cf::object::attachment sockpuppet =>
203subtype. If C<$subtype> is zero or undef, matches all objects of the given 248 on_skill_attack => sub {
204type. 249 my ($self, $victim) = @_;
205 250 ...
206=item cf::attach_to_objects ... 251 }
207 252 }
208Attach handlers to all objects. Do not use this except for debugging or
209very rare events, as handlers are (obviously) called for I<all> objects in
210the game.
211
212=item cf::attach_to_players ...
213
214Attach handlers to all players.
215
216=item cf::attach_to_maps ...
217
218Attach handlers to all maps.
219
220=item cf:register_attachment $name, ...
221
222Register an attachment by name through which objects can refer to this
223attachment.
224
225=item cf:register_player_attachment $name, ...
226
227Register an attachment by name through which players can refer to this
228attachment.
229
230=item cf:register_map_attachment $name, ...
231
232Register an attachment by name through which maps can refer to this
233attachment.
234 253
235=cut 254=cut
236 255
237# the following variables are defined in .xs and must not be re-created 256# the following variables are defined in .xs and must not be re-created
238our @CB_GLOBAL = (); # registry for all global events 257our @CB_GLOBAL = (); # registry for all global events
239our @CB_OBJECT = (); # all objects (should not be used except in emergency) 258our @CB_OBJECT = (); # all objects (should not be used except in emergency)
240our @CB_PLAYER = (); 259our @CB_PLAYER = ();
260our @CB_CLIENT = ();
241our @CB_TYPE = (); # registry for type (cf-object class) based events 261our @CB_TYPE = (); # registry for type (cf-object class) based events
242our @CB_MAP = (); 262our @CB_MAP = ();
243 263
244my %attachment; 264my %attachment;
245 265
246sub _attach_cb($\%$$$) { 266sub _attach_cb($$$$) {
247 my ($registry, $undo, $event, $prio, $cb) = @_; 267 my ($registry, $event, $prio, $cb) = @_;
248 268
249 use sort 'stable'; 269 use sort 'stable';
250 270
251 $cb = [$prio, $cb]; 271 $cb = [$prio, $cb];
252 272
253 @{$registry->[$event]} = sort 273 @{$registry->[$event]} = sort
254 { $a->[0] cmp $b->[0] } 274 { $a->[0] cmp $b->[0] }
255 @{$registry->[$event] || []}, $cb; 275 @{$registry->[$event] || []}, $cb;
256
257 push @{$undo->{cb}}, [$event, $cb];
258} 276}
259 277
260# attach handles attaching event callbacks 278# attach handles attaching event callbacks
261# the only thing the caller has to do is pass the correct 279# the only thing the caller has to do is pass the correct
262# registry (== where the callback attaches to). 280# registry (== where the callback attaches to).
263sub _attach(\@$@) { 281sub _attach {
264 my ($registry, $klass, @arg) = @_; 282 my ($registry, $klass, @arg) = @_;
265 283
284 my $object_type;
266 my $prio = 0; 285 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; 286 my %cb_id = map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == $klass, 0 .. $#EVENT;
274 287
275 while (@arg) { 288 while (@arg) {
276 my $type = shift @arg; 289 my $type = shift @arg;
277 290
278 if ($type eq "prio") { 291 if ($type eq "prio") {
279 $prio = shift @arg; 292 $prio = shift @arg;
280 293
294 } elsif ($type eq "type") {
295 $object_type = shift @arg;
296 $registry = $CB_TYPE[$object_type] ||= [];
297
298 } elsif ($type eq "subtype") {
299 defined $object_type or Carp::croak "subtype specified without type";
300 my $object_subtype = shift @arg;
301 $registry = $CB_TYPE[$object_type + $object_subtype * NUM_SUBTYPES] ||= [];
302
281 } elsif ($type eq "package") { 303 } elsif ($type eq "package") {
282 my $pkg = shift @arg; 304 my $pkg = shift @arg;
283 305
284 while (my ($name, $id) = each %cb_id) { 306 while (my ($name, $id) = each %cb_id) {
285 if (my $cb = $pkg->can ($name)) { 307 if (my $cb = $pkg->can ($name)) {
286 _attach_cb $registry, %undo, $id, $prio, $cb; 308 _attach_cb $registry, $id, $prio, $cb;
287 } 309 }
288 } 310 }
289 311
290 } elsif (exists $cb_id{$type}) { 312 } elsif (exists $cb_id{$type}) {
291 _attach_cb $registry, %undo, $cb_id{$type}, $prio, shift @arg; 313 _attach_cb $registry, $cb_id{$type}, $prio, shift @arg;
292 314
293 } elsif (ref $type) { 315 } elsif (ref $type) {
294 warn "attaching objects not supported, ignoring.\n"; 316 warn "attaching objects not supported, ignoring.\n";
295 317
296 } else { 318 } else {
297 shift @arg; 319 shift @arg;
298 warn "attach argument '$type' not supported, ignoring.\n"; 320 warn "attach argument '$type' not supported, ignoring.\n";
299 } 321 }
300 } 322 }
301
302 \%undo
303} 323}
304 324
305sub _attach_attachment { 325sub _object_attach {
306 my ($obj, $name, %arg) = @_; 326 my ($obj, $name, %arg) = @_;
307 327
308 return if exists $obj->{_attachment}{$name}; 328 return if exists $obj->{_attachment}{$name};
309
310 my $res;
311 329
312 if (my $attach = $attachment{$name}) { 330 if (my $attach = $attachment{$name}) {
313 my $registry = $obj->registry; 331 my $registry = $obj->registry;
314 332
315 for (@$attach) { 333 for (@$attach) {
316 my ($klass, @attach) = @$_; 334 my ($klass, @attach) = @$_;
317 $res = _attach @$registry, $klass, @attach; 335 _attach $registry, $klass, @attach;
318 } 336 }
319 337
320 $obj->{$name} = \%arg; 338 $obj->{$name} = \%arg;
321 } else { 339 } else {
322 warn "object uses attachment '$name' that is not available, postponing.\n"; 340 warn "object uses attachment '$name' that is not available, postponing.\n";
323 } 341 }
324 342
325 $obj->{_attachment}{$name} = undef; 343 $obj->{_attachment}{$name} = undef;
326
327 $res->{attachment} = $name;
328 $res
329} 344}
330 345
331*cf::object::attach = 346sub cf::attachable::attach {
332*cf::player::attach = 347 if (ref $_[0]) {
333*cf::map::attach = sub { 348 _object_attach @_;
334 my ($obj, $name, %arg) = @_; 349 } else {
335 350 _attach shift->_attach_registry, @_;
336 _attach_attachment $obj, $name, %arg; 351 }
337}; 352};
338 353
339# all those should be optimised 354# all those should be optimised
340*cf::object::detach = 355sub cf::attachable::detach {
341*cf::player::detach =
342*cf::map::detach = sub {
343 my ($obj, $name) = @_; 356 my ($obj, $name) = @_;
344 357
358 if (ref $obj) {
345 delete $obj->{_attachment}{$name}; 359 delete $obj->{_attachment}{$name};
346 reattach ($obj); 360 reattach ($obj);
361 } else {
362 Carp::croak "cannot, currently, detach class attachments";
363 }
347}; 364};
348 365
349*cf::object::attached = 366sub cf::attachable::attached {
350*cf::player::attached =
351*cf::map::attached = sub {
352 my ($obj, $name) = @_; 367 my ($obj, $name) = @_;
353 368
354 exists $obj->{_attachment}{$name} 369 exists $obj->{_attachment}{$name}
355};
356
357sub attach_global {
358 _attach @CB_GLOBAL, KLASS_GLOBAL, @_
359} 370}
360 371
361sub attach_to_type { 372for my $klass (qw(GLOBAL OBJECT PLAYER CLIENT MAP)) {
362 my $type = shift; 373 eval "#line " . __LINE__ . " 'cf.pm'
363 my $subtype = shift; 374 sub cf::\L$klass\E::_attach_registry {
375 (\\\@CB_$klass, KLASS_$klass)
376 }
364 377
365 _attach @{$CB_TYPE[$type + $subtype * NUM_SUBTYPES]}, KLASS_OBJECT, @_ 378 sub cf::\L$klass\E::attachment {
366}
367
368sub attach_to_objects {
369 _attach @CB_OBJECT, KLASS_OBJECT, @_
370}
371
372sub attach_to_players {
373 _attach @CB_PLAYER, KLASS_PLAYER, @_
374}
375
376sub attach_to_maps {
377 _attach @CB_MAP, KLASS_MAP, @_
378}
379
380sub register_attachment {
381 my $name = shift; 379 my \$name = shift;
382 380
383 $attachment{$name} = [[KLASS_OBJECT, @_]];
384}
385
386sub register_player_attachment {
387 my $name = shift;
388
389 $attachment{$name} = [[KLASS_PLAYER, @_]];
390}
391
392sub register_map_attachment {
393 my $name = shift;
394
395 $attachment{$name} = [[KLASS_MAP, @_]]; 381 \$attachment{\$name} = [[KLASS_$klass, \@_]];
382 }
383 ";
384 die if $@;
396} 385}
397 386
398our $override; 387our $override;
399our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals? 388our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals?
400 389
430 419
431=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...) 420=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...)
432 421
433=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...) 422=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...)
434 423
424=item $bool = $client->invoke (EVENT_CLIENT_XXX, ...)
425
435=item $bool = $map->invoke (EVENT_MAP_XXX, ...) 426=item $bool = $map->invoke (EVENT_MAP_XXX, ...)
436 427
437Generate a global/object/player/map-specific event with the given arguments. 428Generate a global/object/player/map-specific event with the given arguments.
438 429
439This API is preliminary (most likely, the EVENT_KLASS_xxx prefix will be 430This API is preliminary (most likely, the EVENT_KLASS_xxx prefix will be
444 435
445=cut 436=cut
446 437
447############################################################################# 438#############################################################################
448 439
449=head2 METHODS VALID FOR ALL CORE OBJECTS 440=head2 METHODS VALID FOR ALL ATTACHABLE OBJECTS
441
442Attachable objects includes objects, players, clients and maps.
450 443
451=over 4 444=over 4
452 445
453=item $object->valid, $player->valid, $map->valid 446=item $object->valid
454 447
455Just because you have a perl object does not mean that the corresponding 448Just because you have a perl object does not mean that the corresponding
456C-level object still exists. If you try to access an object that has no 449C-level object still exists. If you try to access an object that has no
457valid C counterpart anymore you get an exception at runtime. This method 450valid C counterpart anymore you get an exception at runtime. This method
458can be used to test for existence of the C object part without causing an 451can be used to test for existence of the C object part without causing an
460 453
461=back 454=back
462 455
463=cut 456=cut
464 457
465*cf::object::valid =
466*cf::player::valid =
467*cf::map::valid = \&cf::_valid;
468
469############################################################################# 458#############################################################################
470# object support 459# object support
471 460
472sub instantiate { 461sub instantiate {
473 my ($obj, $data) = @_; 462 my ($obj, $data) = @_;
492 481
493 for my $name (keys %{ $obj->{_attachment} || {} }) { 482 for my $name (keys %{ $obj->{_attachment} || {} }) {
494 if (my $attach = $attachment{$name}) { 483 if (my $attach = $attachment{$name}) {
495 for (@$attach) { 484 for (@$attach) {
496 my ($klass, @attach) = @$_; 485 my ($klass, @attach) = @$_;
497 _attach @$registry, $klass, @attach; 486 _attach $registry, $klass, @attach;
498 } 487 }
499 } else { 488 } else {
500 warn "object uses attachment '$name' that is not available, postponing.\n"; 489 warn "object uses attachment '$name' that is not available, postponing.\n";
501 } 490 }
502 } 491 }
558 } 547 }
559 548
560 () 549 ()
561} 550}
562 551
563attach_to_objects 552cf::object->attach (
564 prio => -1000000, 553 prio => -1000000,
565 on_clone => sub { 554 on_clone => sub {
566 my ($src, $dst) = @_; 555 my ($src, $dst) = @_;
567 556
568 @{$dst->registry} = @{$src->registry}; 557 @{$dst->registry} = @{$src->registry};
570 %$dst = %$src; 559 %$dst = %$src;
571 560
572 %{$dst->{_attachment}} = %{$src->{_attachment}} 561 %{$dst->{_attachment}} = %{$src->{_attachment}}
573 if exists $src->{_attachment}; 562 if exists $src->{_attachment};
574 }, 563 },
575; 564);
576 565
577############################################################################# 566#############################################################################
578# command handling &c 567# command handling &c
579 568
580=item cf::register_command $name => \&callback($ob,$args); 569=item cf::register_command $name => \&callback($ob,$args);
609 #warn "registering extcmd '$name' to '$caller'"; 598 #warn "registering extcmd '$name' to '$caller'";
610 599
611 $EXTCMD{$name} = [$cb, $caller]; 600 $EXTCMD{$name} = [$cb, $caller];
612} 601}
613 602
614attach_to_players 603cf::player->attach (
615 on_command => sub { 604 on_command => sub {
616 my ($pl, $name, $params) = @_; 605 my ($pl, $name, $params) = @_;
617 606
618 my $cb = $COMMAND{$name} 607 my $cb = $COMMAND{$name}
619 or return; 608 or return;
639 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; 628 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
640 } 629 }
641 630
642 cf::override; 631 cf::override;
643 }, 632 },
644; 633);
645 634
646sub register { 635sub register {
647 my ($base, $pkg) = @_; 636 my ($base, $pkg) = @_;
648 637
649 #TODO 638 #TODO
718 707
719 Symbol::delete_package $pkg; 708 Symbol::delete_package $pkg;
720} 709}
721 710
722sub load_extensions { 711sub load_extensions {
723 my $LIBDIR = maps_directory "perl";
724
725 for my $ext (<$LIBDIR/*.ext>) { 712 for my $ext (<$LIBDIR/*.ext>) {
726 next unless -r $ext; 713 next unless -r $ext;
727 eval { 714 eval {
728 load_extension $ext; 715 load_extension $ext;
729 1 716 1
741 defined $path or return; 728 defined $path or return;
742 729
743 unlink "$path.pst"; 730 unlink "$path.pst";
744}; 731};
745 732
746attach_to_maps prio => -10000, package => cf::mapsupport::; 733cf::map->attach (prio => -10000, package => cf::mapsupport::);
747 734
748############################################################################# 735#############################################################################
749# load/save perl data associated with player->ob objects 736# load/save perl data associated with player->ob objects
750 737
751sub all_objects(@) { 738sub all_objects(@) {
752 @_, map all_objects ($_->inv), @_ 739 @_, map all_objects ($_->inv), @_
753} 740}
754 741
755# TODO: compatibility cruft, remove when no longer needed 742# TODO: compatibility cruft, remove when no longer needed
756attach_to_players 743cf::player->attach (
757 on_load => sub { 744 on_load => sub {
758 my ($pl, $path) = @_; 745 my ($pl, $path) = @_;
759 746
760 for my $o (all_objects $pl->ob) { 747 for my $o (all_objects $pl->ob) {
761 if (my $value = $o->get_ob_key_value ("_perl_data")) { 748 if (my $value = $o->get_ob_key_value ("_perl_data")) {
763 750
764 %$o = %{ Storable::thaw pack "H*", $value }; 751 %$o = %{ Storable::thaw pack "H*", $value };
765 } 752 }
766 } 753 }
767 }, 754 },
768; 755);
769 756
770############################################################################# 757#############################################################################
771 758
772=head2 CORE EXTENSIONS 759=head2 CORE EXTENSIONS
773 760
864 851
865=pod 852=pod
866 853
867The following fucntions and emthods are available within a safe environment: 854The following fucntions and emthods are available within a safe environment:
868 855
869 cf::object contr pay_amount pay_player 856 cf::object contr pay_amount pay_player map
870 cf::object::player player 857 cf::object::player player
871 cf::player peaceful 858 cf::player peaceful
859 cf::map trigger
872 860
873=cut 861=cut
874 862
875for ( 863for (
876 ["cf::object" => qw(contr pay_amount pay_player)], 864 ["cf::object" => qw(contr pay_amount pay_player map)],
877 ["cf::object::player" => qw(player)], 865 ["cf::object::player" => qw(player)],
878 ["cf::player" => qw(peaceful)], 866 ["cf::player" => qw(peaceful)],
867 ["cf::map" => qw(trigger)],
879) { 868) {
880 no strict 'refs'; 869 no strict 'refs';
881 my ($pkg, @funs) = @$_; 870 my ($pkg, @funs) = @$_;
882 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 871 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
883 for @funs; 872 for @funs;
1023 sub db_sync() { 1012 sub db_sync() {
1024 db_save if $dirty; 1013 db_save if $dirty;
1025 undef $dirty; 1014 undef $dirty;
1026 } 1015 }
1027 1016
1028 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub { 1017 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, data => WF_AUTOCANCEL, cb => sub {
1029 db_sync; 1018 db_sync;
1030 }); 1019 });
1031 1020
1032 sub db_dirty() { 1021 sub db_dirty() {
1033 $dirty = 1; 1022 $dirty = 1;
1047 $DB->{$_[0]} = $_[1]; 1036 $DB->{$_[0]} = $_[1];
1048 } 1037 }
1049 db_dirty; 1038 db_dirty;
1050 } 1039 }
1051 1040
1052 attach_global 1041 cf::global->attach (
1053 prio => 10000, 1042 prio => 10000,
1054 on_cleanup => sub { 1043 on_cleanup => sub {
1055 db_sync; 1044 db_sync;
1056 }, 1045 },
1057 ; 1046 );
1058} 1047}
1059 1048
1060############################################################################# 1049#############################################################################
1061# the server's main() 1050# the server's main()
1062 1051
1083 1072
1084 $msg->("reloading..."); 1073 $msg->("reloading...");
1085 1074
1086 eval { 1075 eval {
1087 # cancel all watchers 1076 # cancel all watchers
1088 $_->cancel for Event::all_watchers; 1077 for (Event::all_watchers) {
1078 $_->cancel if $_->data & WF_AUTOCANCEL;
1079 }
1089 1080
1090 # unload all extensions 1081 # unload all extensions
1091 for (@exts) { 1082 for (@exts) {
1092 $msg->("unloading <$_>"); 1083 $msg->("unloading <$_>");
1093 unload_extension $_; 1084 unload_extension $_;
1169}; 1160};
1170 1161
1171unshift @INC, $LIBDIR; 1162unshift @INC, $LIBDIR;
1172 1163
1173$TICK_WATCHER = Event->timer ( 1164$TICK_WATCHER = Event->timer (
1174 prio => 1, 1165 prio => 0,
1175 async => 1,
1176 at => $NEXT_TICK || 1, 1166 at => $NEXT_TICK || 1,
1167 data => WF_AUTOCANCEL,
1177 cb => sub { 1168 cb => sub {
1178 cf::server_tick; # one server iteration 1169 cf::server_tick; # one server iteration
1179 1170
1180 my $NOW = Event::time; 1171 my $NOW = Event::time;
1181 $NEXT_TICK += $TICK; 1172 $NEXT_TICK += $TICK;
1191IO::AIO::max_poll_time $TICK * 0.2; 1182IO::AIO::max_poll_time $TICK * 0.2;
1192 1183
1193Event->io (fd => IO::AIO::poll_fileno, 1184Event->io (fd => IO::AIO::poll_fileno,
1194 poll => 'r', 1185 poll => 'r',
1195 prio => 5, 1186 prio => 5,
1187 data => WF_AUTOCANCEL,
1196 cb => \&IO::AIO::poll_cb); 1188 cb => \&IO::AIO::poll_cb);
1197 1189
11981 11901
1199 1191

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines