--- deliantra/Deliantra-Client/DC/Protocol.pm 2007/07/23 21:03:26 1.128 +++ deliantra/Deliantra-Client/DC/Protocol.pm 2007/08/09 03:40:01 1.147 @@ -23,7 +23,7 @@ setup_req => { extmap => 1, excmd => 1, - ywidget => 1, + ywidget => 1,#d# %{$arg{setup_req} || {}}, }, ); @@ -50,63 +50,17 @@ } sort { $a->{par} <=> $b->{par} } CFPlus::Pod::find command => "*"; - $self->connect_ext (music => sub { - my (%ev) = @_; - - return unless $::CFG->{bgm_enable}; - - my $faces = $ev{faces}; - my @songs; - - # request music from server if appropriate - if (my $faces = $ev{faces}) { - for (@$faces) { - my ($face, $pri, $chksum) = @$_; - utf8::downgrade $chksum; - - $chksum = unpack "H*", $chksum; - $self->{music_map}{$face} = $chksum; - - # check if already cached - CFPlus::DB::get "res-metadata" => $chksum, sub { - my ($meta_json) = @_; - my $path = CFPlus::DB::path_of_res $chksum; - - if (defined $meta_json) { - my $meta = $self->{json_coder}->decode ($meta_json); - $meta->{path} = $path; - $self->{music_meta}{$chksum} = $meta; - &::audio_music_set ($self->{songs}); - } else { - ::message ({ markup => "starting to download song #$face/$pri, check your output-rate setting if your connection gets laggy." }); - $self->ask_face ($face, -100 - $pri, undef, sub { - my $len = length $_[1]; - my ($meta_json, $data) = unpack "(w/a*)*", $_[1]; - - CFPlus::DB::write_file $path, $data, sub { - CFPlus::DB::put "res-metadata" => $chksum => $meta_json, sub { - my $meta = $self->{json_coder}->decode ($meta_json); - $meta->{path} = $path; - $self->{music_meta}{$chksum} = $meta; - - ::message ({ markup => "downloaded song #$face, size $len octets" }); - &::audio_music_set ($self->{songs}); - }; - }; - }); - } - } - } - } - - if (my $play = $ev{play}) { - &::audio_music_set ($self->{songs} = [map $self->{music_map}{$_}, @$play]); - } + $self->connect_ext (ambient_music => sub { + my ($songs) = @_; + &::audio_music_set_ambient ($songs); }); $self->connect_ext (capabilities => sub { my (%cap) = @_; + #$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) { $self->{tileset} = $default; @@ -123,40 +77,38 @@ $self->{json_coder} ->convert_blessed - ->filter_json_single_key_object (__widget_ref__ => sub { + ->filter_json_single_key_object (__w_ => sub { $self->{widget}{$_[0]} }); # widgetset new $self->connect_ext (ws_n => sub { - my ($arg) = @_; + my ($id) = @_; - $self->{widgetset}{$arg{id}} = { + $self->{widgetset}{$id} = { w => {}, }; }); # widgetset destroy $self->connect_ext (ws_d => sub { - my ($arg) = @_; + my ($id) = @_; - my $ws = delete $self->{widgetset}{$arg{id}} + my $ws = delete $self->{widgetset}{$id} or return; $_->destroy for values %{$ws->{w}}; }); - # widgetset destroy + # widgetset create $self->connect_ext (ws_c => sub { - my ($arg) = @_; - - my $args = $arg->{args} || {}; + my ($ws, $id, $class, $args) = @_; for my $ev (grep /^on_/, keys %$args) { $args->{$ev} = sub { my $id = shift->{s_id}; - $self->send_exti_msg (w_e => id => $id, name => $ev, args => \@_); + $self->send_exti_msg (w_e => $id, $ev, \@_); 1 }; @@ -164,15 +116,15 @@ if (my $widget = eval { local $SIG{__DIE__}; - "CFPlus::UI::$arg->{class}"->new ( + "CFPlus::UI::$class"->new ( %$args, - s_ws => $arg->{ws}, - s_id => $arg->{id}, + s_ws => $ws, + s_id => $id, ) } ) { - $self->{widget}{$arg->{id}} - = $self->{widgetset}{$arg->{ws}}{w}{$arg->{id}} + $self->{widget}{$id} + = $self->{widgetset}{$ws}{w}{$id} = $widget; $widget->connect (on_destroy => sub { @@ -182,37 +134,34 @@ delete $self->{widgetset}{$widget->{s_ws}}{$widget->{s_id}}; }); } else { - warn "server failed creating client-side widget " . (CFPlus::to_json $arg) . ": $@\n"; - $self->send_exti_msg (w_e => id => $arg->{id}, name => "destroy"); + warn "server failed creating client-side widget " . (CFPlus::to_json $class) . ": $@\n"; + $self->send_exti_msg (w_e => $id, "destroy"); } }); # widget call $self->connect_ext (w_c => sub { - my ($arg) = @_; + my ($id, $rid, $method, $args) = @_; - my $w = $self->{widget}{$arg->{id}} + my $w = $self->{widget}{$id} or return; - my $m = $arg->{name}; - my $a = $arg->{args} || []; + $args ||= []; - if (exists $arg->{rid}) { - $self->send_exti_msg (w_r => rid => $arg->{rid}, res => [$w->$m (@$a)]); + if ($rid) { + $self->send_exti_msg (w_r => $rid, [$w->$method (@$args)]); } else { - $w->$m (@$a); + $w->$method (@$args); } }); # widget set $self->connect_ext (w_s => sub { - my ($arg) = @_; + my ($id, $attr) = @_; - my $w = $self->{widget}{$arg->{id}} + my $w = $self->{widget}{$id} or return; - my $attr = $arg->{attr}; - for (my $i = 0; $i < $#$attr; $i += 2) { my ($member, $value) = @$attr[$i, $i+1]; if (defined $value) { @@ -226,12 +175,19 @@ # widget get $self->connect_ext (w_g => sub { - my ($arg) = @_; + my ($id, $rid, $attr) = @_; - my $w = $self->{widget}{$arg->{id}} + my $w = $self->{widget}{$id} or return; - $self->send_exti_msg (w_r => rid => $arg->{rid}, res => [map $w->{$_}, @{$arg->{attr}}]); + $self->send_exti_msg (w_r => $rid, [map $w->{$_}, @$attr]); + }); + + # message window + $self->connect_ext (channel_info => sub { + my ($info) = @_; + $self->{channels}->{$info->{id}} = $info; + $::MESSAGE_WINDOW->add_channel ($info); }); # destroy widgets on logout @@ -265,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 { @@ -602,13 +551,13 @@ 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; + $self->have_tile ($id) + if $exists; $self->bg_fetch; }; @@ -763,25 +712,61 @@ sub face_find { my ($self, $facenum, $face, $cb) = @_; - my $hash = "$face->{chksum},$face->{name}"; + if ($face->{type} == 0) { # FT_FACE + my $id = CFPlus::DB::get_tile_id_sync $face->{name}; - my $id = CFPlus::DB::get_tile_id_sync $hash; + $face->{id} = $id; + $self->{faceid}[$facenum] = $id; - $face->{id} = $id; - $self->{faceid}[$facenum] = $id; + $self->{map}->set_tileid ($facenum => $id); - $self->{map}->set_tileid ($facenum => $id); + CFPlus::DB::get tilecache => $id, $cb; - 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_meta => $face->{name}, $cb; + } } sub face_update { my ($self, $facenum, $face, $changed) = @_; - CFPlus::DB::put tilecache => $face->{id} => $face->{image}, sub { } - if $changed; + if ($face->{type} == 0) { # FT_FACE + CFPlus::DB::put tilecache => $face->{id} => $face->{data}, sub { } + if $changed; + + $self->have_tile ($face->{id}); + + } elsif ($face->{type} & 1) { # split metadata + if ($changed) { # new data + my ($meta_json, $data) = unpack "(w/a*)*", delete $face->{data}; + $face->{meta} = $self->{json_coder}->decode ($meta_json); + + 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}); + } + + ::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); + } - $self->set_texture ($face->{id} => delete $face->{image}); + } } sub smooth_update { @@ -790,19 +775,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; + $self->{texture}[$tile] ||= my $tex = + new CFPlus::Texture + tile => $tile, minify => 1, mipmap => 1, delay => 1; - $_->() for @{(delete $self->{face_cb}{$id}) || []}; + $_->() for @{(delete $self->{face_cb}{$tile}) || []}; } sub connect_face_update { @@ -818,9 +800,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 @@ -895,13 +878,13 @@ $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 & 0x1f] || [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 => $_ }) + ::message ({ fg => $fg, markup => $_, type => $type, extra => [@extra] }) for split /\n/, $text; $self->{statusbox}->add ($text, @@ -968,40 +951,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; @@ -1167,7 +1116,6 @@ . "map size $self->{mapw}×$self->{maph}\n" ); - ::setup_build_button ($self->{editor_support}->{builder_ui}); } sub logged_in { @@ -1199,14 +1147,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) = @_;