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.57 by root, Wed Aug 30 11:21:24 2006 UTC vs.
Revision 1.82 by root, Sun Dec 3 20:59:52 2006 UTC

5use Storable; 5use Storable;
6use Opcode; 6use Opcode;
7use Safe; 7use Safe;
8use Safe::Hole; 8use Safe::Hole;
9 9
10use IO::AIO ();
11use YAML::Syck ();
10use Time::HiRes; 12use Time::HiRes;
11use Event; 13use Event;
12$Event::Eval = 1; # no idea why this is required, but it is 14$Event::Eval = 1; # no idea why this is required, but it is
13 15
16# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
17$YAML::Syck::ImplicitUnicode = 1;
18
14use strict; 19use strict;
15 20
16_reload_1; 21_init_vars;
17 22
18our %COMMAND = (); 23our %COMMAND = ();
19our @EVENT; 24our @EVENT;
20our %PROP_TYPE;
21our %PROP_IDX;
22our $LIBDIR = maps_directory "perl"; 25our $LIBDIR = maps_directory "perl";
23 26
24our $TICK = MAX_TIME * 1e-6; 27our $TICK = MAX_TIME * 1e-6;
25our $TICK_WATCHER; 28our $TICK_WATCHER;
26our $NEXT_TICK; 29our $NEXT_TICK;
30
31our %CFG;
32
33our $uptime;
34
35$uptime ||= time;
36
37#############################################################################
38
39=head2 GLOBAL VARIABLES
40
41=over 4
42
43=item $cf::LIBDIR
44
45The perl library directory, where extensions and cf-specific modules can
46be found. It will be added to C<@INC> automatically.
47
48=item $cf::TICK
49
50The interval between server ticks, in seconds.
51
52=item %cf::CFG
53
54Configuration for the server, loaded from C</etc/crossfire/config>, or
55from wherever your confdir points to.
56
57=back
58
59=cut
27 60
28BEGIN { 61BEGIN {
29 *CORE::GLOBAL::warn = sub { 62 *CORE::GLOBAL::warn = sub {
30 my $msg = join "", @_; 63 my $msg = join "", @_;
31 $msg .= "\n" 64 $msg .= "\n"
34 print STDERR "cfperl: $msg"; 67 print STDERR "cfperl: $msg";
35 LOG llevError, "cfperl: $msg"; 68 LOG llevError, "cfperl: $msg";
36 }; 69 };
37} 70}
38 71
39my %ignore_set = (MAP_PROP_PATH => 1); # I hate the plug-in api. Deeply!
40
41# generate property mutators
42sub prop_gen {
43 my ($prefix, $class) = @_;
44
45 no strict 'refs';
46
47 for my $prop (keys %PROP_TYPE) {
48 $prop =~ /^\Q$prefix\E_(.*$)/ or next;
49 my $sub = lc $1;
50
51 my $type = $PROP_TYPE{$prop};
52 my $idx = $PROP_IDX {$prop};
53
54 *{"$class\::get_$sub"} = *{"$class\::$sub"} = sub {
55 $_[0]->get_property ($type, $idx)
56 };
57
58 *{"$class\::set_$sub"} = sub {
59 $_[0]->set_property ($type, $idx, $_[1]);
60 } unless $ignore_set{$prop};
61 }
62}
63
64# auto-generate most of the API
65
66prop_gen OBJECT_PROP => "cf::object";
67# CFAPI_OBJECT_ANIMATION?
68prop_gen PLAYER_PROP => "cf::object::player";
69
70prop_gen MAP_PROP => "cf::map";
71prop_gen ARCH_PROP => "cf::arch";
72
73@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 72@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
74 73
75# we bless all objects into (empty) derived classes to force a method lookup 74# we bless all objects into (empty) derived classes to force a method lookup
76# within the Safe compartment. 75# within the Safe compartment.
77for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) { 76for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) {
87my @exts; 86my @exts;
88my @hook; 87my @hook;
89my %command; 88my %command;
90my %extcmd; 89my %extcmd;
91 90
92############################################################################# 91=head2 UTILITY FUNCTIONS
93# utility functions 92
93=over 4
94
95=cut
94 96
95use JSON::Syck (); # TODO# replace by JSON::PC once working 97use JSON::Syck (); # TODO# replace by JSON::PC once working
98
99=item $ref = cf::from_json $json
100
101Converts a JSON string into the corresponding perl data structure.
102
103=cut
96 104
97sub from_json($) { 105sub from_json($) {
98 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs 106 $JSON::Syck::ImplicitUnicode = 1; # work around JSON::Syck bugs
99 JSON::Syck::Load $_[0] 107 JSON::Syck::Load $_[0]
100} 108}
101 109
110=item $json = cf::to_json $ref
111
112Converts a perl data structure into its JSON representation.
113
114=cut
115
102sub to_json($) { 116sub to_json($) {
103 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs 117 $JSON::Syck::ImplicitUnicode = 0; # work around JSON::Syck bugs
104 JSON::Syck::Dump $_[0] 118 JSON::Syck::Dump $_[0]
105} 119}
106 120
107############################################################################# 121=back
108# "new" plug-in system
109 122
123=cut
124
125#############################################################################
126
110=head3 EVENTS AND OBJECT ATTACHMENTS 127=head2 EVENTS AND OBJECT ATTACHMENTS
111 128
112=over 4 129=over 4
113 130
114=item $object->attach ($attachment, key => $value...) 131=item $object->attach ($attachment, key => $value...)
115 132
389 for (@$callbacks) { 406 for (@$callbacks) {
390 eval { &{$_->[1]} }; 407 eval { &{$_->[1]} };
391 408
392 if ($@) { 409 if ($@) {
393 warn "$@"; 410 warn "$@";
394 warn "... while processing $EVENT[$event][0] event, skipping processing altogether.\n"; 411 warn "... while processing $EVENT[$event][0](@_) event, skipping processing altogether.\n";
395 override; 412 override;
396 } 413 }
397 414
398 return 1 if $override; 415 return 1 if $override;
399 } 416 }
415removed in future versions), and there is no public API to access override 432removed in future versions), and there is no public API to access override
416results (if you must, access C<@cf::invoke_results> directly). 433results (if you must, access C<@cf::invoke_results> directly).
417 434
418=back 435=back
419 436
420=head2 methods valid for all pointers 437=cut
438
439#############################################################################
440
441=head2 METHODS VALID FOR ALL CORE OBJECTS
421 442
422=over 4 443=over 4
423 444
424=item $object->valid 445=item $object->valid, $player->valid, $map->valid
425
426=item $player->valid
427
428=item $map->valid
429 446
430Just because you have a perl object does not mean that the corresponding 447Just because you have a perl object does not mean that the corresponding
431C-level object still exists. If you try to access an object that has no 448C-level object still exists. If you try to access an object that has no
432valid C counterpart anymore you get an exception at runtime. This method 449valid C counterpart anymore you get an exception at runtime. This method
433can be used to test for existence of the C object part without causing an 450can be used to test for existence of the C object part without causing an
476 } 493 }
477 } 494 }
478} 495}
479 496
480sub object_freezer_save { 497sub object_freezer_save {
481 my ($filename, $objs) = @_; 498 my ($filename, $rdata, $objs) = @_;
482 499
483 if (@$objs) { 500 if (length $$rdata) {
501 warn sprintf "saving %s (%d,%d)\n",
502 $filename, length $$rdata, scalar @$objs;
503
484 open my $fh, ">:raw", "$filename.pst~"; 504 if (open my $fh, ">:raw", "$filename~") {
505 chmod SAVE_MODE, $fh;
506 syswrite $fh, $$rdata;
507 close $fh;
508
509 if (@$objs && open my $fh, ">:raw", "$filename.pst~") {
510 chmod SAVE_MODE, $fh;
485 syswrite $fh, Storable::nfreeze { version => 1, objs => $objs }; 511 syswrite $fh, Storable::nfreeze { version => 1, objs => $objs };
486 close $fh; 512 close $fh;
487 unlink "$filename.cfperl";
488 chmod SAVE_MODE, "$filename.pst~";
489 rename "$filename.pst~", "$filename.pst"; 513 rename "$filename.pst~", "$filename.pst";
514 } else {
515 unlink "$filename.pst";
516 }
517
518 rename "$filename~", $filename;
519 } else {
520 warn "FATAL: $filename~: $!\n";
521 }
490 } else { 522 } else {
523 unlink $filename;
491 unlink "$filename.pst"; 524 unlink "$filename.pst";
492 } 525 }
526}
493 527
494 chmod SAVE_MODE, "$filename~"; 528sub object_freezer_as_string {
495 rename "$filename~", $filename; 529 my ($rdata, $objs) = @_;
530
531 use Data::Dumper;
532
533 $$rdata . Dumper $objs
496} 534}
497 535
498sub object_thawer_load { 536sub object_thawer_load {
499 my ($filename) = @_; 537 my ($filename) = @_;
500 538
539 local $/;
540
541 my $av;
542
543 #TODO: use sysread etc.
544 if (open my $data, "<:raw:perlio", $filename) {
545 $data = <$data>;
501 open my $fh, "<:raw:perlio", "$filename.pst" 546 if (open my $pst, "<:raw:perlio", "$filename.pst") {
502 or return; 547 $av = eval { (Storable::thaw <$pst>)->{objs} };
548 }
549 return ($data, $av);
550 }
503 551
504 eval { local $/; (Storable::thaw <$fh>)->{objs} } 552 ()
505} 553}
506 554
507attach_to_objects 555attach_to_objects
508 prio => -1000000, 556 prio => -1000000,
509 on_clone => sub { 557 on_clone => sub {
594 . "#line 1 \"$path\"\n{\n" 642 . "#line 1 \"$path\"\n{\n"
595 . (do { local $/; <$fh> }) 643 . (do { local $/; <$fh> })
596 . "\n};\n1"; 644 . "\n};\n1";
597 645
598 eval $source 646 eval $source
599 or die "$path: $@"; 647 or die $@ ? "$path: $@\n"
648 : "extension disabled.\n";
600 649
601 push @exts, $pkg; 650 push @exts, $pkg;
602 $ext_pkg{$base} = $pkg; 651 $ext_pkg{$base} = $pkg;
603 652
604# no strict 'refs'; 653# no strict 'refs';
655 load_extension $ext; 704 load_extension $ext;
656 1 705 1
657 } or warn "$ext not loaded: $@"; 706 } or warn "$ext not loaded: $@";
658 } 707 }
659} 708}
660
661sub _perl_reload(&) {
662 my ($msg) = @_;
663
664 $msg->("reloading...");
665
666 eval {
667 # 1. cancel all watchers
668 $_->cancel for Event::all_watchers;
669
670 # 2. unload all extensions
671 for (@exts) {
672 $msg->("unloading <$_>");
673 unload_extension $_;
674 }
675
676 # 3. unload all modules loaded from $LIBDIR
677 while (my ($k, $v) = each %INC) {
678 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
679
680 $msg->("removing <$k>");
681 delete $INC{$k};
682
683 $k =~ s/\.pm$//;
684 $k =~ s/\//::/g;
685
686 if (my $cb = $k->can ("unload_module")) {
687 $cb->();
688 }
689
690 Symbol::delete_package $k;
691 }
692
693 # 4. get rid of safe::, as good as possible
694 Symbol::delete_package "safe::$_"
695 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
696
697 # 5. remove register_script_function callbacks
698 # TODO
699
700 # 6. unload cf.pm "a bit"
701 delete $INC{"cf.pm"};
702
703 # don't, removes xs symbols, too,
704 # and global variables created in xs
705 #Symbol::delete_package __PACKAGE__;
706
707 # 7. reload cf.pm
708 $msg->("reloading cf.pm");
709 require cf;
710 };
711 $msg->($@) if $@;
712
713 $msg->("reloaded");
714};
715
716sub perl_reload() {
717 _perl_reload {
718 warn $_[0];
719 print "$_[0]\n";
720 };
721}
722
723register_command "perl-reload", 0, sub {
724 my ($who, $arg) = @_;
725
726 if ($who->flag (FLAG_WIZ)) {
727 _perl_reload {
728 warn $_[0];
729 $who->message ($_[0]);
730 };
731 }
732};
733 709
734############################################################################# 710#############################################################################
735# extcmd framework, basically convert ext <msg> 711# extcmd framework, basically convert ext <msg>
736# into pkg::->on_extcmd_arg1 (...) while shortcutting a few 712# into pkg::->on_extcmd_arg1 (...) while shortcutting a few
737 713
765 defined $path or return; 741 defined $path or return;
766 742
767 unlink "$path.pst"; 743 unlink "$path.pst";
768}; 744};
769 745
770# old style persistent data, TODO: remove #d#
771*cf::mapsupport::on_swapin = sub {
772 my ($map) = @_;
773
774 my $path = $map->tmpname;
775 $path = $map->path unless defined $path;
776
777 open my $fh, "<:raw", "$path.cfperl"
778 or return; # no perl data
779
780 my $data = Storable::thaw do { local $/; <$fh> };
781
782 $data->{version} <= 1
783 or return; # too new
784
785 $map->_set_obs ($data->{obs});
786 $map->invoke (EVENT_MAP_UPGRADE);
787};
788
789attach_to_maps prio => -10000, package => cf::mapsupport::; 746attach_to_maps prio => -10000, package => cf::mapsupport::;
790 747
791############################################################################# 748#############################################################################
792# load/save perl data associated with player->ob objects 749# load/save perl data associated with player->ob objects
793 750
794sub all_objects(@) { 751sub all_objects(@) {
795 @_, map all_objects ($_->inv), @_ 752 @_, map all_objects ($_->inv), @_
796} 753}
797 754
755# TODO: compatibility cruft, remove when no longer needed
798attach_to_players 756attach_to_players
799 on_load => sub { 757 on_load => sub {
800 my ($pl, $path) = @_; 758 my ($pl, $path) = @_;
801 759
802 for my $o (all_objects $pl->ob) { 760 for my $o (all_objects $pl->ob) {
808 } 766 }
809 }, 767 },
810; 768;
811 769
812############################################################################# 770#############################################################################
813# core extensions - in perl 771
772=head2 CORE EXTENSIONS
773
774Functions and methods that extend core crossfire objects.
775
776=over 4
814 777
815=item cf::player::exists $login 778=item cf::player::exists $login
816 779
817Returns true when the given account exists. 780Returns true when the given account exists.
818 781
821sub cf::player::exists($) { 784sub cf::player::exists($) {
822 cf::player::find $_[0] 785 cf::player::find $_[0]
823 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; 786 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2;
824} 787}
825 788
826=item $player->reply ($npc, $msg[, $flags]) 789=item $player_object->reply ($npc, $msg[, $flags])
827 790
828Sends a message to the player, as if the npc C<$npc> replied. C<$npc> 791Sends a message to the player, as if the npc C<$npc> replied. C<$npc>
829can be C<undef>. Does the right thing when the player is currently in a 792can be C<undef>. Does the right thing when the player is currently in a
830dialogue with the given NPC character. 793dialogue with the given NPC character.
831 794
858 $msg{msgid} = $id; 821 $msg{msgid} = $id;
859 822
860 $self->send ("ext " . to_json \%msg); 823 $self->send ("ext " . to_json \%msg);
861} 824}
862 825
826=item $player_object->may ("access")
827
828Returns wether the given player is authorized to access resource "access"
829(e.g. "command_wizcast").
830
831=cut
832
833sub cf::object::player::may {
834 my ($self, $access) = @_;
835
836 $self->flag (cf::FLAG_WIZ) ||
837 (ref $cf::CFG{"may_$access"}
838 ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}}
839 : $cf::CFG{"may_$access"})
840}
841
842=cut
843
863############################################################################# 844#############################################################################
864# map scripting support 845
846=head2 SAFE SCRIPTING
847
848Functions that provide a safe environment to compile and execute
849snippets of perl code without them endangering the safety of the server
850itself. Looping constructs, I/O operators and other built-in functionality
851is not available in the safe scripting environment, and the number of
852functions and methods that can be called is greatly reduced.
853
854=cut
865 855
866our $safe = new Safe "safe"; 856our $safe = new Safe "safe";
867our $safe_hole = new Safe::Hole; 857our $safe_hole = new Safe::Hole;
868 858
869$SIG{FPE} = 'IGNORE'; 859$SIG{FPE} = 'IGNORE';
870 860
871$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); 861$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time));
872 862
873# here we export the classes and methods available to script code 863# here we export the classes and methods available to script code
864
865=pod
866
867The following fucntions and emthods are available within a safe environment:
868
869 cf::object contr pay_amount pay_player
870 cf::object::player player
871 cf::player peaceful
872
873=cut
874 874
875for ( 875for (
876 ["cf::object" => qw(contr pay_amount pay_player)], 876 ["cf::object" => qw(contr pay_amount pay_player)],
877 ["cf::object::player" => qw(player)], 877 ["cf::object::player" => qw(player)],
878 ["cf::player" => qw(peaceful)], 878 ["cf::player" => qw(peaceful)],
881 my ($pkg, @funs) = @$_; 881 my ($pkg, @funs) = @$_;
882 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"}) 882 *{"safe::$pkg\::$_"} = $safe_hole->wrap (\&{"$pkg\::$_"})
883 for @funs; 883 for @funs;
884} 884}
885 885
886=over 4
887
888=item @retval = safe_eval $code, [var => value, ...]
889
890Compiled and executes the given perl code snippet. additional var/value
891pairs result in temporary local (my) scalar variables of the given name
892that are available in the code snippet. Example:
893
894 my $five = safe_eval '$first + $second', first => 1, second => 4;
895
896=cut
897
886sub safe_eval($;@) { 898sub safe_eval($;@) {
887 my ($code, %vars) = @_; 899 my ($code, %vars) = @_;
888 900
889 my $qcode = $code; 901 my $qcode = $code;
890 $qcode =~ s/"/‟/g; # not allowed in #line filenames 902 $qcode =~ s/"/‟/g; # not allowed in #line filenames
912 } 924 }
913 925
914 wantarray ? @res : $res[0] 926 wantarray ? @res : $res[0]
915} 927}
916 928
929=item cf::register_script_function $function => $cb
930
931Register a function that can be called from within map/npc scripts. The
932function should be reasonably secure and should be put into a package name
933like the extension.
934
935Example: register a function that gets called whenever a map script calls
936C<rent::overview>, as used by the C<rent> extension.
937
938 cf::register_script_function "rent::overview" => sub {
939 ...
940 };
941
942=cut
943
917sub register_script_function { 944sub register_script_function {
918 my ($fun, $cb) = @_; 945 my ($fun, $cb) = @_;
919 946
920 no strict 'refs'; 947 no strict 'refs';
921 *{"safe::$fun"} = $safe_hole->wrap ($cb); 948 *{"safe::$fun"} = $safe_hole->wrap ($cb);
922} 949}
923 950
951=back
952
953=cut
954
955#############################################################################
956
957=head2 EXTENSION DATABASE SUPPORT
958
959Crossfire maintains a very simple database for extension use. It can
960currently store anything that can be serialised using Storable, which
961excludes objects.
962
963The parameter C<$family> should best start with the name of the extension
964using it, it should be unique.
965
966=over 4
967
968=item $hashref = cf::db_get $family
969
970Return a hashref for use by the extension C<$family>, which can be
971modified. After modifications, you have to call C<cf::db_dirty> or
972C<cf::db_sync>.
973
974=item $value = cf::db_get $family => $key
975
976Returns a single value from the database
977
978=item cf::db_put $family => $hashref
979
980Stores the given family hashref into the database. Updates are delayed, if
981you want the data to be synced to disk immediately, use C<cf::db_sync>.
982
983=item cf::db_put $family => $key => $value
984
985Stores the given C<$value> in the family hash. Updates are delayed, if you
986want the data to be synced to disk immediately, use C<cf::db_sync>.
987
988=item cf::db_dirty
989
990Marks the database as dirty, to be updated at a later time.
991
992=item cf::db_sync
993
994Immediately write the database to disk I<if it is dirty>.
995
996=cut
997
998our $DB;
999
1000{
1001 my $path = cf::localdir . "/database.pst";
1002
1003 sub db_load() {
1004 warn "loading database $path\n";#d# remove later
1005 $DB = stat $path ? Storable::retrieve $path : { };
1006 }
1007
1008 my $pid;
1009
1010 sub db_save() {
1011 warn "saving database $path\n";#d# remove later
1012 waitpid $pid, 0 if $pid;
1013 if (0 == ($pid = fork)) {
1014 $DB->{_meta}{version} = 1;
1015 Storable::nstore $DB, "$path~";
1016 rename "$path~", $path;
1017 cf::_exit 0 if defined $pid;
1018 }
1019 }
1020
1021 my $dirty;
1022
1023 sub db_sync() {
1024 db_save if $dirty;
1025 undef $dirty;
1026 }
1027
1028 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub {
1029 db_sync;
1030 });
1031
1032 sub db_dirty() {
1033 $dirty = 1;
1034 $idle->start;
1035 }
1036
1037 sub db_get($;$) {
1038 @_ >= 2
1039 ? $DB->{$_[0]}{$_[1]}
1040 : ($DB->{$_[0]} ||= { })
1041 }
1042
1043 sub db_put($$;$) {
1044 if (@_ >= 3) {
1045 $DB->{$_[0]}{$_[1]} = $_[2];
1046 } else {
1047 $DB->{$_[0]} = $_[1];
1048 }
1049 db_dirty;
1050 }
1051
1052 attach_global
1053 prio => 10000,
1054 on_cleanup => sub {
1055 db_sync;
1056 },
1057 ;
1058}
1059
924############################################################################# 1060#############################################################################
925# the server's main() 1061# the server's main()
926 1062
1063sub cfg_load {
1064 open my $fh, "<:utf8", cf::confdir . "/config"
1065 or return;
1066
1067 local $/;
1068 *CFG = YAML::Syck::Load <$fh>;
1069}
1070
927sub main { 1071sub main {
1072 cfg_load;
1073 db_load;
1074 load_extensions;
928 Event::loop; 1075 Event::loop;
929} 1076}
930 1077
931############################################################################# 1078#############################################################################
932# initialisation 1079# initialisation
933 1080
1081sub _perl_reload(&) {
1082 my ($msg) = @_;
1083
1084 $msg->("reloading...");
1085
1086 eval {
1087 # cancel all watchers
1088 $_->cancel for Event::all_watchers;
1089
1090 # unload all extensions
1091 for (@exts) {
1092 $msg->("unloading <$_>");
1093 unload_extension $_;
1094 }
1095
1096 # unload all modules loaded from $LIBDIR
1097 while (my ($k, $v) = each %INC) {
1098 next unless $v =~ /^\Q$LIBDIR\E\/.*\.pm$/;
1099
1100 $msg->("removing <$k>");
1101 delete $INC{$k};
1102
1103 $k =~ s/\.pm$//;
1104 $k =~ s/\//::/g;
1105
1106 if (my $cb = $k->can ("unload_module")) {
1107 $cb->();
1108 }
1109
1110 Symbol::delete_package $k;
1111 }
1112
1113 # sync database to disk
1114 cf::db_sync;
1115
1116 # get rid of safe::, as good as possible
1117 Symbol::delete_package "safe::$_"
1118 for qw(cf::object cf::object::player cf::player cf::map cf::party cf::region);
1119
1120 # remove register_script_function callbacks
1121 # TODO
1122
1123 # unload cf.pm "a bit"
1124 delete $INC{"cf.pm"};
1125
1126 # don't, removes xs symbols, too,
1127 # and global variables created in xs
1128 #Symbol::delete_package __PACKAGE__;
1129
1130 # reload cf.pm
1131 $msg->("reloading cf.pm");
1132 require cf;
1133
1134 # load config and database again
1135 cf::cfg_load;
1136 cf::db_load;
1137
1138 # load extensions
1139 $msg->("load extensions");
1140 cf::load_extensions;
1141
1142 # reattach attachments to objects
1143 $msg->("reattach");
1144 _global_reattach;
1145 };
1146 $msg->($@) if $@;
1147
1148 $msg->("reloaded");
1149};
1150
1151sub perl_reload() {
1152 _perl_reload {
1153 warn $_[0];
1154 print "$_[0]\n";
1155 };
1156}
1157
1158register_command "perl-reload", 0, sub {
1159 my ($who, $arg) = @_;
1160
1161 if ($who->flag (FLAG_WIZ)) {
1162 _perl_reload {
1163 warn $_[0];
1164 $who->message ($_[0]);
1165 };
1166 }
1167};
1168
934register "<global>", __PACKAGE__; 1169register "<global>", __PACKAGE__;
935 1170
936unshift @INC, $LIBDIR; 1171unshift @INC, $LIBDIR;
937 1172
938load_extensions;
939
940$TICK_WATCHER = Event->timer ( 1173$TICK_WATCHER = Event->timer (
941 prio => 1, 1174 prio => 1,
1175 async => 1,
942 at => $NEXT_TICK || 1, 1176 at => $NEXT_TICK || 1,
943 cb => sub { 1177 cb => sub {
944 cf::server_tick; # one server iteration 1178 cf::server_tick; # one server iteration
945 1179
946 my $NOW = Event::time; 1180 my $NOW = Event::time;
947 $NEXT_TICK += $TICK; 1181 $NEXT_TICK += $TICK;
948 1182
949 # if we are delayed by four ticks, skip them all 1183 # if we are delayed by four ticks or more, skip them all
950 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4; 1184 $NEXT_TICK = $NOW if $NOW >= $NEXT_TICK + $TICK * 4;
951 1185
952 $TICK_WATCHER->at ($NEXT_TICK); 1186 $TICK_WATCHER->at ($NEXT_TICK);
953 $TICK_WATCHER->start; 1187 $TICK_WATCHER->start;
954 }, 1188 },
955); 1189);
956 1190
957_reload_2; 1191IO::AIO::max_poll_time $TICK * 0.2;
1192
1193Event->io (fd => IO::AIO::poll_fileno,
1194 poll => 'r',
1195 prio => 5,
1196 cb => \&IO::AIO::poll_cb);
958 1197
9591 11981
960 1199

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines