--- deliantra/server/lib/cf.pm 2006/11/07 17:38:22 1.81 +++ deliantra/server/lib/cf.pm 2006/12/14 22:45:40 1.87 @@ -18,9 +18,14 @@ 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"; @@ -30,9 +35,7 @@ our %CFG; -our $uptime; - -$uptime ||= time; +our $UPTIME; $UPTIME ||= time; ############################################################################# @@ -40,6 +43,10 @@ =over 4 +=item $cf::UPTIME + +The timestamp of the server start (so not actually an uptime). + =item $cf::LIBDIR The perl library directory, where extensions and cf-specific modules can @@ -73,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_socket cf::player + cf::arch cf::living + cf::map cf::party cf::region +)) { no strict 'refs'; @{"safe::$pkg\::wrap::ISA"} = @{"$pkg\::wrap::ISA"} = $pkg; } @@ -85,8 +97,6 @@ my %ext_pkg; my @exts; my @hook; -my %command; -my %extcmd; =head2 UTILITY FUNCTIONS @@ -567,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); - } +Register a callbackf ro execution when the client sends an extcmd packet. - -1 -} - -sub register_command { - my ($name, $time, $cb) = @_; +If the callback returns something, it is sent back as if reply was being +called. - my $caller = caller; - #warn "registering command '$name/$time' to '$caller'"; - - push @{ $command{$name} }, [$time, $cb, $caller]; - $COMMAND{"$name\000"} = List::Util::max map $_->[0], @{ $command{$name} }; -} +=cut sub register_extcmd { my ($name, $cb) = @_; @@ -614,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) = @_; @@ -644,7 +672,8 @@ . "\n};\n1"; eval $source - or die "$path: $@"; + or die $@ ? "$path: $@\n" + : "extension disabled.\n"; push @exts, $pkg; $ext_pkg{$base} = $pkg; @@ -667,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")) { @@ -707,30 +734,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 { @@ -1024,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; }); @@ -1084,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) { @@ -1154,7 +1159,9 @@ }; } -register_command "perl-reload", 0, sub { +register "", __PACKAGE__; + +register_command "perl-reload" => sub { my ($who, $arg) = @_; if ($who->flag (FLAG_WIZ)) { @@ -1165,14 +1172,13 @@ } }; -register "", __PACKAGE__; - unshift @INC, $LIBDIR; $TICK_WATCHER = Event->timer ( prio => 1, async => 1, at => $NEXT_TICK || 1, + data => WF_AUTOCANCEL, cb => sub { cf::server_tick; # one server iteration @@ -1192,6 +1198,7 @@ Event->io (fd => IO::AIO::poll_fileno, poll => 'r', prio => 5, + data => WF_AUTOCANCEL, cb => \&IO::AIO::poll_cb); 1