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.46 by root, Sun Aug 27 16:15:12 2006 UTC vs.
Revision 1.66 by root, Tue Sep 12 22:43:31 2006 UTC

11use Event; 11use Event;
12$Event::Eval = 1; # no idea why this is required, but it is 12$Event::Eval = 1; # no idea why this is required, but it is
13 13
14use strict; 14use strict;
15 15
16_init_vars;
17
16our %COMMAND = (); 18our %COMMAND = ();
17our @EVENT; 19our @EVENT;
18our %PROP_TYPE;
19our %PROP_IDX;
20our $LIBDIR = maps_directory "perl"; 20our $LIBDIR = maps_directory "perl";
21 21
22our $TICK = MAX_TIME * 1e-6; 22our $TICK = MAX_TIME * 1e-6;
23our $TICK_WATCHER; 23our $TICK_WATCHER;
24our $NEXT_TICK; 24our $NEXT_TICK;
32 print STDERR "cfperl: $msg"; 32 print STDERR "cfperl: $msg";
33 LOG llevError, "cfperl: $msg"; 33 LOG llevError, "cfperl: $msg";
34 }; 34 };
35} 35}
36 36
37my %ignore_set = (MAP_PROP_PATH => 1); # I hate the plug-in api. Deeply!
38
39# generate property mutators
40sub prop_gen {
41 my ($prefix, $class) = @_;
42
43 no strict 'refs';
44
45 for my $prop (keys %PROP_TYPE) {
46 $prop =~ /^\Q$prefix\E_(.*$)/ or next;
47 my $sub = lc $1;
48
49 my $type = $PROP_TYPE{$prop};
50 my $idx = $PROP_IDX {$prop};
51
52 *{"$class\::get_$sub"} = *{"$class\::$sub"} = sub {
53 $_[0]->get_property ($type, $idx)
54 };
55
56 *{"$class\::set_$sub"} = sub {
57 $_[0]->set_property ($type, $idx, $_[1]);
58 } unless $ignore_set{$prop};
59 }
60}
61
62# auto-generate most of the API
63
64prop_gen OBJECT_PROP => "cf::object";
65# CFAPI_OBJECT_ANIMATION?
66prop_gen PLAYER_PROP => "cf::object::player";
67
68prop_gen MAP_PROP => "cf::map";
69prop_gen ARCH_PROP => "cf::arch";
70
71@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 37@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
72 38
73# we bless all objects into (empty) derived classes to force a method lookup 39# we bless all objects into (empty) derived classes to force a method lookup
74# within the Safe compartment. 40# within the Safe compartment.
75for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch)) { 41for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) {
76 no strict 'refs'; 42 no strict 'refs';
77 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; 43 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
78} 44}
79 45
80$Event::DIED = sub { 46$Event::DIED = sub {
103} 69}
104 70
105############################################################################# 71#############################################################################
106# "new" plug-in system 72# "new" plug-in system
107 73
74=head3 EVENTS AND OBJECT ATTACHMENTS
75
76=over 4
77
78=item $object->attach ($attachment, key => $value...)
79
108=item $object->attach ($attachment, ...) 80=item $object->detach ($attachment)
109 81
110Attach a pre-registered attachment to an object. 82Attach/detach a pre-registered attachment to an object.
111 83
84=item $player->attach ($attachment, key => $value...)
85
112=item $player->attach ($attachment, ...) 86=item $player->detach ($attachment)
113 87
114Attach a pre-registered attachment to a player. 88Attach/detach a pre-registered attachment to a player.
115 89
116=item $map->attach ($attachment, ...) # not yet persistent 90=item $map->attach ($attachment, key => $value...)
117 91
92=item $map->detach ($attachment)
93
118Attach a pre-registered attachment to a map. 94Attach/detach a pre-registered attachment to a map.
95
96=item $bool = $object->attached ($name)
97
98=item $bool = $player->attached ($name)
99
100=item $bool = $map->attached ($name)
101
102Checks wether the named attachment is currently attached to the object.
119 103
120=item cf::attach_global ... 104=item cf::attach_global ...
121 105
122Attach handlers for global events. 106Attach handlers for global events.
123 107
150package and register them. Only handlers for eevents supported by the 134package and register them. Only handlers for eevents supported by the
151object/class are recognised. 135object/class are recognised.
152 136
153=back 137=back
154 138
155=item cf::attach_to_type $object_type, ... 139=item cf::attach_to_type $object_type, $subtype, ...
156 140
157Attach handlers for a specific object type (e.g. TRANSPORT). 141Attach handlers for a specific object type (e.g. TRANSPORT) and
142subtype. If C<$subtype> is zero or undef, matches all objects of the given
143type.
158 144
159=item cf::attach_to_objects ... 145=item cf::attach_to_objects ...
160 146
161Attach handlers to all objects. Do not use this except for debugging or 147Attach handlers to all objects. Do not use this except for debugging or
162very rare events, as handlers are (obviously) called for I<all> objects in 148very rare events, as handlers are (obviously) called for I<all> objects in
169=item cf::attach_to_maps ... 155=item cf::attach_to_maps ...
170 156
171Attach handlers to all maps. 157Attach handlers to all maps.
172 158
173=item cf:register_attachment $name, ... 159=item cf:register_attachment $name, ...
160
161Register an attachment by name through which objects can refer to this
162attachment.
163
164=item cf:register_player_attachment $name, ...
165
166Register an attachment by name through which players can refer to this
167attachment.
168
169=item cf:register_map_attachment $name, ...
170
171Register an attachment by name through which maps can refer to this
172attachment.
174 173
175=cut 174=cut
176 175
177# the following variables are defined in .xs and must not be re-created 176# the following variables are defined in .xs and must not be re-created
178our @CB_GLOBAL = (); # registry for all global events 177our @CB_GLOBAL = (); # registry for all global events
241 240
242 \%undo 241 \%undo
243} 242}
244 243
245sub _attach_attachment { 244sub _attach_attachment {
246 my ($klass, $obj, $name, @args) = q_; 245 my ($obj, $name, %arg) = @_;
246
247 return if exists $obj->{_attachment}{$name};
247 248
248 my $res; 249 my $res;
249 250
250 if (my $attach = $attachment{$name}) { 251 if (my $attach = $attachment{$name}) {
251 my $registry = $obj->registry; 252 my $registry = $obj->registry;
252 253
254 for (@$attach) {
255 my ($klass, @attach) = @$_;
253 $res = _attach @$registry, $klass, @$attach; 256 $res = _attach @$registry, $klass, @attach;
254
255 if (my $cb = delete $registry->[EVENT_OBJECT_INSTANTIATE]) {
256 for (@$cb) {
257 eval { $_->[1]->($obj, @args); };
258 if ($@) {
259 warn "$@";
260 warn "... while processing '$name' instantiate with args <@args>.\n";
261 }
262 } 257 }
263 } 258
259 $obj->{$name} = \%arg;
264 } else { 260 } else {
265 warn "object uses attachment '$name' that is not available, postponing.\n"; 261 warn "object uses attachment '$name' that is not available, postponing.\n";
266 } 262 }
267 263
268 push @{$obj->{_attachment}}, $name; 264 $obj->{_attachment}{$name} = undef;
269 265
270 $res->{attachment} = $name; 266 $res->{attachment} = $name;
271 $res 267 $res
272} 268}
273 269
274sub cf::object::attach { 270*cf::object::attach =
271*cf::player::attach =
272*cf::map::attach = sub {
275 my ($obj, $name, @args) = @_; 273 my ($obj, $name, %arg) = @_;
276 274
277 _attach_attachment KLASS_OBJECT, $obj, $name, @args; 275 _attach_attachment $obj, $name, %arg;
278} 276};
279 277
278# all those should be optimised
279*cf::object::detach =
280sub cf::player::attach { 280*cf::player::detach =
281*cf::map::detach = sub {
281 my ($obj, $name, @args) = @_; 282 my ($obj, $name) = @_;
282 283
283 _attach_attachment KLASS_PLAYER, $obj, $name, @args; 284 delete $obj->{_attachment}{$name};
284} 285 reattach ($obj);
286};
285 287
286sub cf::map::attach { 288*cf::object::attached =
289*cf::player::attached =
290*cf::map::attached = sub {
287 my ($obj, $name, @args) = @_; 291 my ($obj, $name) = @_;
288 292
289 _attach_attachment KLASS_MAP, $obj, $name, @args; 293 exists $obj->{_attachment}{$name}
290} 294};
291 295
292sub attach_global { 296sub attach_global {
293 _attach @CB_GLOBAL, KLASS_GLOBAL, @_ 297 _attach @CB_GLOBAL, KLASS_GLOBAL, @_
294} 298}
295 299
296sub attach_to_type { 300sub attach_to_type {
297 my $type = shift; 301 my $type = shift;
302 my $subtype = shift;
298 303
299 _attach @{$CB_TYPE[$type]}, KLASS_OBJECT, @_ 304 _attach @{$CB_TYPE[$type + $subtype * NUM_SUBTYPES]}, KLASS_OBJECT, @_
300} 305}
301 306
302sub attach_to_objects { 307sub attach_to_objects {
303 _attach @CB_OBJECT, KLASS_OBJECT, @_ 308 _attach @CB_OBJECT, KLASS_OBJECT, @_
304} 309}
312} 317}
313 318
314sub register_attachment { 319sub register_attachment {
315 my $name = shift; 320 my $name = shift;
316 321
322 $attachment{$name} = [[KLASS_OBJECT, @_]];
323}
324
325sub register_player_attachment {
326 my $name = shift;
327
328 $attachment{$name} = [[KLASS_PLAYER, @_]];
329}
330
331sub register_map_attachment {
332 my $name = shift;
333
317 $attachment{$name} = [@_]; 334 $attachment{$name} = [[KLASS_MAP, @_]];
318} 335}
319 336
320our $override; 337our $override;
321our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals? 338our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals?
322 339
336 for (@$callbacks) { 353 for (@$callbacks) {
337 eval { &{$_->[1]} }; 354 eval { &{$_->[1]} };
338 355
339 if ($@) { 356 if ($@) {
340 warn "$@"; 357 warn "$@";
341 warn "... while processing $EVENT[$event][0] event, skipping processing altogether.\n"; 358 warn "... while processing $EVENT[$event][0](@_) event, skipping processing altogether.\n";
342 override; 359 override;
343 } 360 }
344 361
345 return 1 if $override; 362 return 1 if $override;
346 } 363 }
347 364
348 0 365 0
349} 366}
367
368=item $bool = cf::invoke EVENT_GLOBAL_XXX, ...
369
370=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...)
371
372=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...)
373
374=item $bool = $map->invoke (EVENT_MAP_XXX, ...)
375
376Generate a global/object/player/map-specific event with the given arguments.
377
378This API is preliminary (most likely, the EVENT_KLASS_xxx prefix will be
379removed in future versions), and there is no public API to access override
380results (if you must, access C<@cf::invoke_results> directly).
381
382=back
383
384=head2 methods valid for all pointers
385
386=over 4
387
388=item $object->valid
389
390=item $player->valid
391
392=item $map->valid
393
394Just because you have a perl object does not mean that the corresponding
395C-level object still exists. If you try to access an object that has no
396valid C counterpart anymore you get an exception at runtime. This method
397can be used to test for existence of the C object part without causing an
398exception.
399
400=back
401
402=cut
403
404*cf::object::valid =
405*cf::player::valid =
406*cf::map::valid = \&cf::_valid;
350 407
351############################################################################# 408#############################################################################
352# object support 409# object support
353 410
354sub instantiate { 411sub instantiate {
356 413
357 $data = from_json $data; 414 $data = from_json $data;
358 415
359 for (@$data) { 416 for (@$data) {
360 my ($name, $args) = @$_; 417 my ($name, $args) = @$_;
361 attach $obj, $name, @{$args || [] }; 418
419 $obj->attach ($name, %{$args || {} });
362 } 420 }
363} 421}
364 422
365# basically do the same as instantiate, without calling instantiate 423# basically do the same as instantiate, without calling instantiate
366sub reattach { 424sub reattach {
367 warn "reattach<@_>\n";#d#
368 my ($obj) = @_; 425 my ($obj) = @_;
369 my $registry = $obj->registry; 426 my $registry = $obj->registry;
370 427
428 @$registry = ();
429
430 delete $obj->{_attachment} unless scalar keys %{ $obj->{_attachment} || {} };
431
371 for my $name (@{ $obj->{_attachment} }) { 432 for my $name (keys %{ $obj->{_attachment} || {} }) {
372 if (my $attach = $attachment{$name}) { 433 if (my $attach = $attachment{$name}) {
434 for (@$attach) {
435 my ($klass, @attach) = @$_;
373 _attach @$registry, KLASS_OBJECT, @$attach; 436 _attach @$registry, $klass, @attach;
437 }
374 } else { 438 } else {
375 warn "object uses attachment '$name' that is not available, postponing.\n"; 439 warn "object uses attachment '$name' that is not available, postponing.\n";
376 } 440 }
377 } 441 }
378
379 warn "reattach<@_, $_>\n";
380} 442}
381 443
382sub object_freezer_save { 444sub object_freezer_save {
383 my ($filename, $objs) = @_; 445 my ($filename, $rdata, $objs) = @_;
384 warn "freeze $filename\n";#d#
385 use Data::Dumper; print Dumper $objs;
386 446
387 $filename .= ".pst"; 447 if (length $$rdata) {
448 warn sprintf "saving %s (%d,%d)\n",
449 $filename, length $$rdata, scalar @$objs;
388 450
389 if (@$objs) {
390 open my $fh, ">:raw", "$filename~"; 451 if (open my $fh, ">:raw", "$filename~") {
391 chmod $fh, SAVE_MODE; 452 chmod SAVE_MODE, $fh;
453 syswrite $fh, $$rdata;
454 close $fh;
455
456 if (@$objs && open my $fh, ">:raw", "$filename.pst~") {
457 chmod SAVE_MODE, $fh;
392 syswrite $fh, Storable::nfreeze { version => 1, objs => $objs }; 458 syswrite $fh, Storable::nfreeze { version => 1, objs => $objs };
393 close $fh; 459 close $fh;
460 rename "$filename.pst~", "$filename.pst";
461 } else {
462 unlink "$filename.pst";
463 }
464
394 rename "$filename~", $filename; 465 rename "$filename~", $filename;
466 } else {
467 warn "FATAL: $filename~: $!\n";
468 }
395 } else { 469 } else {
396 unlink $filename; 470 unlink $filename;
471 unlink "$filename.pst";
397 } 472 }
398} 473}
399 474
400sub object_thawer_load { 475sub object_thawer_load {
401 my ($filename) = @_; 476 my ($filename) = @_;
402 477
403 warn "thaw $filename\n";#d# 478 local $/;
404 479
480 my $av;
481
482 #TODO: use sysread etc.
483 if (open my $data, "<:raw:perlio", $filename) {
484 $data = <$data>;
405 open my $fh, "<:raw:perlio", "$filename.pst" 485 if (open my $pst, "<:raw:perlio", "$filename.pst") {
406 or return; 486 $av = eval { (Storable::thaw <$pst>)->{objs} };
487 }
488 return ($data, $av);
489 }
407 490
408 eval { local $/; (Storable::thaw <$fh>)->{objs} } 491 ()
409} 492}
410 493
411attach_to_objects 494attach_to_objects
412 prio => -1000000, 495 prio => -1000000,
413 on_clone => sub { 496 on_clone => sub {
414 my ($src, $dst) = @_; 497 my ($src, $dst) = @_;
415 498
416 @{$dst->registry} = @{$src->registry}; 499 @{$dst->registry} = @{$src->registry};
417 warn "registry clone ", join ":", @{$src->registry};#d#
418 500
419 %$dst = %$src; 501 %$dst = %$src;
420 502
421 $dst->{_attachment} = [@{ $src->{_attachment} }] 503 %{$dst->{_attachment}} = %{$src->{_attachment}}
422 if exists $src->{_attachment}; 504 if exists $src->{_attachment};
423
424 warn "clone<@_>\n";#d#
425 }, 505 },
426; 506;
427 507
428############################################################################# 508#############################################################################
429# old plug-in events 509# old plug-in events
562 load_extension $ext; 642 load_extension $ext;
563 1 643 1
564 } or warn "$ext not loaded: $@"; 644 } or warn "$ext not loaded: $@";
565 } 645 }
566} 646}
567
568sub _perl_reload(&) {
569 my ($msg) = @_;
570
571 $msg->("reloading...");
572
573 eval {
574 # 1. cancel all watchers
575 $_->cancel for Event::all_watchers;
576
577 # 2. unload all extensions
578 for (@exts) {
579 $msg->("unloading <$_>");
580 unload_extension $_;
581 }
582
583 # 3. unload all modules loaded from $LIBDIR
584 while (my ($k, $v) = each %INC) {
585 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
586
587 $msg->("removing <$k>");
588 delete $INC{$k};
589
590 $k =~ s/\.pm$//;
591 $k =~ s/\//::/g;
592
593 if (my $cb = $k->can ("unload_module")) {
594 $cb->();
595 }
596
597 Symbol::delete_package $k;
598 }
599
600 # 4. get rid of safe::, as good as possible
601 Symbol::delete_package "safe::$_"
602 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
603
604 # 5. remove register_script_function callbacks
605 # TODO
606
607 # 6. unload cf.pm "a bit"
608 delete $INC{"cf.pm"};
609
610 # don't, removes xs symbols, too,
611 # and global variables created in xs
612 #Symbol::delete_package __PACKAGE__;
613
614 # 7. reload cf.pm
615 $msg->("reloading cf.pm");
616 require cf;
617 };
618 $msg->($@) if $@;
619
620 $msg->("reloaded");
621};
622
623sub perl_reload() {
624 _perl_reload {
625 warn $_[0];
626 print "$_[0]\n";
627 };
628}
629
630register_command "perl-reload", 0, sub {
631 my ($who, $arg) = @_;
632
633 if ($who->flag (FLAG_WIZ)) {
634 _perl_reload {
635 warn $_[0];
636 $who->message ($_[0]);
637 };
638 }
639};
640 647
641############################################################################# 648#############################################################################
642# extcmd framework, basically convert ext <msg> 649# extcmd framework, basically convert ext <msg>
643# into pkg::->on_extcmd_arg1 (...) while shortcutting a few 650# into pkg::->on_extcmd_arg1 (...) while shortcutting a few
644 651
669 my ($map) = @_; 676 my ($map) = @_;
670 677
671 my $path = $map->tmpname; 678 my $path = $map->tmpname;
672 defined $path or return; 679 defined $path or return;
673 680
674 unlink "$path.cfperl";
675 unlink "$path.pst"; 681 unlink "$path.pst";
676}; 682};
677 683
678*cf::mapsupport::on_swapin =
679*cf::mapsupport::on_load = sub {
680 my ($map) = @_;
681
682 my $path = $map->tmpname;
683 $path = $map->path unless defined $path;
684
685 open my $fh, "<:raw", "$path.cfperl"
686 or return; # no perl data
687
688 my $data = Storable::thaw do { local $/; <$fh> };
689
690 $data->{version} <= 1
691 or return; # too new
692
693 $map->_set_obs ($data->{obs});
694};
695
696attach_to_maps prio => -10000, package => cf::mapsupport::; 684attach_to_maps prio => -10000, package => cf::mapsupport::;
697 685
698############################################################################# 686#############################################################################
699# load/save perl data associated with player->ob objects 687# load/save perl data associated with player->ob objects
700 688
701sub all_objects(@) { 689sub all_objects(@) {
702 @_, map all_objects ($_->inv), @_ 690 @_, map all_objects ($_->inv), @_
703} 691}
704 692
693# TODO: compatibility cruft, remove when no longer needed
705attach_to_players 694attach_to_players
706 on_load => sub { 695 on_load => sub {
707 my ($pl, $path) = @_; 696 my ($pl, $path) = @_;
708 697
709 for my $o (all_objects $pl->ob) { 698 for my $o (all_objects $pl->ob) {
827 no strict 'refs'; 816 no strict 'refs';
828 *{"safe::$fun"} = $safe_hole->wrap ($cb); 817 *{"safe::$fun"} = $safe_hole->wrap ($cb);
829} 818}
830 819
831############################################################################# 820#############################################################################
821
822=head2 EXTENSION DATABASE SUPPORT
823
824Crossfire maintains a very simple database for extension use. It can
825currently store anything that can be serialised using Storable, which
826excludes objects.
827
828The parameter C<$family> should best start with the name of the extension
829using it, it should be unique.
830
831=over 4
832
833=item $hashref = cf::db_get $family
834
835Return a hashref for use by the extension C<$family>, which can be
836modified. After modifications, you have to call C<cf::db_dirty> or
837C<cf::db_sync>.
838
839=item $value = cf::db_get $family => $key
840
841Returns a single value from the database
842
843=item cf::db_put $family => $hashref
844
845Stores the given family hashref into the database. Updates are delayed, if
846you want the data to be synced to disk immediately, use C<cf::db_sync>.
847
848=item cf::db_put $family => $key => $value
849
850Stores the given C<$value> in the family hash. Updates are delayed, if you
851want the data to be synced to disk immediately, use C<cf::db_sync>.
852
853=item cf::db_dirty
854
855Marks the database as dirty, to be updated at a later time.
856
857=item cf::db_sync
858
859Immediately write the database to disk I<if it is dirty>.
860
861=cut
862
863{
864 my $db;
865 my $path = cf::localdir . "/database.pst";
866
867 sub db_load() {
868 warn "loading database $path\n";#d# remove later
869 $db = stat $path ? Storable::retrieve $path : { };
870 }
871
872 my $pid;
873
874 sub db_save() {
875 warn "saving database $path\n";#d# remove later
876 waitpid $pid, 0 if $pid;
877 unless ($pid = fork) {
878 $db->{_meta}{version} = 1;
879 Storable::nstore $db, "$path~";
880 rename "$path~", $path;
881 cf::_exit 0 if defined $pid;
882 }
883 }
884
885 my $dirty;
886
887 sub db_sync() {
888 db_save if $dirty;
889 undef $dirty;
890 }
891
892 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub {
893 db_sync;
894 });
895
896 sub db_dirty() {
897 $dirty = 1;
898 $idle->start;
899 }
900
901 sub db_get($;$) {
902 @_ >= 2
903 ? $db->{$_[0]}{$_[1]}
904 : ($db->{$_[0]} ||= { })
905 }
906
907 sub db_put($$;$) {
908 if (@_ >= 3) {
909 $db->{$_[0]}{$_[1]} = $_[2];
910 } else {
911 $db->{$_[0]} = $_[1];
912 }
913 db_dirty;
914 }
915}
916
917#############################################################################
832# the server's main() 918# the server's main()
833 919
834sub main { 920sub main {
921 db_load;
922 load_extensions;
835 Event::loop; 923 Event::loop;
836} 924}
837 925
838############################################################################# 926#############################################################################
839# initialisation 927# initialisation
840 928
929sub _perl_reload(&) {
930 my ($msg) = @_;
931
932 $msg->("reloading...");
933
934 eval {
935 # cancel all watchers
936 $_->cancel for Event::all_watchers;
937
938 # unload all extensions
939 for (@exts) {
940 $msg->("unloading <$_>");
941 unload_extension $_;
942 }
943
944 # unload all modules loaded from $LIBDIR
945 while (my ($k, $v) = each %INC) {
946 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
947
948 $msg->("removing <$k>");
949 delete $INC{$k};
950
951 $k =~ s/\.pm$//;
952 $k =~ s/\//::/g;
953
954 if (my $cb = $k->can ("unload_module")) {
955 $cb->();
956 }
957
958 Symbol::delete_package $k;
959 }
960
961 # sync database to disk
962 cf::db_sync;
963
964 # get rid of safe::, as good as possible
965 Symbol::delete_package "safe::$_"
966 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
967
968 # remove register_script_function callbacks
969 # TODO
970
971 # unload cf.pm "a bit"
972 delete $INC{"cf.pm"};
973
974 # don't, removes xs symbols, too,
975 # and global variables created in xs
976 #Symbol::delete_package __PACKAGE__;
977
978 # reload cf.pm
979 $msg->("reloading cf.pm");
980 require cf;
981
982 # load database again
983 cf::db_load;
984
985 # load extensions
986 $msg->("load extensions");
987 cf::load_extensions;
988
989 # reattach attachments to objects
990 $msg->("reattach");
991 _global_reattach;
992 };
993 $msg->($@) if $@;
994
995 $msg->("reloaded");
996};
997
998sub perl_reload() {
999 _perl_reload {
1000 warn $_[0];
1001 print "$_[0]\n";
1002 };
1003}
1004
1005register_command "perl-reload", 0, sub {
1006 my ($who, $arg) = @_;
1007
1008 if ($who->flag (FLAG_WIZ)) {
1009 _perl_reload {
1010 warn $_[0];
1011 $who->message ($_[0]);
1012 };
1013 }
1014};
1015
841register "<global>", __PACKAGE__; 1016register "<global>", __PACKAGE__;
842 1017
843unshift @INC, $LIBDIR; 1018unshift @INC, $LIBDIR;
844
845load_extensions;
846 1019
847$TICK_WATCHER = Event->timer ( 1020$TICK_WATCHER = Event->timer (
848 prio => 1, 1021 prio => 1,
849 at => $NEXT_TICK || 1, 1022 at => $NEXT_TICK || 1,
850 cb => sub { 1023 cb => sub {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines