--- deliantra/Deliantra-Client/DC/Protocol.pm 2007/07/24 18:39:39 1.133 +++ deliantra/Deliantra-Client/DC/Protocol.pm 2007/08/14 13:25:25 1.154 @@ -50,20 +50,16 @@ } sort { $a->{par} <=> $b->{par} } CFPlus::Pod::find command => "*"; - $self->connect_ext (music => sub { - my ($ev) = @_; - - &::audio_music_set ($self->{songs} = $ev->{play}) - if $ev->{play}; + $self->connect_ext (ambient_music => sub { + my ($songs) = @_; + &::audio_music_set_ambient ($songs); }); $self->connect_ext (capabilities => sub { my (%cap) = @_; - $self->send_exti_msg (fx_want => { - 3 => !!$::CFG->{bgm_enable}, # FT_MUSIC - 5 => !!$::CFG->{audio_enable}, # FT_SOUND - }); + #$self->send ("setup sound 0"); # we use a different protocol + $self->update_fx_want; if (my $ts = $cap{tileset}) { if (my ($default) = grep $_->[2] & 1, @$ts) { @@ -189,7 +185,9 @@ # message window $self->connect_ext (channel_info => sub { - $::MESSAGE_WINDOW->add_channel ($_[0]); + my ($info) = @_; + $self->{channels}->{$info->{id}} = $info; + $::MESSAGE_WINDOW->add_channel ($info); }); # destroy widgets on logout @@ -223,26 +221,19 @@ $self } -sub logprint { - my ($self, @a) = @_; - - $self->{log_fh} ||= do { - my $path = "$Crossfire::VARDIR/log.$self->{host}"; - - open my $fh, ">>:utf8", $path - or die "Couldn't open logfile $path: $!"; - - $fh->autoflush (1); - - $fh; - }; +sub update_fx_want { + my ($self) = @_; - my ($sec, $min, $hour, $mday, $mon, $year) = localtime time; + $self->send_exti_msg (fx_want => { + 3 => !!$::CFG->{bgm_enable}, # FT_MUSIC + 5 => !!$::CFG->{audio_enable}, # FT_SOUND + }); +} - my $ts = sprintf "%04d-%02d-%02d %02d:%02d:%02d", - $year + 1900, $mon + 1, $mday, $hour, $min, $sec; +sub logprint { + my ($self, @a) = @_; - print {$self->{log_fh}} "$ts ", @a, "\n"; + CFPlus::DB::logprint "$Crossfire::VARDIR/log.$self->{host}" => (join "", @a), sub { }; } sub _stat_numdiff { @@ -517,8 +508,36 @@ sub feed_map1a { my ($self, $data) = @_; - $self->{map}->map1a_update ($data, $self->{setup}{extmap}); - $self->{map_widget}->update; + my $missing = $self->{map}->map1a_update ($data, $self->{setup}{extmap}); + my $delay; + + for my $tile (@$missing) { + next if $self->{delay}{$tile}; + + $delay = 1; + + if (my $tex = $::CONN->{texture}[$tile]) { + $tex->upload; + } else { + $self->{delay}{$tile} = 1; + + # we assume the face is in-flight and will eventually come + push @{$self->{face_cb}{$tile}}, sub { + delete $self->{delay}{$tile}; + $_[0]->upload; + }; + } + } + + if ($delay) { + # delay the map drawing a tiny bit in the hope of getting the missing fetched + Event->timer (after => 0.03, cb => sub { + $_[0]->w->cancel; + $self->{map_widget}->update; + }); + } else { + $self->{map_widget}->update; + } } sub magicmap { @@ -535,9 +554,9 @@ my ($hash, $x, $y, $w, $h) = @$map_info; - my $data = $self->{map}->get_rect ($x, $y, $w, $h); - CFPlus::DB::put $self->{mapcache} => $hash => Compress::LZF::compress $data, sub { }; - #warn sprintf "SAVEmap[%s] length %d\n", $hash, length $data;#d# + my $data = Compress::LZF::compress $self->{map}->get_rect ($x, $y, $w, $h); + $self->{map_cache_new}{$hash} = \$data; + CFPlus::DB::put $self->{mapcache} => $hash => $data, sub { }; } sub map_clear { @@ -560,13 +579,15 @@ or return; } while $self->{texture}[$id]; - CFPlus::DB::get tilecache => $id, sub { - my ($data) = @_; + CFPlus::DB::exists tilecache => $id, sub { + my ($exists) = @_; return unless $self->{map}; # stop when destroyed - $self->set_texture ($id => $data) - if defined $data; + if ($exists) { + $self->have_tile ($id); + $self->{texture}[$id]->upload; + } $self->bg_fetch; }; @@ -577,20 +598,27 @@ my $gen = $self->{map_change_gen}; - CFPlus::DB::get $self->{mapcache} => $hash, sub { + my $cb = sub { return unless $gen == $self->{map_change_gen}; my ($data) = @_; if (defined $data) { - $data = Compress::LZF::decompress $data; - #warn sprintf "LOADmap[%s,%d,%d] length %d\n", $hash, $x, $y, length $data;#d# + $self->{map_cache_new}{$hash} = \$data; + + my $data = Compress::LZF::decompress $data; my $inprogress = @{ $self->{bg_fetch} || [] }; unshift @{ $self->{bg_fetch} }, $self->{map}->set_rect ($x, $y, $data); $self->bg_fetch unless $inprogress; } }; + + if (my $rdata = $self->{map_cache_old}{$hash}) { + $cb->($$rdata); + } else { + CFPlus::DB::get $self->{mapcache} => $hash, $cb; + } } # hardcode /world/world_xxx_xxx map names, the savings are enourmous, @@ -693,6 +721,7 @@ $self->flush_map; ++$self->{map_change_gen}; + $self->{map_cache_old} = delete $self->{map_cache_new}; my ($ox, $oy) = ($::MAP->ox, $::MAP->oy); @@ -732,8 +761,7 @@ CFPlus::DB::get tilecache => $id, $cb; } elsif ($face->{type} & 1) { # with metadata - #::message ({ markup => "starting to download song #$face/$pri, check your output-rate setting if your connection gets laggy." }); - CFPlus::DB::get "res-metadata" => $face->{name}, $cb; + CFPlus::DB::get res_meta => $face->{name}, $cb; } } @@ -744,38 +772,37 @@ CFPlus::DB::put tilecache => $face->{id} => $face->{data}, sub { } if $changed; - $self->set_texture ($face->{id} => delete $face->{data}); + $self->have_tile ($face->{id}); } elsif ($face->{type} & 1) { # split metadata - my $cb = sub { }; + if ($changed) { # new data + my ($meta_json, $data) = unpack "(w/a*)*", delete $face->{data}; + $face->{meta} = $self->{json_coder}->decode ($meta_json); - if ($face->{type} == 3) { # FT_MUSIC - $cb = sub { - $self->{music_meta}{$facenum} = $face; + 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}); + } - ::message ({ markup => "downloaded song #$facenum" }) - if $changed; + ::add_license ($face); - &::audio_music_set ($self->{songs}); - }; - } + if ($face->{type} == 3) { # FT_MUSIC + $self->{music_meta}{$facenum} = $face; - if ($changed) { # new data - my ($meta_json, $data) = unpack "(w/a*)*", delete $face->{data}; - my $path = CFPlus::DB::path_of_res $face->{name}; + ::message ({ markup => "downloaded song #$facenum" }) + if $changed; - CFPlus::DB::write_file $path, $data, sub { - CFPlus::DB::put "res-metadata" => $face->{name} => $meta_json, sub { - $face->{meta} = $self->{json_coder}->decode ($meta_json); - $face->{path} = $path; + &::audio_music_push ($facenum); + } elsif ($face->{type} == 5) { # FT_SOUND + $self->{sound_meta}{$facenum} = $face; - $cb->(); - }; - }; - } else { - $face->{meta} = $self->{json_coder}->decode (delete $face->{data}); - $cb->(); + ::message ({ markup => "downloaded sound #$facenum" }) + if $changed; + + &::audio_sound_push ($facenum); } + } } @@ -785,19 +812,16 @@ $self->{map}->set_smooth ($facenum, $face->{smoothface}, $face->{smoothlevel}); } -sub set_texture { - my ($self, $id, $data) = @_; +sub have_tile { + my ($self, $tile) = @_; return unless $self->{map}; - $self->{texture}[$id] = my $tex = - new_from_image CFPlus::Texture - $data, minify => 1, mipmap => 1; - - $self->{map}->set_texture ($id, @$tex{qw(name w h s t)}, @{$tex->{minified}}); - $self->{map_widget}->update; + my $tex = $self->{texture}[$tile] ||= + new CFPlus::Texture + tile => $tile, minify => 1, mipmap => 1, delay => 1; - $_->() for @{(delete $self->{face_cb}{$id}) || []}; + $_->($tex) for @{(delete $self->{face_cb}{$tile}) || []}; } sub connect_face_update { @@ -813,9 +837,10 @@ } sub sound_play { - my ($self, $x, $y, $soundnum, $type) = @_; + my ($self, $type, $face, $dx, $dy, $vol) = @_; - $self->{sound_play}->($x, $y, $soundnum, $type); + &::audio_sound_play ($face, $dx, $dy, $vol) + unless $type & 1; # odd types are silent for future expansion } my $LAST_QUERY; # server is stupid, stupid, stupid @@ -890,14 +915,19 @@ $self->logprint ("msg: ", $text); return if $color < 0; # negative color == ignore if not understood - my $fg = $CF_COLOR[$color % @CF_COLOR]; + my $fg = $CF_COLOR[$color & NDI_COLOR_MASK] || [1, 0, 0]; ## try to create single paragraphs of multiple lines sent by the server # no longer neecssary with TRT servers #$text =~ s/(?<=\S)\n(?=\w)/ /g; - ::message ({ fg => $fg, markup => $_, type => $type }) - for split /\n/, $text; + ::message ({ + fg => $fg, + markup => $_, + type => $type, + extra => [@extra], + color_flags => $color + }) for split /\n/, $text; $self->{statusbox}->add ($text, group => $text, @@ -963,40 +993,6 @@ ::stop_game (); } -sub image_info { - my ($self, $numfaces) = @_; - - $self->{num_faces} = $numfaces; - $self->{face_prefetch} = [1 .. $numfaces]; - $self->face_prefetch; -} - -sub face_prefetch { - my ($self) = @_; - - return unless $::CFG->{face_prefetch}; - - if ($self->{num_faces}) { - return if @{ $self->{send_queue} || [] }; - my $todo = @{ $self->{face_prefetch} } - or return; - - my ($face) = splice @{ $self->{face_prefetch} }, + rand @{ $self->{face_prefetch} }, 1, (); - - $self->send ("requestinfo image_sums $face $face"); - - $self->{statusbox}->add (CFPlus::asxml "prefetching $todo", - group => "prefetch", timeout => 3, fg => [1, 1, 0, 0.5]); - } elsif (!exists $self->{num_faces}) { - $self->send ("requestinfo image_info"); - - $self->{num_faces} = 0; - - $self->{statusbox}->add (CFPlus::asxml "starting to prefetch", - group => "prefetch", timeout => 3, fg => [1, 1, 0, 0.5]); - } -} - sub update_floorbox { $CFPlus::UI::ROOT->on_refresh ($::FLOORBOX => sub { return unless $::CONN; @@ -1035,7 +1031,7 @@ $::FLOORBOX->add_at (@add); }); - $::WANT_REFRESH++; + $::WANT_REFRESH->start; } sub set_opencont { @@ -1162,7 +1158,6 @@ . "map size $self->{mapw}×$self->{maph}\n" ); - ::setup_build_button ($self->{editor_support}->{builder_ui}); } sub logged_in { @@ -1194,14 +1189,6 @@ $self->send_command ("pickup $::CFG->{pickup}"); } -sub buildat { - my ($self, $builditem, $x, $y) = @_; - - if ($self->{cfplus_ext}) { - $self->send_ext_msg (builder_build => dx => $x, dy => $y, (ref ($builditem) eq 'HASH') ? %$builditem : (item => $builditem)); - } -} - sub lookat { my ($self, $x, $y) = @_;