--- deliantra/server/lib/cf.pm 2007/08/01 17:22:51 1.327 +++ deliantra/server/lib/cf.pm 2007/08/20 22:21:48 1.335 @@ -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; + # 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) - my $res = (Coro::Handle::unblock $fh1)->readline (undef); - warn "pst<$res>" unless $res =~ /^pst/; - $res = Coro::Storable::thaw $res; - - 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); - - eval { - close $fh1; - - my @res = eval { $cb->(@args) }; - - syswrite $fh2, _store_scalar $@ ? \"$@" : \@res; - close $fh2; - }; + &$cb + }, @args; - 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 @@ -1945,10 +1918,10 @@ } # find and load all maps in the 3x3 area around a map -sub load_diag { +sub load_neighbours { my ($map) = @_; - my @diag; # diagonal neighbours + my @neigh; # diagonal neighbours for (0 .. 3) { my $neigh = $map->tile_path ($_) @@ -1957,12 +1930,14 @@ or next; $neigh->load; - push @diag, [$neigh->tile_path (($_ + 3) % 4), $neigh], - [$neigh->tile_path (($_ + 1) % 4), $neigh]; + push @neigh, + [$neigh->tile_path (($_ + 3) % 4), $neigh], + [$neigh->tile_path (($_ + 1) % 4), $neigh]; } - for (@diag) { - my $neigh = find @$_ + for (grep defined $_->[0], @neigh) { + my ($path, $origin) = @$_; + my $neigh = find $path, $origin or next; $neigh->load; } @@ -2245,6 +2220,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" @@ -2331,7 +2316,7 @@ if $x <=0 && $y <= 0; $map->load; - $map->load_diag; + $map->load_neighbours; return unless $self->contr->active; $self->activate_recursive; @@ -2555,7 +2540,8 @@ 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") @@ -2712,7 +2698,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 @@ -2722,7 +2712,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 @@ -2737,7 +2727,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)], @@ -2823,6 +2813,8 @@ sub load_facedata($) { my ($path) = @_; + my $enc = JSON::XS->new->utf8->canonical; + warn "loading facedata from $path\n"; my $facedata; @@ -2834,6 +2826,13 @@ $facedata->{version} == 2 or cf::cleanup "$path: version mismatch, cannot proceed."; + # patch in the exptable + $facedata->{resource}{"res/exp_table"} = { + type => FT_RSRC, + data => $enc->encode ([map cf::level_to_min_exp $_, 0 .. cf::settings->max_level]), + }; + cf::cede_to_tick; + { my $faces = $facedata->{faceinfo}; @@ -2841,8 +2840,8 @@ my $idx = (cf::face::find $face) || cf::face::alloc $face; cf::face::set_visibility $idx, $info->{visibility}; cf::face::set_magicmap $idx, $info->{magicmap}; - cf::face::set_data $idx, 0, $info->{data32}, $info->{chksum32}; - cf::face::set_data $idx, 1, $info->{data64}, $info->{chksum64}; + cf::face::set_data $idx, 0, $info->{data32}, Digest::MD5::md5 $info->{data32}; + cf::face::set_data $idx, 1, $info->{data64}, Digest::MD5::md5 $info->{data64}; cf::cede_to_tick; } @@ -2877,29 +2876,25 @@ # TODO: for gcfclient pleasure, we should give resources # that gcfclient doesn't grok a >10000 face index. my $res = $facedata->{resource}; - my $enc = JSON::XS->new->utf8->canonical; my $soundconf = delete $res->{"res/sound.conf"}; while (my ($name, $info) = each %$res) { - my $meta = $enc->encode ({ - name => $name, - %{ $info->{meta} || {} }, - }); - my $idx = (cf::face::find $name) || cf::face::alloc $name; + my $data; if ($info->{type} & 1) { # prepend meta info - my $data = pack "(w/a*)*", $meta, $info->{data}; - my $chk = Digest::MD5::md5 "$info->{chksum},$meta"; # mangle data checksum and metadata + my $meta = $enc->encode ({ + name => $name, + %{ $info->{meta} || {} }, + }); - cf::face::set_data $idx, 0, $data, $chk; - } else { - cf::face::set_data $idx, 0, $info->{data}, $info->{chksum}; + $data = pack "(w/a*)*", $meta, $info->{data}; } + cf::face::set_data $idx, 0, $data, Digest::MD5::md5 $data; cf::face::set_type $idx, $info->{type}; cf::cede_to_tick;