--- deliantra/Deliantra-Client/DC/Protocol.pm 2007/08/17 21:18:01 1.155 +++ deliantra/Deliantra-Client/DC/Protocol.pm 2007/08/21 00:59:34 1.156 @@ -61,6 +61,20 @@ #$self->send ("setup sound 0"); # we use a different protocol $self->update_fx_want; + $self->send_exti_req (resource => "exp_table", sub { + my ($exp_table) = @_; + + $self->register_face_handler ($exp_table, sub { + my ($face) = @_; + + $self->{exp_table} = $self->{json_coder}->decode (delete $face->{data}); + + #TODO: update all interested parties + }); + + () + }); + if (my $ts = $cap{tileset}) { if (my ($default) = grep $_->[2] & 1, @$ts) { $self->{tileset} = $default; @@ -286,6 +300,7 @@ $self->send_exti_msg (fx_want => { 3 => !!$::CFG->{bgm_enable}, # FT_MUSIC 5 => !!$::CFG->{audio_enable}, # FT_SOUND + 6 => 1, # FT_RSRC }); } @@ -581,7 +596,7 @@ $self->{delay}{$tile} = 1; # we assume the face is in-flight and will eventually come - push @{$self->{face_cb}{$tile}}, sub { + push @{$self->{tile_cb}{$tile}}, sub { delete $self->{delay}{$tile}; $_[0]->upload; }; @@ -631,21 +646,21 @@ sub bg_fetch { my ($self) = @_; - my $id; + my $tile; do { - $id = pop @{$self->{bg_fetch}} + $tile = pop @{$self->{bg_fetch}} or return; - } while $self->{texture}[$id]; + } while $self->{texture}[$tile]; - CFPlus::DB::exists tilecache => $id, sub { - my ($exists) = @_; + CFPlus::DB::get tilecache => $tile, sub { + my ($data) = @_; return unless $self->{map}; # stop when destroyed - if ($exists) { - $self->have_tile ($id); - $self->{texture}[$id]->upload; + if (defined $data) { + $self->have_tile ($tile, $data); + $self->{texture}[$tile]->upload; } $self->bg_fetch; @@ -812,56 +827,63 @@ if ($face->{type} == 0) { # FT_FACE my $id = CFPlus::DB::get_tile_id_sync $face->{name}; - $face->{id} = $id; - $self->{faceid}[$facenum] = $id; - + $face->{id} = $id; $self->{map}->set_tileid ($facenum => $id); CFPlus::DB::get tilecache => $id, $cb; } elsif ($face->{type} & 1) { # with metadata CFPlus::DB::get res_meta => $face->{name}, $cb; + + } else { # no metadata + CFPlus::DB::get res_data => $face->{name}, $cb; } } sub face_update { my ($self, $facenum, $face, $changed) = @_; - if ($face->{type} == 0) { # FT_FACE + if ($face->{type} == 0) { + # image, FT_FACE CFPlus::DB::put tilecache => $face->{id} => $face->{data}, sub { } if $changed; - $self->have_tile ($face->{id}); + $self->have_tile ($face->{id}, delete $face->{data}); - } elsif ($face->{type} & 1) { # split metadata + } elsif ($face->{type} & 1) { + # split metadata case, FT_MUSIC, FT_SOUND if ($changed) { # new data - my ($meta_json, $data) = unpack "(w/a*)*", delete $face->{data}; - $face->{meta} = $self->{json_coder}->decode ($meta_json); + my ($meta, $data) = unpack "(w/a*)*", $face->{data}; + $face->{data} = $meta; CFPlus::DB::put res_data => $face->{name} => $data, sub { }; - CFPlus::DB::put res_meta => $face->{name} => $meta_json, sub { }; - } else { - $face->{meta} = $self->{json_coder}->decode (delete $face->{data}); + CFPlus::DB::put res_meta => $face->{name} => $meta, sub { }; } + $face->{data} = $self->{json_coder}->decode ($face->{data}); + ::add_license ($face); if ($face->{type} == 3) { # FT_MUSIC - $self->{music_meta}{$facenum} = $face; - ::message ({ markup => "downloaded song #$facenum" }) if $changed; &::audio_music_push ($facenum); } elsif ($face->{type} == 5) { # FT_SOUND - $self->{sound_meta}{$facenum} = $face; - ::message ({ markup => "downloaded sound #$facenum" }) if $changed; &::audio_sound_push ($facenum); } + } else { + # flat resource case, FT_RSRC + CFPlus::DB::put res_data => $face->{name} => $face->{data}, sub { } + if $changed; + } + + if (my $cbs = $self->{face_cb}{$facenum}) { + $_->($face, $changed) for @$cbs; } } @@ -872,27 +894,48 @@ } sub have_tile { - my ($self, $tile) = @_; + my ($self, $tile, $data) = @_; return unless $self->{map}; my $tex = $self->{texture}[$tile] ||= new CFPlus::Texture - tile => $tile, minify => 1, mipmap => 1, delay => 1; + tile => $tile, + image => $data, delete_image => 1, + minify => 1, mipmap => 1; - $_->($tex) for @{(delete $self->{face_cb}{$tile}) || []}; + if (my $cbs = delete $self->{tile_cb}{$tile}) { + $_->($tex) for @$cbs; + } } -sub connect_face_update { - my ($self, $id, $cb) = @_; +# call in non-void context registers a temporary +# hook with handle, otherwise its permanent +sub on_face_change { + my ($self, $num, $cb) = @_; - push @{$self->{face_cb}{$id}}, $cb; + push @{$self->{face_cb}{$num}}, $cb; - CFPlus::guard { - @{$self->{face_cb}{$id}} - = grep $_ != $cb, - @{$self->{face_cb}{$id}}; - } + defined wantarray + ? CFPlus::guard { + @{$self->{face_cb}{$num}} + = grep $_ != $cb, + @{$self->{face_cb}{$num}}; + } + : () +} + +# call in non-void context registers a temporary +# hook with handle, otherwise its permanent +sub register_face_handler { + my ($self, $num, $cb) = @_; + + # invoke if available right now + $cb->($self->{face}[$num], 0) + unless exists $self->{face}[$num]{loading}; + + # future changes + $self->on_face_change ($num => $cb) } sub sound_play {