--- deliantra/server/lib/cf.pm 2006/12/11 01:30:41 1.83 +++ deliantra/server/lib/cf.pm 2006/12/17 22:03:44 1.91 @@ -18,11 +18,16 @@ use strict; +sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload + +our %COMMAND = (); +our %COMMAND_TIME = (); +our %EXTCMD = (); + _init_vars; -our %COMMAND = (); our @EVENT; -our $LIBDIR = maps_directory "perl"; +our $LIBDIR = datadir . "/ext"; our $TICK = MAX_TIME * 1e-6; our $TICK_WATCHER; @@ -30,10 +35,7 @@ our %CFG; -our $uptime;#d# -our $UPTIME; -$UPTIME ||= $uptime;#d# -$UPTIME ||= time; +our $UPTIME; $UPTIME ||= time; ############################################################################# @@ -78,7 +80,12 @@ # we bless all objects into (empty) derived classes to force a method lookup # within the Safe compartment. -for my $pkg (qw(cf::object cf::object::player cf::player cf::map cf::party cf::region cf::arch cf::living)) { +for my $pkg (qw( + cf::object cf::object::player + cf::client cf::player + cf::arch cf::living + cf::map cf::party cf::region +)) { no strict 'refs'; @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; } @@ -90,8 +97,6 @@ my %ext_pkg; my @exts; my @hook; -my %command; -my %extcmd; =head2 UTILITY FUNCTIONS @@ -572,46 +577,32 @@ ; ############################################################################# -# old plug-in events +# command handling &c -sub inject_event { - my $extension = shift; - my $event_code = shift; +=item cf::register_command $name => \&callback($ob,$args); - my $cb = $hook[$event_code]{$extension} - or return; +Register a callback for execution when the client sends the user command +$name. - &$cb -} +=cut -sub inject_global_event { - my $event = shift; +sub register_command { + my ($name, $cb) = @_; - my $cb = $hook[$event] - or return; + my $caller = caller; + #warn "registering command '$name/$time' to '$caller'"; - List::Util::max map &$_, values %$cb + push @{ $COMMAND{$name} }, [$caller, $cb]; } -sub inject_command { - my ($name, $obj, $params) = @_; +=item cf::register_extcmd $name => \&callback($pl,$packet); - for my $cmd (@{ $command{$name} }) { - $cmd->[1]->($obj, $params); - } - - -1 -} +Register a callbackf ro execution when the client sends an extcmd packet. -sub register_command { - my ($name, $time, $cb) = @_; - - my $caller = caller; - #warn "registering command '$name/$time' to '$caller'"; +If the callback returns something, it is sent back as if reply was being +called. - push @{ $command{$name} }, [$time, $cb, $caller]; - $COMMAND{"$name\000"} = List::Util::max map $_->[0], @{ $command{$name} }; -} +=cut sub register_extcmd { my ($name, $cb) = @_; @@ -619,9 +610,41 @@ my $caller = caller; #warn "registering extcmd '$name' to '$caller'"; - $extcmd{$name} = [$cb, $caller]; + $EXTCMD{$name} = [$cb, $caller]; } +attach_to_players + on_command => sub { + my ($pl, $name, $params) = @_; + + my $cb = $COMMAND{$name} + or return; + + for my $cmd (@$cb) { + $cmd->[1]->($pl->ob, $params); + } + + cf::override; + }, + on_extcmd => sub { + my ($pl, $buf) = @_; + + my $msg = eval { from_json $buf }; + + if (ref $msg) { + if (my $cb = $EXTCMD{$msg->{msgtype}}) { + if (my %reply = $cb->[0]->($pl, $msg)) { + $pl->ext_reply ($msg->{msgid}, %reply); + } + } + } else { + warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; + } + + cf::override; + }, +; + sub register { my ($base, $pkg) = @_; @@ -673,21 +696,19 @@ # } # remove commands - for my $name (keys %command) { - my @cb = grep $_->[2] ne $pkg, @{ $command{$name} }; + for my $name (keys %COMMAND) { + my @cb = grep $_->[0] ne $pkg, @{ $COMMAND{$name} }; if (@cb) { - $command{$name} = \@cb; - $COMMAND{"$name\000"} = List::Util::max map $_->[0], @cb; + $COMMAND{$name} = \@cb; } else { - delete $command{$name}; - delete $COMMAND{"$name\000"}; + delete $COMMAND{$name}; } } # remove extcmds - for my $name (grep $extcmd{$_}[1] eq $pkg, keys %extcmd) { - delete $extcmd{$name}; + for my $name (grep $EXTCMD{$_}[1] eq $pkg, keys %EXTCMD) { + delete $EXTCMD{$name}; } if (my $cb = $pkg->can ("unload")) { @@ -701,8 +722,6 @@ } sub load_extensions { - my $LIBDIR = maps_directory "perl"; - for my $ext (<$LIBDIR/*.ext>) { next unless -r $ext; eval { @@ -713,30 +732,6 @@ } ############################################################################# -# extcmd framework, basically convert ext -# into pkg::->on_extcmd_arg1 (...) while shortcutting a few - -attach_to_players - on_extcmd => sub { - my ($pl, $buf) = @_; - - my $msg = eval { from_json $buf }; - - if (ref $msg) { - if (my $cb = $extcmd{$msg->{msgtype}}) { - if (my %reply = $cb->[0]->($pl, $msg)) { - $pl->ext_reply ($msg->{msgid}, %reply); - } - } - } else { - warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; - } - - cf::override; - }, -; - -############################################################################# # load/save/clean perl data associated with a map *cf::mapsupport::on_clean = sub { @@ -871,16 +866,18 @@ The following fucntions and emthods are available within a safe environment: - cf::object contr pay_amount pay_player + cf::object contr pay_amount pay_player map cf::object::player player cf::player peaceful + cf::map trigger =cut for ( - ["cf::object" => qw(contr pay_amount pay_player)], + ["cf::object" => qw(contr pay_amount pay_player map)], ["cf::object::player" => qw(player)], ["cf::player" => qw(peaceful)], + ["cf::map" => qw(trigger)], ) { no strict 'refs'; my ($pkg, @funs) = @$_; @@ -1030,7 +1027,7 @@ undef $dirty; } - my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, cb => sub { + my $idle = Event->idle (min => $TICK * 2.8, max => 10, repeat => 0, data => WF_AUTOCANCEL, cb => sub { db_sync; }); @@ -1090,7 +1087,9 @@ eval { # cancel all watchers - $_->cancel for Event::all_watchers; + for (Event::all_watchers) { + $_->cancel if $_->data & WF_AUTOCANCEL; + } # unload all extensions for (@exts) { @@ -1160,7 +1159,9 @@ }; } -register_command "perl-reload", 0, sub { +register "", __PACKAGE__; + +register_command "perl-reload" => sub { my ($who, $arg) = @_; if ($who->flag (FLAG_WIZ)) { @@ -1171,14 +1172,12 @@ } }; -register "", __PACKAGE__; - unshift @INC, $LIBDIR; $TICK_WATCHER = Event->timer ( - prio => 1, - async => 1, + prio => 0, at => $NEXT_TICK || 1, + data => WF_AUTOCANCEL, cb => sub { cf::server_tick; # one server iteration @@ -1198,6 +1197,7 @@ Event->io (fd => IO::AIO::poll_fileno, poll => 'r', prio => 5, + data => WF_AUTOCANCEL, cb => \&IO::AIO::poll_cb); 1