--- deliantra/server/lib/cf.pm 2007/07/26 21:44:43 1.321 +++ deliantra/server/lib/cf.pm 2007/08/18 17:33:53 1.332 @@ -12,7 +12,7 @@ use Safe; use Safe::Hole; -use Coro 3.61 (); +use Coro 3.64 (); use Coro::State; use Coro::Handle; use Coro::Event; @@ -21,6 +21,7 @@ use Coro::Semaphore; use Coro::AIO; use Coro::Storable; +use Coro::Util (); use JSON::XS 1.4 (); use BDB (); @@ -474,57 +475,19 @@ =cut -sub _store_scalar { - open my $fh, ">", \my $buf - or die "fork_call: cannot open fh-to-buf in child : $!"; - Storable::store_fd $_[0], $fh; - close $fh; - - $buf -} - sub fork_call(&@) { my ($cb, @args) = @_; -# socketpair my $fh1, my $fh2, Socket::AF_UNIX, Socket::SOCK_STREAM, Socket::PF_UNSPEC -# or die "socketpair: $!"; - pipe my $fh1, my $fh2 - or die "pipe: $!"; - - if (my $pid = fork) { - close $fh2; - - my $res = (Coro::Handle::unblock $fh1)->readline (undef); - warn "pst<$res>" unless $res =~ /^pst/; - $res = Coro::Storable::thaw $res; + # we seemingly have to make a local copy of the whole thing, + # otherwise perl prematurely frees the stuff :/ + # TODO: investigate and fix (liekly this will be rather laborious) - waitpid $pid, 0; # should not block anymore, we expect the child to simply behave - - Carp::confess $$res unless "ARRAY" eq ref $res; - - return wantarray ? @$res : $res->[-1]; - } else { + my @res = Coro::Util::fork_eval { reset_signals; - local $SIG{__WARN__}; - local $SIG{__DIE__}; - # just in case, this hack effectively disables event - # in the child. cleaner and slower would be canceling all watchers, - # but this works for the time being. - local $Coro::idle; - $Coro::current->prio (Coro::PRIO_MAX); + &$cb + }, @args; - eval { - close $fh1; - - my @res = eval { $cb->(@args) }; - - syswrite $fh2, _store_scalar $@ ? \"$@" : \@res; - close $fh2; - }; - - warn $@ if $@; - _exit 0; - } + wantarray ? @res : $res[-1] } =item $value = cf::db_get $family => $key @@ -1374,6 +1337,16 @@ $self } +=item $player->send_msg ($channel, $msg, $color, [extra...]) + +=cut + +sub send_msg { + my $ns = shift->ns + or return; + $ns->send_msg (@_); +} + =item $pl->quit_character Nukes the player without looking back. If logged in, the connection will @@ -1923,6 +1896,9 @@ $self->activate; } + $self->{last_save} = $cf::RUNTIME; + $self->last_access ($cf::RUNTIME); + $self->in_memory (cf::MAP_IN_MEMORY); } @@ -2242,6 +2218,16 @@ } } +=item $object->send_msg ($channel, $msg, $color, [extra...]) + +=cut + +sub cf::object::send_msg { + my $pl = shift->contr + or return; + $pl->send_msg (@_); +} + =item $player_object->may ("access") Returns wether the given player is authorized to access resource "access" @@ -2514,7 +2500,7 @@ $msg = $self->pl->expand_cfpod ($msg); - $color &= ~cf::NDI_UNIQUE; # just in case... + $color &= cf::NDI_CLIENT_MASK; # just in case... if (ref $channel) { # send meta info to client, if not yet sent @@ -2529,21 +2515,31 @@ return unless @extra || length $msg; if ($self->can_msg) { - $self->send_packet ("msg " . $self->{json_coder}->encode ([$color, $channel, $msg, @extra])); - } else { - # replace some tags by gcfclient-compatible ones - for ($msg) { - 1 while - s/([^<]*)<\/b>/[b]${1}[\/b]/ - || s/([^<]*)<\/i>/[i]${1}[\/i]/ - || s/([^<]*)<\/u>/[ul]${1}[\/ul]/ - || s/([^<]*)<\/tt>/[fixed]${1}[\/fixed]/ - || s/([^<]*)<\/fg>/[color=$1]${2}[\/color]/; - } + # default colour, mask it out + $color &= ~(cf::NDI_COLOR_MASK | cf::NDI_DEF) + if $color & cf::NDI_DEF; + $self->send_packet ("msg " . $self->{json_coder}->encode ( + [$color & cf::NDI_CLIENT_MASK, $channel, $msg, @extra])); + } else { if ($color >= 0) { + # replace some tags by gcfclient-compatible ones + for ($msg) { + 1 while + s/([^<]*)<\/b>/[b]${1}[\/b]/ + || s/([^<]*)<\/i>/[i]${1}[\/i]/ + || s/([^<]*)<\/u>/[ul]${1}[\/ul]/ + || s/([^<]*)<\/tt>/[fixed]${1}[\/fixed]/ + || s/([^<]*)<\/fg>/[color=$1]${2}[\/color]/; + } + + $color &= cf::NDI_COLOR_MASK; + + utf8::encode $msg; + if (0 && $msg =~ /\[/) { - $self->send_packet ("drawextinfo $color 4 0 $msg") + # COMMAND/INFO + $self->send_packet ("drawextinfo $color 10 8 $msg") } else { $msg =~ s/\[\/?(?:b|i|u|fixed|color)[^\]]*\]//g; $self->send_packet ("drawinfo $color $msg") @@ -2700,7 +2696,11 @@ $SIG{FPE} = 'IGNORE'; -$safe->permit_only (Opcode::opset qw(:base_core :base_mem :base_orig :base_math sort time)); +$safe->permit_only (Opcode::opset qw( + :base_core :base_mem :base_orig :base_math + grepstart grepwhile mapstart mapwhile + sort time +)); # here we export the classes and methods available to script code @@ -2710,7 +2710,7 @@ cf::object contr pay_amount pay_player map x y force_find force_add - insert remove + insert remove name archname title slaying race cf::object::player player @@ -2725,7 +2725,7 @@ for ( ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y - insert remove)], + insert remove inv name archname title slaying race)], ["cf::object::player" => qw(player)], ["cf::player" => qw(peaceful)], ["cf::map" => qw(trigger)], @@ -2901,13 +2901,14 @@ or next; my $face = cf::face::find "sound/$sound->[1]"; - warn "$sound->[0]: $face\n";#d# - cf::sound::set $sound->[0] => $face; cf::sound::old_sound_index $_, $face; # gcfclient-compat } - #TODO + while (my ($k, $v) = each %{$soundconf->{event}}) { + my $face = cf::face::find "sound/$v"; + cf::sound::set $k => $face; + } } }