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.84 by root, Mon Dec 11 02:54:57 2006 UTC vs.
Revision 1.87 by root, Thu Dec 14 22:45:40 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
23our %COMMAND = ();
24our %COMMAND_TIME = ();
25our %EXTCMD = ();
26
21_init_vars; 27_init_vars;
22 28
23our %COMMAND = ();
24our @EVENT; 29our @EVENT;
25our $LIBDIR = maps_directory "perl"; 30our $LIBDIR = maps_directory "perl";
26 31
27our $TICK = MAX_TIME * 1e-6; 32our $TICK = MAX_TIME * 1e-6;
28our $TICK_WATCHER; 33our $TICK_WATCHER;
73 78
74@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 79@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
75 80
76# we bless all objects into (empty) derived classes to force a method lookup 81# we bless all objects into (empty) derived classes to force a method lookup
77# within the Safe compartment. 82# within the Safe compartment.
78for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) { 83for my $pkg (qw(
84 cf::object cf::object::player
85 cf::client_socket cf::player
86 cf::arch cf::living
87 cf::map cf::party cf::region
88)) {
79 no strict 'refs'; 89 no strict 'refs';
80 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; 90 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
81} 91}
82 92
83$Event::DIED = sub { 93$Event::DIED = sub {
85}; 95};
86 96
87my %ext_pkg; 97my %ext_pkg;
88my @exts; 98my @exts;
89my @hook; 99my @hook;
90my %command;
91my %extcmd;
92 100
93=head2 UTILITY FUNCTIONS 101=head2 UTILITY FUNCTIONS
94 102
95=over 4 103=over 4
96 104
567 if exists $src->{_attachment}; 575 if exists $src->{_attachment};
568 }, 576 },
569; 577;
570 578
571############################################################################# 579#############################################################################
572# old plug-in events 580# command handling &c
573 581
574sub inject_event { 582=item cf::register_command $name => \&callback($ob,$args);
575 my $extension = shift;
576 my $event_code = shift;
577 583
578 my $cb = $hook[$event_code]{$extension} 584Register a callback for execution when the client sends the user command
579 or return; 585$name.
580 586
581 &$cb 587=cut
582}
583
584sub inject_global_event {
585 my $event = shift;
586
587 my $cb = $hook[$event]
588 or return;
589
590 List::Util::max map &$_, values %$cb
591}
592
593sub inject_command {
594 my ($name, $obj, $params) = @_;
595
596 for my $cmd (@{ $command{$name} }) {
597 $cmd->[1]->($obj, $params);
598 }
599
600 -1
601}
602 588
603sub register_command { 589sub register_command {
604 my ($name, $time, $cb) = @_; 590 my ($name, $cb) = @_;
605 591
606 my $caller = caller; 592 my $caller = caller;
607 #warn "registering command '$name/$time' to '$caller'"; 593 #warn "registering command '$name/$time' to '$caller'";
608 594
609 push @{ $command{$name} }, [$time, $cb, $caller]; 595 push @{ $COMMAND{$name} }, [$caller, $cb];
610 $COMMAND{"$name\000"} = List::Util::max map $_->[0], @{ $command{$name} };
611} 596}
597
598=item cf::register_extcmd $name => \&callback($pl,$packet);
599
600Register a callbackf ro execution when the client sends an extcmd packet.
601
602If the callback returns something, it is sent back as if reply was being
603called.
604
605=cut
612 606
613sub register_extcmd { 607sub register_extcmd {
614 my ($name, $cb) = @_; 608 my ($name, $cb) = @_;
615 609
616 my $caller = caller; 610 my $caller = caller;
617 #warn "registering extcmd '$name' to '$caller'"; 611 #warn "registering extcmd '$name' to '$caller'";
618 612
619 $extcmd{$name} = [$cb, $caller]; 613 $EXTCMD{$name} = [$cb, $caller];
620} 614}
615
616attach_to_players
617 on_command => sub {
618 my ($pl, $name, $params) = @_;
619
620 my $cb = $COMMAND{$name}
621 or return;
622
623 for my $cmd (@$cb) {
624 $cmd->[1]->($pl->ob, $params);
625 }
626
627 cf::override;
628 },
629 on_extcmd => sub {
630 my ($pl, $buf) = @_;
631
632 my $msg = eval { from_json $buf };
633
634 if (ref $msg) {
635 if (my $cb = $EXTCMD{$msg->{msgtype}}) {
636 if (my %reply = $cb->[0]->($pl, $msg)) {
637 $pl->ext_reply ($msg->{msgid}, %reply);
638 }
639 }
640 } else {
641 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
642 }
643
644 cf::override;
645 },
646;
621 647
622sub register { 648sub register {
623 my ($base, $pkg) = @_; 649 my ($base, $pkg) = @_;
624 650
625 #TODO 651 #TODO
668# for my $idx (0 .. $#PLUGIN_EVENT) { 694# for my $idx (0 .. $#PLUGIN_EVENT) {
669# delete $hook[$idx]{$pkg}; 695# delete $hook[$idx]{$pkg};
670# } 696# }
671 697
672 # remove commands 698 # remove commands
673 for my $name (keys %command) { 699 for my $name (keys %COMMAND) {
674 my @cb = grep $_->[2] ne $pkg, @{ $command{$name} }; 700 my @cb = grep $_->[0] ne $pkg, @{ $COMMAND{$name} };
675 701
676 if (@cb) { 702 if (@cb) {
677 $command{$name} = \@cb; 703 $COMMAND{$name} = \@cb;
678 $COMMAND{"$name\000"} = List::Util::max map $_->[0], @cb;
679 } else { 704 } else {
680 delete $command{$name};
681 delete $COMMAND{"$name\000"}; 705 delete $COMMAND{$name};
682 } 706 }
683 } 707 }
684 708
685 # remove extcmds 709 # remove extcmds
686 for my $name (grep $extcmd{$_}[1] eq $pkg, keys %extcmd) { 710 for my $name (grep $EXTCMD{$_}[1] eq $pkg, keys %EXTCMD) {
687 delete $extcmd{$name}; 711 delete $EXTCMD{$name};
688 } 712 }
689 713
690 if (my $cb = $pkg->can ("unload")) { 714 if (my $cb = $pkg->can ("unload")) {
691 eval { 715 eval {
692 $cb->($pkg); 716 $cb->($pkg);
706 load_extension $ext; 730 load_extension $ext;
707 1 731 1
708 } or warn "$ext not loaded: $@"; 732 } or warn "$ext not loaded: $@";
709 } 733 }
710} 734}
711
712#############################################################################
713# extcmd framework, basically convert ext <msg>
714# into pkg::->on_extcmd_arg1 (...) while shortcutting a few
715
716attach_to_players
717 on_extcmd => sub {
718 my ($pl, $buf) = @_;
719
720 my $msg = eval { from_json $buf };
721
722 if (ref $msg) {
723 if (my $cb = $extcmd{$msg->{msgtype}}) {
724 if (my %reply = $cb->[0]->($pl, $msg)) {
725 $pl->ext_reply ($msg->{msgid}, %reply);
726 }
727 }
728 } else {
729 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
730 }
731
732 cf::override;
733 },
734;
735 735
736############################################################################# 736#############################################################################
737# load/save/clean perl data associated with a map 737# load/save/clean perl data associated with a map
738 738
739*cf::mapsupport::on_clean = sub { 739*cf::mapsupport::on_clean = sub {
1025 sub db_sync() { 1025 sub db_sync() {
1026 db_save if $dirty; 1026 db_save if $dirty;
1027 undef $dirty; 1027 undef $dirty;
1028 } 1028 }
1029 1029
1030 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub { 1030 my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, data => WF_AUTOCANCEL, cb => sub {
1031 db_sync; 1031 db_sync;
1032 }); 1032 });
1033 1033
1034 sub db_dirty() { 1034 sub db_dirty() {
1035 $dirty = 1; 1035 $dirty = 1;
1085 1085
1086 $msg->("reloading..."); 1086 $msg->("reloading...");
1087 1087
1088 eval { 1088 eval {
1089 # cancel all watchers 1089 # cancel all watchers
1090 $_->cancel for Event::all_watchers; 1090 for (Event::all_watchers) {
1091 $_->cancel if $_->data & WF_AUTOCANCEL;
1092 }
1091 1093
1092 # unload all extensions 1094 # unload all extensions
1093 for (@exts) { 1095 for (@exts) {
1094 $msg->("unloading <$_>"); 1096 $msg->("unloading <$_>");
1095 unload_extension $_; 1097 unload_extension $_;
1155 warn $_[0]; 1157 warn $_[0];
1156 print "$_[0]\n"; 1158 print "$_[0]\n";
1157 }; 1159 };
1158} 1160}
1159 1161
1162register "<global>", __PACKAGE__;
1163
1160register_command "perl-reload", 0, sub { 1164register_command "perl-reload" => sub {
1161 my ($who, $arg) = @_; 1165 my ($who, $arg) = @_;
1162 1166
1163 if ($who->flag (FLAG_WIZ)) { 1167 if ($who->flag (FLAG_WIZ)) {
1164 _perl_reload { 1168 _perl_reload {
1165 warn $_[0]; 1169 warn $_[0];
1166 $who->message ($_[0]); 1170 $who->message ($_[0]);
1167 }; 1171 };
1168 } 1172 }
1169}; 1173};
1170 1174
1171register "<global>", __PACKAGE__;
1172
1173unshift @INC, $LIBDIR; 1175unshift @INC, $LIBDIR;
1174 1176
1175$TICK_WATCHER = Event->timer ( 1177$TICK_WATCHER = Event->timer (
1176 prio => 1, 1178 prio => 1,
1177 async => 1, 1179 async => 1,
1178 at => $NEXT_TICK || 1, 1180 at => $NEXT_TICK || 1,
1181 data => WF_AUTOCANCEL,
1179 cb => sub { 1182 cb => sub {
1180 cf::server_tick; # one server iteration 1183 cf::server_tick; # one server iteration
1181 1184
1182 my $NOW = Event::time; 1185 my $NOW = Event::time;
1183 $NEXT_TICK += $TICK; 1186 $NEXT_TICK += $TICK;
1193IO::AIO::max_poll_time $TICK * 0.2; 1196IO::AIO::max_poll_time $TICK * 0.2;
1194 1197
1195Event->io (fd => IO::AIO::poll_fileno, 1198Event->io (fd => IO::AIO::poll_fileno,
1196 poll => 'r', 1199 poll => 'r',
1197 prio => 5, 1200 prio => 5,
1201 data => WF_AUTOCANCEL,
1198 cb => \&IO::AIO::poll_cb); 1202 cb => \&IO::AIO::poll_cb);
1199 1203
12001 12041
1201 1205

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines