--- deliantra/server/lib/cf.pm 2007/07/21 18:01:26 1.312 +++ deliantra/server/lib/cf.pm 2007/07/23 21:02:50 1.316 @@ -324,6 +324,62 @@ $guard } +=item cf::get_slot $time[, $priority[, $name]] + +Allocate $time seconds of blocking CPU time at priority C<$priority>: +This call blocks and returns only when you have at least C<$time> seconds +of cpu time till the next tick. The slot is only valid till the next cede. + +The optional C<$name> can be used to identify the job to run. It might be +used for statistical purposes and should identify the same time-class. + +Useful for short background jobs. + +=cut + +our @SLOT_QUEUE; +our $SLOT_QUEUE; + +$SLOT_QUEUE->cancel if $SLOT_QUEUE; +$SLOT_QUEUE = Coro::async { + my $signal = new Coro::Signal; + + while () { + next_job: + my $avail = cf::till_tick; + if ($avail > 0.01) { + for (0 .. $#SLOT_QUEUE) { + if ($SLOT_QUEUE[$_][0] < $avail) { + my $job = splice @SLOT_QUEUE, $_, 1, (); + $job->[2]->send; + Coro::cede; + goto next_job; + } + } + } + + if (@SLOT_QUEUE) { + # we do not use wait_For_tick() as it returns immediately when tick is inactive + push @cf::WAIT_FOR_TICK, $signal; + $signal->wait; + } else { + Coro::schedule; + } + } +}; + +sub get_slot($;$$) { + my ($time, $pri, $name) = @_; + + $time = $TICK * .6 if $time > $TICK * .6; + my $sig = new Coro::Signal; + + push @SLOT_QUEUE, [$time, $pri, $sig, $name]; + @SLOT_QUEUE = sort { $b->[1] <=> $a->[1] } @SLOT_QUEUE; + $SLOT_QUEUE->ready; + $sig->wait; +} + =item cf::async { BLOCK } Currently the same as Coro::async_pool, meaning you cannot use @@ -1127,10 +1183,16 @@ my $msg = eval { $pl->ns->{json_coder}->decode ($buf) }; if (ref $msg) { - if (my $cb = $EXTCMD{$msg->{msgtype}}) { - if (my %reply = $cb->($pl, $msg)) { - $pl->ext_reply ($msg->{msgid}, %reply); - } + my ($type, $reply, @payload) = + "ARRAY" eq ref $msg + ? @$msg + : ($msg->{msgtype}, $msg->{msgid}, %$msg); # TODO: version 1, remove + + if (my $cb = $EXTCMD{$type}) { + my @reply = $cb->($pl, @payload); + + $pl->ext_reply ($reply, @reply) + if $reply; } } else { warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; @@ -1463,29 +1525,34 @@ $_[0]{hintmode} } -=item $player->ext_reply ($msgid, %msg) +=item $player->ext_reply ($msgid, @msg) Sends an ext reply to the player. =cut -sub ext_reply($$%) { - my ($self, $id, %msg) = @_; +sub ext_reply($$@) { + my ($self, $id, @msg) = @_; - $msg{msgid} = $id; - $self->send ("ext " . $self->ns->{json_coder}->encode (\%msg)); + if ($self->ns->extcmd == 2) { + $self->send ("ext " . $self->ns->{json_coder}->encode (["reply-$id", @msg])); + } elsif ($self->ns->extcmd == 1) { + #TODO: version 1, remove + unshift @msg, msgtype => "reply", msgid => $id; + $self->send ("ext " . $self->ns->{json_coder}->encode ({@msg})); + } } -=item $player->ext_event ($type, %msg) +=item $player->ext_msg ($type, @msg) Sends an ext event to the client. =cut -sub ext_event($$%) { - my ($self, $type, %msg) = @_; +sub ext_msg($$@) { + my ($self, $type, @msg) = @_; - $self->ns->ext_event ($type, %msg); + $self->ns->ext_msg ($type, @msg); } =head3 cf::region @@ -2165,13 +2232,8 @@ my $pl = $self->contr; if ($pl->{npc_dialog} && $pl->{npc_dialog}->{id}) { - my $diag = $pl->{npc_dialog}; - $diag->{pl}->ext_reply ( - $diag->{id}, - msgtype => "reply", - msg => $diag->{pl}->expand_cfpod ($msg), - add_topics => [] - ); + my $dialog = $pl->{npc_dialog}; + $dialog->{pl}->ext_msg ($dialog->{id}, update => msg => $dialog->{pl}->expand_cfpod ($msg)); } else { $msg = $npc->name . " says: $msg" if $npc; @@ -2452,20 +2514,20 @@ $msg = $self->pl->expand_cfpod ($msg); - return unless @extra || length $msg; - $color &= ~cf::NDI_UNIQUE; # just in case... if (ref $channel) { # send meta info to client, if not yet sent unless (exists $self->{channel}{$channel->{id}}) { $self->{channel}{$channel->{id}} = $channel; - $self->ext_event (channel_info => %$channel); + $self->ext_msg (channel_info => %$channel); } $channel = $channel->{id}; } + return unless @extra || length $msg; + if ($self->can_msg) { $self->send_packet ("msg " . $self->{json_coder}->encode ([$color, $channel, $msg, @extra])); } else { @@ -2490,19 +2552,23 @@ } } -=item $client->ext_event ($type, %msg) +=item $client->ext_msg ($type, @msg) Sends an ext event to the client. =cut -sub cf::client::ext_event($$%) { - my ($self, $type, %msg) = @_; +sub cf::client::ext_msg($$@) { + my ($self, $type, @msg) = @_; - return unless $self->extcmd; + my $extcmd = $self->extcmd; - $msg{msgtype} = "event_$type"; - $self->send_packet ("ext " . $self->{json_coder}->encode (\%msg)); + if ($extcmd == 2) { + $self->send_packet ("ext " . $self->{json_coder}->encode ([$type, @msg])); + } elsif ($extcmd == 1) { # TODO: remove + push @msg, msgtype => "event_$type"; + $self->send_packet ("ext " . $self->{json_coder}->encode ({@msg})); + } } =item $success = $client->query ($flags, "text", \&cb) @@ -2567,11 +2633,16 @@ my $msg = eval { $ns->{json_coder}->decode ($buf) }; if (ref $msg) { - if (my $cb = $EXTICMD{$msg->{msgtype}}) { - if (my %reply = $cb->($ns, $msg)) { - $reply{msgid} = $msg->{msgid}; - $ns->send ("ext " . $ns->{json_coder}->encode (\%reply)); - } + my ($type, $reply, @payload) = + "ARRAY" eq ref $msg + ? @$msg + : ($msg->{msgtype}, $msg->{msgid}, %$msg); # TODO: version 1, remove + + if (my $cb = $EXTICMD{$type}) { + my @reply = $cb->($ns, @payload); + + $ns->ext_reply ($reply, @reply) + if $reply; } } else { warn "client " . ($ns->pl ? $ns->pl->ob->name : $ns->host) . " sent unparseable exti message: <$buf>\n";