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.85 by root, Mon Dec 11 22:56:57 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(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) { 88for my $pkg (qw(
89 cf::global
90 cf::object cf::object::player
91 cf::client cf::player
92 cf::arch cf::living
93 cf::map cf::party cf::region
94)) {
82 no strict 'refs'; 95 no strict 'refs';
83 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; 96 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
84} 97}
85 98
86$Event::DIED = sub { 99$Event::DIED = sub {
125 138
126=cut 139=cut
127 140
128############################################################################# 141#############################################################################
129 142
130=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+).
131 152
132=over 4 153=over 4
133 154
134=item $object->attach ($attachment, key => $value...)
135
136=item $object->detach ($attachment)
137
138Attach/detach a pre-registered attachment to an object.
139
140=item $player->attach ($attachment, key => $value...)
141
142=item $player->detach ($attachment)
143
144Attach/detach a pre-registered attachment to a player.
145
146=item $map->attach ($attachment, key => $value...) 155=item $attachable->attach ($attachment, key => $value...)
147 156
148=item $map->detach ($attachment) 157=item $attachable->detach ($attachment)
149 158
150Attach/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.
151 161
152=item $bool = $object->attached ($name) 162Example, attach a minesweeper attachment to the given object, making it a
16310x10 minesweeper game:
153 164
154=item $bool = $player->attached ($name) 165 $obj->attach (minesweeper => width => 10, height => 10);
155 166
156=item $bool = $map->attached ($name) 167=item $bool = $attachable->attached ($name)
157 168
158Checks wether the named attachment is currently attached to the object. 169Checks wether the named attachment is currently attached to the object.
159 170
160=item cf::attach_global ... 171=item cf::CLASS->attach ...
161 172
162Attach handlers for global events. 173=item cf::CLASS->detach ...
163 174
164This and all following C<attach_*>-functions expect any number of the 175Define an anonymous attachment and attach it to all objects of the given
165following 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:
166 209
167=over 4 210=over 4
168 211
169=item prio => $number 212=item prio => $number
170 213
172by another C<prio> setting). Lower priority handlers get executed 215by another C<prio> setting). Lower priority handlers get executed
173earlier. 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
174registered at priority C<-1000>, so lower priorities should not be used 217registered at priority C<-1000>, so lower priorities should not be used
175unless you know what you are doing. 218unless you know what you are doing.
176 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
177=item on_I<event> => \&cb 226=item on_I<event> => \&cb
178 227
179Call the given code reference whenever the named event happens (event is 228Call the given code reference whenever the named event happens (event is
180something 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
181handlers are recognised generally depends on the type of object these 230handlers are recognised generally depends on the type of object these
190package and register them. Only handlers for eevents supported by the 239package and register them. Only handlers for eevents supported by the
191object/class are recognised. 240object/class are recognised.
192 241
193=back 242=back
194 243
195=item cf::attach_to_type $object_type, $subtype, ... 244Example, define an attachment called "sockpuppet" that calls the given
245event handler when a monster attacks:
196 246
197Attach handlers for a specific object type (e.g. TRANSPORT) and 247 cf::object::attachment sockpuppet =>
198subtype. If C<$subtype> is zero or undef, matches all objects of the given 248 on_skill_attack => sub {
199type. 249 my ($self, $victim) = @_;
200 250 ...
201=item cf::attach_to_objects ... 251 }
202 252 }
203Attach handlers to all objects. Do not use this except for debugging or
204very rare events, as handlers are (obviously) called for I<all> objects in
205the game.
206
207=item cf::attach_to_players ...
208
209Attach handlers to all players.
210
211=item cf::attach_to_maps ...
212
213Attach handlers to all maps.
214
215=item cf:register_attachment $name, ...
216
217Register an attachment by name through which objects can refer to this
218attachment.
219
220=item cf:register_player_attachment $name, ...
221
222Register an attachment by name through which players can refer to this
223attachment.
224
225=item cf:register_map_attachment $name, ...
226
227Register an attachment by name through which maps can refer to this
228attachment.
229 253
230=cut 254=cut
231 255
232# 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
233our @CB_GLOBAL = (); # registry for all global events 257our @CB_GLOBAL = (); # registry for all global events
234our @CB_OBJECT = (); # all objects (should not be used except in emergency) 258our @CB_OBJECT = (); # all objects (should not be used except in emergency)
235our @CB_PLAYER = (); 259our @CB_PLAYER = ();
260our @CB_CLIENT = ();
236our @CB_TYPE = (); # registry for type (cf-object class) based events 261our @CB_TYPE = (); # registry for type (cf-object class) based events
237our @CB_MAP = (); 262our @CB_MAP = ();
238 263
239my %attachment; 264my %attachment;
240 265
241sub _attach_cb($\%$$$) { 266sub _attach_cb($$$$) {
242 my ($registry, $undo, $event, $prio, $cb) = @_; 267 my ($registry, $event, $prio, $cb) = @_;
243 268
244 use sort 'stable'; 269 use sort 'stable';
245 270
246 $cb = [$prio, $cb]; 271 $cb = [$prio, $cb];
247 272
248 @{$registry->[$event]} = sort 273 @{$registry->[$event]} = sort
249 { $a->[0] cmp $b->[0] } 274 { $a->[0] cmp $b->[0] }
250 @{$registry->[$event] || []}, $cb; 275 @{$registry->[$event] || []}, $cb;
251
252 push @{$undo->{cb}}, [$event, $cb];
253} 276}
254 277
255# attach handles attaching event callbacks 278# attach handles attaching event callbacks
256# 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
257# registry (== where the callback attaches to). 280# registry (== where the callback attaches to).
258sub _attach(\@$@) { 281sub _attach {
259 my ($registry, $klass, @arg) = @_; 282 my ($registry, $klass, @arg) = @_;
260 283
284 my $object_type;
261 my $prio = 0; 285 my $prio = 0;
262
263 my %undo = (
264 registry => $registry,
265 cb => [],
266 );
267
268 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;
269 287
270 while (@arg) { 288 while (@arg) {
271 my $type = shift @arg; 289 my $type = shift @arg;
272 290
273 if ($type eq "prio") { 291 if ($type eq "prio") {
274 $prio = shift @arg; 292 $prio = shift @arg;
275 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
276 } elsif ($type eq "package") { 303 } elsif ($type eq "package") {
277 my $pkg = shift @arg; 304 my $pkg = shift @arg;
278 305
279 while (my ($name, $id) = each %cb_id) { 306 while (my ($name, $id) = each %cb_id) {
280 if (my $cb = $pkg->can ($name)) { 307 if (my $cb = $pkg->can ($name)) {
281 _attach_cb $registry, %undo, $id, $prio, $cb; 308 _attach_cb $registry, $id, $prio, $cb;
282 } 309 }
283 } 310 }
284 311
285 } elsif (exists $cb_id{$type}) { 312 } elsif (exists $cb_id{$type}) {
286 _attach_cb $registry, %undo, $cb_id{$type}, $prio, shift @arg; 313 _attach_cb $registry, $cb_id{$type}, $prio, shift @arg;
287 314
288 } elsif (ref $type) { 315 } elsif (ref $type) {
289 warn "attaching objects not supported, ignoring.\n"; 316 warn "attaching objects not supported, ignoring.\n";
290 317
291 } else { 318 } else {
292 shift @arg; 319 shift @arg;
293 warn "attach argument '$type' not supported, ignoring.\n"; 320 warn "attach argument '$type' not supported, ignoring.\n";
294 } 321 }
295 } 322 }
296
297 \%undo
298} 323}
299 324
300sub _attach_attachment { 325sub _object_attach {
301 my ($obj, $name, %arg) = @_; 326 my ($obj, $name, %arg) = @_;
302 327
303 return if exists $obj->{_attachment}{$name}; 328 return if exists $obj->{_attachment}{$name};
304
305 my $res;
306 329
307 if (my $attach = $attachment{$name}) { 330 if (my $attach = $attachment{$name}) {
308 my $registry = $obj->registry; 331 my $registry = $obj->registry;
309 332
310 for (@$attach) { 333 for (@$attach) {
311 my ($klass, @attach) = @$_; 334 my ($klass, @attach) = @$_;
312 $res = _attach @$registry, $klass, @attach; 335 _attach $registry, $klass, @attach;
313 } 336 }
314 337
315 $obj->{$name} = \%arg; 338 $obj->{$name} = \%arg;
316 } else { 339 } else {
317 warn "object uses attachment '$name' that is not available, postponing.\n"; 340 warn "object uses attachment '$name' that is not available, postponing.\n";
318 } 341 }
319 342
320 $obj->{_attachment}{$name} = undef; 343 $obj->{_attachment}{$name} = undef;
321
322 $res->{attachment} = $name;
323 $res
324} 344}
325 345
326*cf::object::attach = 346sub cf::attachable::attach {
327*cf::player::attach = 347 if (ref $_[0]) {
328*cf::map::attach = sub { 348 _object_attach @_;
329 my ($obj, $name, %arg) = @_; 349 } else {
330 350 _attach shift->_attach_registry, @_;
331 _attach_attachment $obj, $name, %arg; 351 }
332}; 352};
333 353
334# all those should be optimised 354# all those should be optimised
335*cf::object::detach = 355sub cf::attachable::detach {
336*cf::player::detach =
337*cf::map::detach = sub {
338 my ($obj, $name) = @_; 356 my ($obj, $name) = @_;
339 357
358 if (ref $obj) {
340 delete $obj->{_attachment}{$name}; 359 delete $obj->{_attachment}{$name};
341 reattach ($obj); 360 reattach ($obj);
361 } else {
362 Carp::croak "cannot, currently, detach class attachments";
363 }
342}; 364};
343 365
344*cf::object::attached = 366sub cf::attachable::attached {
345*cf::player::attached =
346*cf::map::attached = sub {
347 my ($obj, $name) = @_; 367 my ($obj, $name) = @_;
348 368
349 exists $obj->{_attachment}{$name} 369 exists $obj->{_attachment}{$name}
350};
351
352sub attach_global {
353 _attach @CB_GLOBAL, KLASS_GLOBAL, @_
354} 370}
355 371
356sub attach_to_type { 372for my $klass (qw(GLOBAL OBJECT PLAYER CLIENT MAP)) {
357 my $type = shift; 373 eval "#line " . __LINE__ . " 'cf.pm'
358 my $subtype = shift; 374 sub cf::\L$klass\E::_attach_registry {
375 (\\\@CB_$klass, KLASS_$klass)
376 }
359 377
360 _attach @{$CB_TYPE[$type + $subtype * NUM_SUBTYPES]}, KLASS_OBJECT, @_ 378 sub cf::\L$klass\E::attachment {
361}
362
363sub attach_to_objects {
364 _attach @CB_OBJECT, KLASS_OBJECT, @_
365}
366
367sub attach_to_players {
368 _attach @CB_PLAYER, KLASS_PLAYER, @_
369}
370
371sub attach_to_maps {
372 _attach @CB_MAP, KLASS_MAP, @_
373}
374
375sub register_attachment {
376 my $name = shift; 379 my \$name = shift;
377 380
378 $attachment{$name} = [[KLASS_OBJECT, @_]];
379}
380
381sub register_player_attachment {
382 my $name = shift;
383
384 $attachment{$name} = [[KLASS_PLAYER, @_]];
385}
386
387sub register_map_attachment {
388 my $name = shift;
389
390 $attachment{$name} = [[KLASS_MAP, @_]]; 381 \$attachment{\$name} = [[KLASS_$klass, \@_]];
382 }
383 ";
384 die if $@;
391} 385}
392 386
393our $override; 387our $override;
394our @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?
395 389
425 419
426=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...) 420=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...)
427 421
428=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...) 422=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...)
429 423
424=item $bool = $client->invoke (EVENT_CLIENT_XXX, ...)
425
430=item $bool = $map->invoke (EVENT_MAP_XXX, ...) 426=item $bool = $map->invoke (EVENT_MAP_XXX, ...)
431 427
432Generate a global/object/player/map-specific event with the given arguments. 428Generate a global/object/player/map-specific event with the given arguments.
433 429
434This 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
439 435
440=cut 436=cut
441 437
442############################################################################# 438#############################################################################
443 439
444=head2 METHODS VALID FOR ALL CORE OBJECTS 440=head2 METHODS VALID FOR ALL ATTACHABLE OBJECTS
441
442Attachable objects includes objects, players, clients and maps.
445 443
446=over 4 444=over 4
447 445
448=item $object->valid, $player->valid, $map->valid 446=item $object->valid
449 447
450Just 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
451C-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
452valid C counterpart anymore you get an exception at runtime. This method 450valid C counterpart anymore you get an exception at runtime. This method
453can 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
455 453
456=back 454=back
457 455
458=cut 456=cut
459 457
460*cf::object::valid =
461*cf::player::valid =
462*cf::map::valid = \&cf::_valid;
463
464############################################################################# 458#############################################################################
465# object support 459# object support
466 460
467sub instantiate { 461sub instantiate {
468 my ($obj, $data) = @_; 462 my ($obj, $data) = @_;
487 481
488 for my $name (keys %{ $obj->{_attachment} || {} }) { 482 for my $name (keys %{ $obj->{_attachment} || {} }) {
489 if (my $attach = $attachment{$name}) { 483 if (my $attach = $attachment{$name}) {
490 for (@$attach) { 484 for (@$attach) {
491 my ($klass, @attach) = @$_; 485 my ($klass, @attach) = @$_;
492 _attach @$registry, $klass, @attach; 486 _attach $registry, $klass, @attach;
493 } 487 }
494 } else { 488 } else {
495 warn "object uses attachment '$name' that is not available, postponing.\n"; 489 warn "object uses attachment '$name' that is not available, postponing.\n";
496 } 490 }
497 } 491 }
553 } 547 }
554 548
555 () 549 ()
556} 550}
557 551
558attach_to_objects 552cf::object->attach (
559 prio => -1000000, 553 prio => -1000000,
560 on_clone => sub { 554 on_clone => sub {
561 my ($src, $dst) = @_; 555 my ($src, $dst) = @_;
562 556
563 @{$dst->registry} = @{$src->registry}; 557 @{$dst->registry} = @{$src->registry};
565 %$dst = %$src; 559 %$dst = %$src;
566 560
567 %{$dst->{_attachment}} = %{$src->{_attachment}} 561 %{$dst->{_attachment}} = %{$src->{_attachment}}
568 if exists $src->{_attachment}; 562 if exists $src->{_attachment};
569 }, 563 },
570; 564);
571 565
572############################################################################# 566#############################################################################
573# command handling &c 567# command handling &c
574 568
575=item cf::register_command $name => \&callback($ob,$args); 569=item cf::register_command $name => \&callback($ob,$args);
604 #warn "registering extcmd '$name' to '$caller'"; 598 #warn "registering extcmd '$name' to '$caller'";
605 599
606 $EXTCMD{$name} = [$cb, $caller]; 600 $EXTCMD{$name} = [$cb, $caller];
607} 601}
608 602
609attach_to_players 603cf::player->attach (
610 on_command => sub { 604 on_command => sub {
611 my ($pl, $name, $params) = @_; 605 my ($pl, $name, $params) = @_;
612 606
613 my $cb = $COMMAND{$name} 607 my $cb = $COMMAND{$name}
614 or return; 608 or return;
634 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; 628 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
635 } 629 }
636 630
637 cf::override; 631 cf::override;
638 }, 632 },
639; 633);
640 634
641sub register { 635sub register {
642 my ($base, $pkg) = @_; 636 my ($base, $pkg) = @_;
643 637
644 #TODO 638 #TODO
713 707
714 Symbol::delete_package $pkg; 708 Symbol::delete_package $pkg;
715} 709}
716 710
717sub load_extensions { 711sub load_extensions {
718 my $LIBDIR = maps_directory "perl";
719
720 for my $ext (<$LIBDIR/*.ext>) { 712 for my $ext (<$LIBDIR/*.ext>) {
721 next unless -r $ext; 713 next unless -r $ext;
722 eval { 714 eval {
723 load_extension $ext; 715 load_extension $ext;
724 1 716 1
736 defined $path or return; 728 defined $path or return;
737 729
738 unlink "$path.pst"; 730 unlink "$path.pst";
739}; 731};
740 732
741attach_to_maps prio => -10000, package => cf::mapsupport::; 733cf::map->attach (prio => -10000, package => cf::mapsupport::);
742 734
743############################################################################# 735#############################################################################
744# load/save perl data associated with player->ob objects 736# load/save perl data associated with player->ob objects
745 737
746sub all_objects(@) { 738sub all_objects(@) {
747 @_, map all_objects ($_->inv), @_ 739 @_, map all_objects ($_->inv), @_
748} 740}
749 741
750# TODO: compatibility cruft, remove when no longer needed 742# TODO: compatibility cruft, remove when no longer needed
751attach_to_players 743cf::player->attach (
752 on_load => sub { 744 on_load => sub {
753 my ($pl, $path) = @_; 745 my ($pl, $path) = @_;
754 746
755 for my $o (all_objects $pl->ob) { 747 for my $o (all_objects $pl->ob) {
756 if (my $value = $o->get_ob_key_value ("_perl_data")) { 748 if (my $value = $o->get_ob_key_value ("_perl_data")) {
758 750
759 %$o = %{ Storable::thaw pack "H*", $value }; 751 %$o = %{ Storable::thaw pack "H*", $value };
760 } 752 }
761 } 753 }
762 }, 754 },
763; 755);
764 756
765############################################################################# 757#############################################################################
766 758
767=head2 CORE EXTENSIONS 759=head2 CORE EXTENSIONS
768 760
859 851
860=pod 852=pod
861 853
862The following fucntions and emthods are available within a safe environment: 854The following fucntions and emthods are available within a safe environment:
863 855
864 cf::object contr pay_amount pay_player 856 cf::object contr pay_amount pay_player map
865 cf::object::player player 857 cf::object::player player
866 cf::player peaceful 858 cf::player peaceful
859 cf::map trigger
867 860
868=cut 861=cut
869 862
870for ( 863for (
871 ["cf::object" => qw(contr pay_amount pay_player)], 864 ["cf::object" => qw(contr pay_amount pay_player map)],
872 ["cf::object::player" => qw(player)], 865 ["cf::object::player" => qw(player)],
873 ["cf::player" => qw(peaceful)], 866 ["cf::player" => qw(peaceful)],
867 ["cf::map" => qw(trigger)],
874) { 868) {
875 no strict 'refs'; 869 no strict 'refs';
876 my ($pkg, @funs) = @$_; 870 my ($pkg, @funs) = @$_;
877 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 871 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
878 for @funs; 872 for @funs;
1018 sub db_sync() { 1012 sub db_sync() {
1019 db_save if $dirty; 1013 db_save if $dirty;
1020 undef $dirty; 1014 undef $dirty;
1021 } 1015 }
1022 1016
1023 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 {
1024 db_sync; 1018 db_sync;
1025 }); 1019 });
1026 1020
1027 sub db_dirty() { 1021 sub db_dirty() {
1028 $dirty = 1; 1022 $dirty = 1;
1042 $DB->{$_[0]} = $_[1]; 1036 $DB->{$_[0]} = $_[1];
1043 } 1037 }
1044 db_dirty; 1038 db_dirty;
1045 } 1039 }
1046 1040
1047 attach_global 1041 cf::global->attach (
1048 prio => 10000, 1042 prio => 10000,
1049 on_cleanup => sub { 1043 on_cleanup => sub {
1050 db_sync; 1044 db_sync;
1051 }, 1045 },
1052 ; 1046 );
1053} 1047}
1054 1048
1055############################################################################# 1049#############################################################################
1056# the server's main() 1050# the server's main()
1057 1051
1078 1072
1079 $msg->("reloading..."); 1073 $msg->("reloading...");
1080 1074
1081 eval { 1075 eval {
1082 # cancel all watchers 1076 # cancel all watchers
1083 $_->cancel for Event::all_watchers; 1077 for (Event::all_watchers) {
1078 $_->cancel if $_->data & WF_AUTOCANCEL;
1079 }
1084 1080
1085 # unload all extensions 1081 # unload all extensions
1086 for (@exts) { 1082 for (@exts) {
1087 $msg->("unloading <$_>"); 1083 $msg->("unloading <$_>");
1088 unload_extension $_; 1084 unload_extension $_;
1164}; 1160};
1165 1161
1166unshift @INC, $LIBDIR; 1162unshift @INC, $LIBDIR;
1167 1163
1168$TICK_WATCHER = Event->timer ( 1164$TICK_WATCHER = Event->timer (
1169 prio => 1, 1165 prio => 0,
1170 async => 1,
1171 at => $NEXT_TICK || 1, 1166 at => $NEXT_TICK || 1,
1167 data => WF_AUTOCANCEL,
1172 cb => sub { 1168 cb => sub {
1173 cf::server_tick; # one server iteration 1169 cf::server_tick; # one server iteration
1174 1170
1175 my $NOW = Event::time; 1171 my $NOW = Event::time;
1176 $NEXT_TICK += $TICK; 1172 $NEXT_TICK += $TICK;
1186IO::AIO::max_poll_time $TICK * 0.2; 1182IO::AIO::max_poll_time $TICK * 0.2;
1187 1183
1188Event->io (fd => IO::AIO::poll_fileno, 1184Event->io (fd => IO::AIO::poll_fileno,
1189 poll => 'r', 1185 poll => 'r',
1190 prio => 5, 1186 prio => 5,
1187 data => WF_AUTOCANCEL,
1191 cb => \&IO::AIO::poll_cb); 1188 cb => \&IO::AIO::poll_cb);
1192 1189
11931 11901
1194 1191

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines