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.79 by root, Tue Nov 7 14:58:35 2006 UTC vs.
Revision 1.86 by root, Thu Dec 14 05:09:32 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
21our %COMMAND = ();
22our %COMMAND_TIME = ();
23our %EXTCMD = ();
24
21_init_vars; 25_init_vars;
22 26
23our %COMMAND = ();
24our @EVENT; 27our @EVENT;
25our $LIBDIR = maps_directory "perl"; 28our $LIBDIR = maps_directory "perl";
26 29
27our $TICK = MAX_TIME * 1e-6; 30our $TICK = MAX_TIME * 1e-6;
28our $TICK_WATCHER; 31our $TICK_WATCHER;
29our $NEXT_TICK; 32our $NEXT_TICK;
30 33
31our %CFG; 34our %CFG;
32 35
33our $uptime; 36our $UPTIME; $UPTIME ||= time;
34
35$uptime ||= time;
36 37
37############################################################################# 38#############################################################################
38 39
39=head2 GLOBAL VARIABLES 40=head2 GLOBAL VARIABLES
40 41
41=over 4 42=over 4
43
44=item $cf::UPTIME
45
46The timestamp of the server start (so not actually an uptime).
42 47
43=item $cf::LIBDIR 48=item $cf::LIBDIR
44 49
45The perl library directory, where extensions and cf-specific modules can 50The perl library directory, where extensions and cf-specific modules can
46be found. It will be added to C<@INC> automatically. 51be found. It will be added to C<@INC> automatically.
71 76
72@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 77@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
73 78
74# we bless all objects into (empty) derived classes to force a method lookup 79# we bless all objects into (empty) derived classes to force a method lookup
75# within the Safe compartment. 80# within the Safe compartment.
76for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) { 81for my $pkg (qw(
82 cf::object cf::object::player
83 cf::client_socket cf::player
84 cf::arch cf::living
85 cf::map cf::party cf::region
86)) {
77 no strict 'refs'; 87 no strict 'refs';
78 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; 88 @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg;
79} 89}
80 90
81$Event::DIED = sub { 91$Event::DIED = sub {
83}; 93};
84 94
85my %ext_pkg; 95my %ext_pkg;
86my @exts; 96my @exts;
87my @hook; 97my @hook;
88my %command;
89my %extcmd;
90 98
91=head2 UTILITY FUNCTIONS 99=head2 UTILITY FUNCTIONS
92 100
93=over 4 101=over 4
94 102
523 unlink $filename; 531 unlink $filename;
524 unlink "$filename.pst"; 532 unlink "$filename.pst";
525 } 533 }
526} 534}
527 535
536sub object_freezer_as_string {
537 my ($rdata, $objs) = @_;
538
539 use Data::Dumper;
540
541 $$rdata . Dumper $objs
542}
543
528sub object_thawer_load { 544sub object_thawer_load {
529 my ($filename) = @_; 545 my ($filename) = @_;
530 546
531 local $/; 547 local $/;
532 548
557 if exists $src->{_attachment}; 573 if exists $src->{_attachment};
558 }, 574 },
559; 575;
560 576
561############################################################################# 577#############################################################################
562# old plug-in events 578# command handling &c
563 579
564sub inject_event { 580=item cf::register_command $name => \&callback($ob,$args);
565 my $extension = shift;
566 my $event_code = shift;
567 581
568 my $cb = $hook[$event_code]{$extension} 582Register a callback for execution when the client sends the user command
569 or return; 583$name.
570 584
571 &$cb 585=cut
572}
573
574sub inject_global_event {
575 my $event = shift;
576
577 my $cb = $hook[$event]
578 or return;
579
580 List::Util::max map &$_, values %$cb
581}
582
583sub inject_command {
584 my ($name, $obj, $params) = @_;
585
586 for my $cmd (@{ $command{$name} }) {
587 $cmd->[1]->($obj, $params);
588 }
589
590 -1
591}
592 586
593sub register_command { 587sub register_command {
594 my ($name, $time, $cb) = @_; 588 my ($name, $cb) = @_;
595 589
596 my $caller = caller; 590 my $caller = caller;
597 #warn "registering command '$name/$time' to '$caller'"; 591 #warn "registering command '$name/$time' to '$caller'";
598 592
599 push @{ $command{$name} }, [$time, $cb, $caller]; 593 push @{ $COMMAND{$name} }, [$caller, $cb];
600 $COMMAND{"$name\000"} = List::Util::max map $_->[0], @{ $command{$name} };
601} 594}
595
596=item cf::register_extcmd $name => \&callback($pl,$packet);
597
598Register a callbackf ro execution when the client sends an extcmd packet.
599
600If the callback returns something, it is sent back as if reply was being
601called.
602
603=cut
602 604
603sub register_extcmd { 605sub register_extcmd {
604 my ($name, $cb) = @_; 606 my ($name, $cb) = @_;
605 607
606 my $caller = caller; 608 my $caller = caller;
607 #warn "registering extcmd '$name' to '$caller'"; 609 #warn "registering extcmd '$name' to '$caller'";
608 610
609 $extcmd{$name} = [$cb, $caller]; 611 $EXTCMD{$name} = [$cb, $caller];
610} 612}
613
614attach_to_players
615 on_command => sub {
616 my ($pl, $name, $params) = @_;
617
618 my $cb = $COMMAND{$name}
619 or return;
620
621 for my $cmd (@$cb) {
622 $cmd->[1]->($pl->ob, $params);
623 }
624
625 cf::override;
626 },
627 on_extcmd => sub {
628 my ($pl, $buf) = @_;
629
630 my $msg = eval { from_json $buf };
631
632 if (ref $msg) {
633 if (my $cb = $EXTCMD{$msg->{msgtype}}) {
634 if (my %reply = $cb->[0]->($pl, $msg)) {
635 $pl->ext_reply ($msg->{msgid}, %reply);
636 }
637 }
638 } else {
639 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
640 }
641
642 cf::override;
643 },
644;
611 645
612sub register { 646sub register {
613 my ($base, $pkg) = @_; 647 my ($base, $pkg) = @_;
614 648
615 #TODO 649 #TODO
634 . "#line 1 \"$path\"\n{\n" 668 . "#line 1 \"$path\"\n{\n"
635 . (do { local $/; <$fh> }) 669 . (do { local $/; <$fh> })
636 . "\n};\n1"; 670 . "\n};\n1";
637 671
638 eval $source 672 eval $source
639 or die "$path: $@"; 673 or die $@ ? "$path: $@\n"
674 : "extension disabled.\n";
640 675
641 push @exts, $pkg; 676 push @exts, $pkg;
642 $ext_pkg{$base} = $pkg; 677 $ext_pkg{$base} = $pkg;
643 678
644# no strict 'refs'; 679# no strict 'refs';
657# for my $idx (0 .. $#PLUGIN_EVENT) { 692# for my $idx (0 .. $#PLUGIN_EVENT) {
658# delete $hook[$idx]{$pkg}; 693# delete $hook[$idx]{$pkg};
659# } 694# }
660 695
661 # remove commands 696 # remove commands
662 for my $name (keys %command) { 697 for my $name (keys %COMMAND) {
663 my @cb = grep $_->[2] ne $pkg, @{ $command{$name} }; 698 my @cb = grep $_->[0] ne $pkg, @{ $COMMAND{$name} };
664 699
665 if (@cb) { 700 if (@cb) {
666 $command{$name} = \@cb; 701 $COMMAND{$name} = \@cb;
667 $COMMAND{"$name\000"} = List::Util::max map $_->[0], @cb;
668 } else { 702 } else {
669 delete $command{$name};
670 delete $COMMAND{"$name\000"}; 703 delete $COMMAND{$name};
671 } 704 }
672 } 705 }
673 706
674 # remove extcmds 707 # remove extcmds
675 for my $name (grep $extcmd{$_}[1] eq $pkg, keys %extcmd) { 708 for my $name (grep $EXTCMD{$_}[1] eq $pkg, keys %EXTCMD) {
676 delete $extcmd{$name}; 709 delete $EXTCMD{$name};
677 } 710 }
678 711
679 if (my $cb = $pkg->can ("unload")) { 712 if (my $cb = $pkg->can ("unload")) {
680 eval { 713 eval {
681 $cb->($pkg); 714 $cb->($pkg);
695 load_extension $ext; 728 load_extension $ext;
696 1 729 1
697 } or warn "$ext not loaded: $@"; 730 } or warn "$ext not loaded: $@";
698 } 731 }
699} 732}
700
701#############################################################################
702# extcmd framework, basically convert ext <msg>
703# into pkg::->on_extcmd_arg1 (...) while shortcutting a few
704
705attach_to_players
706 on_extcmd => sub {
707 my ($pl, $buf) = @_;
708
709 my $msg = eval { from_json $buf };
710
711 if (ref $msg) {
712 if (my $cb = $extcmd{$msg->{msgtype}}) {
713 if (my %reply = $cb->[0]->($pl, $msg)) {
714 $pl->ext_reply ($msg->{msgid}, %reply);
715 }
716 }
717 } else {
718 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
719 }
720
721 cf::override;
722 },
723;
724 733
725############################################################################# 734#############################################################################
726# load/save/clean perl data associated with a map 735# load/save/clean perl data associated with a map
727 736
728*cf::mapsupport::on_clean = sub { 737*cf::mapsupport::on_clean = sub {
1144 warn $_[0]; 1153 warn $_[0];
1145 print "$_[0]\n"; 1154 print "$_[0]\n";
1146 }; 1155 };
1147} 1156}
1148 1157
1158register "<global>", __PACKAGE__;
1159
1149register_command "perl-reload", 0, sub { 1160register_command "perl-reload" => sub {
1150 my ($who, $arg) = @_; 1161 my ($who, $arg) = @_;
1151 1162
1152 if ($who->flag (FLAG_WIZ)) { 1163 if ($who->flag (FLAG_WIZ)) {
1153 _perl_reload { 1164 _perl_reload {
1154 warn $_[0]; 1165 warn $_[0];
1155 $who->message ($_[0]); 1166 $who->message ($_[0]);
1156 }; 1167 };
1157 } 1168 }
1158}; 1169};
1159
1160register "<global>", __PACKAGE__;
1161 1170
1162unshift @INC, $LIBDIR; 1171unshift @INC, $LIBDIR;
1163 1172
1164$TICK_WATCHER = Event->timer ( 1173$TICK_WATCHER = Event->timer (
1165 prio => 1, 1174 prio => 1,
1177 $TICK_WATCHER->at ($NEXT_TICK); 1186 $TICK_WATCHER->at ($NEXT_TICK);
1178 $TICK_WATCHER->start; 1187 $TICK_WATCHER->start;
1179 }, 1188 },
1180); 1189);
1181 1190
1182eval { IO::AIO::max_poll_time $TICK * 0.2 }; #d# remove eval after restart 1191IO::AIO::max_poll_time $TICK * 0.2;
1183 1192
1184Event->io (fd => IO::AIO::poll_fileno, 1193Event->io (fd => IO::AIO::poll_fileno,
1185 poll => 'r', 1194 poll => 'r',
1186 prio => 5, 1195 prio => 5,
1187 cb => \&IO::AIO::poll_cb); 1196 cb => \&IO::AIO::poll_cb);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines