--- deliantra/Deliantra-Client/bin/cfplus 2006/05/25 16:54:29 1.3 +++ deliantra/Deliantra-Client/bin/cfplus 2006/05/27 08:45:24 1.14 @@ -31,11 +31,13 @@ use Event; use Crossfire; -use Crossfire::Protocol; +use Crossfire::Protocol::Constants; use Compress::LZF; use CFClient; +use CFClient::OpenGL (); +use CFClient::Protocol; use CFClient::UI; use CFClient::MapWidget; @@ -53,10 +55,6 @@ our $META_SERVER = "crossfire.real-time.com:13326"; -our $FACEMAP; -our $TILECACHE; -our $MAPCACHE; - our $LAST_REFRESH; our $NOW; @@ -101,11 +99,9 @@ our $STATUSBOX; our $DEBUG_STATUS; -our $INVWIN; our $INV; our $INVR; our $INVR_LBL; -our $OPENCONT; sub status { $STATUSBOX->add (CFClient::UI::Label::escape $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]); @@ -122,20 +118,36 @@ my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32; - $MAPCACHE = CFClient::db_table "mapcache_$CFG->{host}"; - $MAP = new CFClient::Map $mapsize, $mapsize; - my ($host, $port) = split /:/, $CFG->{host}; + + $MAP = new CFClient::Map $mapsize, $mapsize; $CONN = eval { - new conn + new CFClient::Protocol host => $host, port => $port || 13327, user => $CFG->{user}, pass => $CFG->{password}, mapw => $mapsize, maph => $mapsize, - ; + + map_widget => $MAPWIDGET, + logview => $LOGVIEW, + statusbox => $STATUSBOX, + map => $MAP, + mapmap => $MAPMAP, + + sound_play => sub { + my ($x, $y, $soundnum, $type) = @_; + + $SDL_MIXER + or return; + + my $chunk = $AUDIO_CHUNKS{$SOUNDS[$soundnum]} + or return; + + $chunk->play; + }, }; if ($CONN) { @@ -163,9 +175,6 @@ $BUTTONBAR->{children}[1]->emit ("activate") unless $BUTTONBAR->{children}[1]->{state}; - - undef $MAPCACHE; - undef $MAP; } sub client_setup { @@ -434,6 +443,15 @@ can_hover => 1, can_events => 1, tooltip => "The map you are currently on (if supported by the server)."); + $vb->add (my $hb0 = new CFClient::UI::HBox); + $hb0->add ($STATWIDS->{weight} = new CFClient::UI::Label valign => 0, align => -1, text => "Weight:", expand => 1, + can_hover => 1, can_events => 1, + tooltip => "This is the amount the Player weights."); + $hb0->add ($STATWIDS->{m_weight} = new CFClient::UI::Label valign => 0, align => -1, text => "Max weight:", expand => 1, + can_hover => 1, can_events => 1, + tooltip => "The weight limit, you can't carry more than this."); + + $vb->add (my $hb = new CFClient::UI::HBox expand => 1); $hb->add (my $tbl = new CFClient::UI::Table expand => 1); @@ -531,43 +549,47 @@ sub update_stats_window { my ($stats) = @_; - # i love text protocols!!! - my $hp = $stats->{Crossfire::Protocol::CS_STAT_HP} * 1; - my $hp_m = $stats->{Crossfire::Protocol::CS_STAT_MAXHP} * 1; - my $sp = $stats->{Crossfire::Protocol::CS_STAT_SP} * 1; - my $sp_m = $stats->{Crossfire::Protocol::CS_STAT_MAXSP} * 1; - my $fo = $stats->{Crossfire::Protocol::CS_STAT_FOOD} * 1; + # I love text protocols... + + my $hp = $stats->{+CS_STAT_HP} * 1; + my $hp_m = $stats->{+CS_STAT_MAXHP} * 1; + my $sp = $stats->{+CS_STAT_SP} * 1; + my $sp_m = $stats->{+CS_STAT_MAXSP} * 1; + my $fo = $stats->{+CS_STAT_FOOD} * 1; my $fo_m = 999; - my $gr = $stats->{Crossfire::Protocol::CS_STAT_GRACE} * 1; - my $gr_m = $stats->{Crossfire::Protocol::CS_STAT_MAXGRACE} * 1; + my $gr = $stats->{+CS_STAT_GRACE} * 1; + my $gr_m = $stats->{+CS_STAT_MAXGRACE} * 1; $GAUGES->{hp} ->set_value ($hp, $hp_m); $GAUGES->{mana} ->set_value ($sp, $sp_m); $GAUGES->{food} ->set_value ($fo, $fo_m); $GAUGES->{grace} ->set_value ($gr, $gr_m); - $GAUGES->{exp} ->set_text ("Exp: " . (formsep $stats->{Crossfire::Protocol::CS_STAT_EXP64}) - . " (lvl " . ($stats->{Crossfire::Protocol::CS_STAT_LEVEL} * 1) . ")"); - my $rng = $stats->{Crossfire::Protocol::CS_STAT_RANGE}; + $GAUGES->{exp} ->set_text ("Exp: " . (formsep $stats->{+CS_STAT_EXP64}) + . " (lvl " . ($stats->{+CS_STAT_LEVEL} * 1) . ")"); + my $rng = $stats->{+CS_STAT_RANGE}; $rng =~ s/^Range: //; # thank you so much dear server $GAUGES->{range} ->set_text ("Rng: " . $rng); - my $title = $stats->{Crossfire::Protocol::CS_STAT_TITLE}; + my $title = $stats->{+CS_STAT_TITLE}; $title =~ s/^Player: //; $STATWIDS->{title} ->set_text ("Title: " . $title); - $STATWIDS->{st_str} ->set_text (sprintf "%d", $stats->{5}); - $STATWIDS->{st_dex} ->set_text (sprintf "%d", $stats->{8}); - $STATWIDS->{st_con} ->set_text (sprintf "%d", $stats->{9}); - $STATWIDS->{st_int} ->set_text (sprintf "%d", $stats->{6}); - $STATWIDS->{st_wis} ->set_text (sprintf "%d", $stats->{7}); - $STATWIDS->{st_pow} ->set_text (sprintf "%d", $stats->{22}); - $STATWIDS->{st_cha} ->set_text (sprintf "%d", $stats->{10}); - $STATWIDS->{st_wc} ->set_text (sprintf "%d", $stats->{13}); - $STATWIDS->{st_ac} ->set_text (sprintf "%d", $stats->{14}); - $STATWIDS->{st_dam} ->set_text (sprintf "%d", $stats->{15}); - $STATWIDS->{st_arm} ->set_text (sprintf "%d", $stats->{16}); - $STATWIDS->{st_spd} ->set_text (sprintf "%.1f", $stats->{Crossfire::Protocol::CS_STAT_SPEED}); - $STATWIDS->{st_wspd}->set_text (sprintf "%.1f", $stats->{Crossfire::Protocol::CS_STAT_WEAP_SP}); + $STATWIDS->{st_str} ->set_text (sprintf "%d" , $stats->{+CS_STAT_STR}); + $STATWIDS->{st_dex} ->set_text (sprintf "%d" , $stats->{+CS_STAT_DEX}); + $STATWIDS->{st_con} ->set_text (sprintf "%d" , $stats->{+CS_STAT_CON}); + $STATWIDS->{st_int} ->set_text (sprintf "%d" , $stats->{+CS_STAT_INT}); + $STATWIDS->{st_wis} ->set_text (sprintf "%d" , $stats->{+CS_STAT_WIS}); + $STATWIDS->{st_pow} ->set_text (sprintf "%d" , $stats->{+CS_STAT_POW}); + $STATWIDS->{st_cha} ->set_text (sprintf "%d" , $stats->{+CS_STAT_CHA}); + $STATWIDS->{st_wc} ->set_text (sprintf "%d" , $stats->{+CS_STAT_WC}); + $STATWIDS->{st_ac} ->set_text (sprintf "%d" , $stats->{+CS_STAT_AC}); + $STATWIDS->{st_dam} ->set_text (sprintf "%d" , $stats->{+CS_STAT_DAM}); + $STATWIDS->{st_arm} ->set_text (sprintf "%d" , $stats->{+CS_STAT_ARMOUR}); + $STATWIDS->{st_spd} ->set_text (sprintf "%.1f", $stats->{+CS_STAT_SPEED}); + $STATWIDS->{st_wspd}->set_text (sprintf "%.1f", $stats->{+CS_STAT_WEAP_SP}); + + $STATWIDS->{m_weight}->set_text (sprintf "Max weight: %.1fkg", $stats->{+CS_STAT_WEIGHT_LIM} / 1000); + # TODO: replace by CS_STAT_RES_xxx constants my %tbl = ( phys => 100, magic => 101, @@ -586,13 +608,11 @@ depl => 113, deat => 115, holyw => 116, - blind => 117 + blind => 117, ); - for (keys %tbl) { - $STATWIDS->{"res_$_"}->set_text (sprintf "%d%", $stats->{$tbl{$_}}); - } - + $STATWIDS->{"res_$_"}->set_text (sprintf "%d%", $stats->{$tbl{$_}}) + for keys %tbl; } sub metaserver_dialog { @@ -886,12 +906,22 @@ $invwin->add (my $hb = new CFClient::UI::HBox expand => 1); $hb->add (my $vb1 = new CFClient::UI::VBox expand => 1); - $vb1->add (my $lbl = new CFClient::UI::Label); + $vb1->add (my $lbl = new CFClient::UI::Label align => 0); $lbl->set_text ("Player"); $vb1->add ($INV = new CFClient::UI::Inventory expand => 1); $hb->add (my $vb2 = new CFClient::UI::VBox expand => 1); - $vb2->add ($INVR_LBL = new CFClient::UI::Label); + $vb2->add (my $hb2 = new CFClient::UI::HBox); + $hb2->add (new CFClient::UI::Button + text => "Close", + tooltip => "Close the currently open container (if one is open)", + connect_activate => sub { + $CONN->send ("apply $CONN->{open_container}") + if $CONN->{open_container} != 0; + }, + ); + $hb2->add ($INVR_LBL = new CFClient::UI::Label align => 0); + $INVR_LBL->set_text ("Floor"); $vb2->add ($INVR = new CFClient::UI::Inventory expand => 1); @@ -958,7 +988,7 @@ $SDL_ACTIVE = 1; $LAST_REFRESH = time - 0.01; - CFClient::gl_init; + CFClient::OpenGL::init; $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize}; @@ -1237,500 +1267,6 @@ delete $animate_object{$widget}; } -@conn::ISA = Crossfire::Protocol::; - -sub conn::new { - my $class = shift; - - my $self = $class->Crossfire::Protocol::new (@_); - - $MAPWIDGET->clr_commands; - - my $parser = new Pod::POM; - my $pod = $parser->parse_file (CFClient::find_rcfile "pod/command_help.pod"); - - for my $head2 ($pod->head2) { - $head2->title =~ /^(\S+) (?:\s+ \( ([^\)]*) \) )?/x - or next; - - my $cmd = $1; - my @args = split /\|/, $2; - @args = (".*") unless @args; - - my $text = CFClient::pod_to_pango $head2->content; - - for my $arg (@args) { - $arg = $arg eq ".*" ? "" : " $arg"; - - $MAPWIDGET->add_command ("$cmd$arg", $text); - } - } - - $self->{noface} = new_from_file CFClient::Texture - CFClient::find_rcfile "noface.png", minify => 1, mipmap => 1; - - $self -} - -sub conn::stats_update { - my ($self, $stats) = @_; - - if (my $exp = $stats->{Crossfire::Protocol::CS_STAT_EXP64}) { - my $diff = $exp - $self->{prev_exp}; - $STATUSBOX->add ("$diff experience gained", group => "experience $diff", fg => [0.5, 1, 0.5, 0.8], timeout => 5) - if exists $self->{prev_exp} && $diff; - $self->{prev_exp} = $exp; - } - - update_stats_window ($stats); -} - -sub conn::user_send { - my ($self, $command) = @_; - - $self->send_command ($command); - status $command; -} - -sub conn::map_scroll { - my ($self, $dx, $dy) = @_; - - $MAP->scroll ($dx, $dy); -} - -sub conn::feed_map1a { - my ($self, $data) = @_; - -# $self->Crossfire::Protocol::feed_map1a ($data); - - $MAP->map1a_update ($data); - $MAPWIDGET->update; -} - -sub conn::flush_map { - my ($self) = @_; - - my $map_info = delete $self->{map_info} - or return; - - my ($hash, $x, $y, $w, $h) = @$map_info; - - my $data = $MAP->get_rect ($x, $y, $w, $h); - $MAPCACHE->put ($hash => Compress::LZF::compress $data); - #warn sprintf "SAVEmap[%s] length %d\n", $hash, length $data;#d# -} - -sub conn::map_clear { - my ($self) = @_; - - $self->flush_map; - delete $self->{neigh_map}; - - $MAP->clear; -} - - -sub conn::load_map($$$) { - my ($self, $hash, $x, $y) = @_; - - if (defined (my $data = $MAPCACHE->get ($hash))) { - $data = Compress::LZF::decompress $data; - #warn sprintf "LOADmap[%s,%d,%d] length %d\n", $hash, $x, $y, length $data;#d# - for my $id ($MAP->set_rect ($x, $y, $data)) { - my $data = $TILECACHE->get ($id) - or next; - - $self->set_texture ($id => $data); - } - } -} - -# hardcode /world/world_xxx_xxx map names, the savings are enourmous, -# (server resource,s latency, bandwidth), so this hack is warranted. -# the right fix is to make real tiled maps with an overview file -sub conn::send_mapinfo { - my ($self, $data, $cb) = @_; - - if ($self->{map_info}[0] =~ m%^/world/world_(\d\d\d)_(\d\d\d)$%) { - my ($wx, $wy) = ($1, $2); - - if ($data =~ /^spatial ([1-4]+)$/) { - my @dx = (0, 0, 1, 0, -1); - my @dy = (0, -1, 0, 1, 0); - my ($dx, $dy); - - for (split //, $1) { - $dx += $dx[$_]; - $dy += $dy[$_]; - } - - $cb->(spatial => 15, - $self->{map_info}[1] - $MAP->ox + $dx * 50, - $self->{map_info}[2] - $MAP->oy + $dy * 50, - 50, 50, - sprintf "/world/world_%03d_%03d", $wx + $dx, $wy + $dy - ); - - return; - } - } - - $self->Crossfire::Protocol::send_mapinfo ($data, $cb); -} - -# this method does a "flood fill" into every tile direction -# it assumes that tiles are arranged in a rectangular grid, -# i.e. a map is the same as the left of the right map etc. -# failure to comply are harmless and result in display errors -# at worst. -sub conn::flood_fill { - my ($self, $block, $gx, $gy, $path, $hash, $flags) = @_; - - # the server does not allow map paths > 6 - return if 7 <= length $path; - - my ($x0, $y0, $x1, $y1) = @{$self->{neigh_rect}}; - - for ( - [1, 3, 0, -1], - [2, 4, 1, 0], - [3, 1, 0, 1], - [4, 2, -1, 0], - ) { - my ($tile, $tile2, $dx, $dy) = @$_; - - next if $block & (1 << $tile); - my $block = $block | (1 << $tile2); - - my $gx = $gx + $dx; - my $gy = $gy + $dy; - - next unless $flags & (1 << ($tile - 1)); - next if $self->{neigh_grid}{$gx, $gy}++; - - my $neigh = $self->{neigh_map}{$hash} ||= []; - if (my $info = $neigh->[$tile]) { - my ($flags, $x, $y, $w, $h, $hash) = @$info; - - $self->flood_fill ($block, $gx, $gy, "$path$tile", $hash, $flags) - if $x >= $x0 && $x + $w < $x1 && $y >= $y0 && $y + $h < $y1; - - } else { - $self->send_mapinfo ("spatial $path$tile", sub { - my ($mode, $flags, $x, $y, $w, $h, $hash) = @_; - - return if $mode ne "spatial"; - - $x += $MAP->ox; - $y += $MAP->oy; - - $self->load_map ($hash, $x, $y) - unless $self->{neigh_map}{$hash}[5]++;#d# - - $neigh->[$tile] = [$flags, $x, $y, $w, $h, $hash]; - - $self->flood_fill ($block, $gx, $gy, "$path$tile", $hash, $flags) - if $x >= $x0 && $x + $w < $x1 && $y >= $y0 && $y + $h < $y1; - }); - } - } -} - -sub conn::map_change { - my ($self, $mode, $flags, $x, $y, $w, $h, $hash) = @_; - - $self->flush_map; - - my ($ox, $oy) = ($::MAP->ox, $::MAP->oy); - - my $mapmapw = $MAPMAP->{w}; - my $mapmaph = $MAPMAP->{h}; - - $self->{neigh_rect} = [ - $ox - $mapmapw * 0.5, $oy - $mapmapw * 0.5, - $ox + $mapmapw * 0.5 + $w, $oy + $mapmapw * 0.5 + $h, - ]; - - delete $self->{neigh_grid}; - - $x += $ox; - $y += $oy; - - $self->{map_info} = [$hash, $x, $y, $w, $h]; - - (my $map = $hash) =~ s/^.*?\/([^\/]+)$/\1/; - $STATWIDS->{map}->set_text ("Map: " . $map); - - $self->load_map ($hash, $x, $y); - $self->flood_fill (0, 0, 0, "", $hash, $flags); -} - -sub conn::face_find { - my ($self, $facenum, $face) = @_; - - my $hash = "$face->{chksum},$face->{name}"; - - my $id = $FACEMAP->get ($hash); - - unless ($id) { - # create new id for face - # I love transactions - for (1..100) { - my $txn = $CFClient::DB_ENV->txn_begin; - my $status = $FACEMAP->db_get (id => $id, BerkeleyDB::DB_RMW); - if ($status == 0 || $status == BerkeleyDB::DB_NOTFOUND) { - $id = ($id || 16) + 1; - if ($FACEMAP->put (id => $id) == 0 - && $FACEMAP->put ($hash => $id) == 0) { - $txn->txn_commit; - - goto gotid; - } - } - $txn->abort; - } - - CFClient::fatal "maximum number of transaction retries reached - database problems?"; - } - -gotid: - $face->{id} = $id; - $MAP->set_face ($facenum => $id); - $self->{faceid}[$facenum] = $id;#d# - - my $face = $TILECACHE->get ($id); - - if ($face) { - #$self->face_prefetch; - $face - } else { - my $tex = $self->{noface}; - $MAP->set_texture ($id, @$tex{qw(name w h s t)}, @{$tex->{minified}}); - undef - }; -} - -sub conn::face_update { - my ($self, $facenum, $face) = @_; - - $TILECACHE->put ($face->{id} => $face->{image}); #TODO: try to avoid duplicate writes - - $self->set_texture ($face->{id} => delete $face->{image}); -} - -sub conn::set_texture { - my ($self, $id, $data) = @_; - - $self->{texture}[$id] ||= do { - my $tex = - new_from_image CFClient::Texture - $data, minify => 1, mipmap => 1; - - $MAP->set_texture ($id, @$tex{qw(name w h s t)}, @{$tex->{minified}}); - $MAPWIDGET->update; - - $tex - }; -} - -sub conn::sound_play { - my ($self, $x, $y, $soundnum, $type) = @_; - - $SDL_MIXER - or return; - - my $chunk = $AUDIO_CHUNKS{$SOUNDS[$soundnum]} - or return; - - $chunk->play; -# warn "sound $x,$y,$soundnum,$type\n";#d# -} - -my $LAST_QUERY; # server is stupid, stupid, stupid - -sub conn::query { - my ($self, $flags, $prompt) = @_; - - $prompt = $LAST_QUERY unless length $prompt; - $LAST_QUERY = $prompt; - - my $dialog = new CFClient::UI::FancyFrame - title => "Query", - child => my $vbox = new CFClient::UI::VBox; - - $vbox->add (new CFClient::UI::Label - max_w => $::WIDTH * 0.4, - ellipsise => 0, - text => $prompt); - - if ($flags & Crossfire::Protocol::CS_QUERY_YESNO) { - $vbox->add (my $hbox = new CFClient::HBox); - $hbox->add (new CFClient::Button - text => "No", - connect_activate => sub { - $self->send ("reply n"); - $dialog->destroy; - $MAPWIDGET->focus_in; - } - ); - $hbox->add (new CFClient::Button - text => "Yes", - connect_activate => sub { - $self->send ("reply y"); - $dialog->destroy; - }, - ); - - $dialog->focus_in; - - } elsif ($flags & Crossfire::Protocol::CS_QUERY_SINGLECHAR) { - $dialog->{tooltip} = "Press a key (click on the entry to make sure it has keyboard focus)"; - $vbox->add (my $entry = new CFClient::UI::Entry - connect_changed => sub { - $self->send ("reply $_[1]"); - $dialog->destroy; - }, - ); - - $entry->focus_in; - - } else { - $dialog->{tooltip} = "Enter the reply and press return (click on the entry to make sure it has keyboard focus)"; - - $vbox->add (my $entry = new CFClient::UI::Entry - $flags & Crossfire::Protocol::CS_QUERY_HIDEINPUT ? (hiddenchar => "*") : (), - connect_activate => sub { - $self->send ("reply $_[1]"); - $dialog->destroy; - }, - ); - - $entry->focus_in; - } - - $dialog->show_centered; -} - -sub conn::drawinfo { - my ($self, $color, $text) = @_; - - my @color = ( - [1.00, 1.00, 1.00], #[0.00, 0.00, 0.00], - [1.00, 1.00, 1.00], - [0.50, 0.50, 1.00], #[0.00, 0.00, 0.55] - [1.00, 0.00, 0.00], - [1.00, 0.54, 0.00], - [0.11, 0.56, 1.00], - [0.93, 0.46, 0.00], - [0.18, 0.54, 0.34], - [0.56, 0.73, 0.56], - [0.80, 0.80, 0.80], - [0.55, 0.41, 0.13], - [0.99, 0.77, 0.26], - [0.74, 0.65, 0.41], - ); - - my $time = sprintf "%02d:%02d:%02d", (localtime time)[2,1,0]; - - $text = CFClient::UI::Label::escape $text; - $text =~ s/\[b\](.*?)\[\/b\]/\1<\/b>/g; - $text =~ s/\[color=(.*?)\](.*?)\[\/color\]/\2<\/span>/g; - - $LOGVIEW->add_paragraph ($color[$color], - join "\n", map "$time $_", split /\n/, $text); - - $STATUSBOX->add ($text, - group => $text, - fg => $color[$color], - timeout => 10, - tooltip_font => $::FONT_FIXED, - ); -} - -sub conn::drawextinfo { - my ($self, $color, $type, $subtype, $message) = @_; - - $self->drawinfo ($color, $message); -} - -sub conn::spell_add { - my ($self, $spell) = @_; - - # TODO - # create a widget dynamically, using spell face (CF::Protocol downloads them) - $MAPWIDGET->add_command ("invoke $spell->{name}", CFClient::UI::Label::escape $spell->{message}); - $MAPWIDGET->add_command ("cast $spell->{name}", CFClient::UI::Label::escape $spell->{message}); -} - -sub conn::spell_delete { - my ($self, $spell) = @_; -} - -sub conn::addme_success { - my ($self) = @_; - - $self->send ("command output-sync $CFG->{output_sync}"); - $self->send ("command output-count $CFG->{output_count}"); - - my $parser = new Pod::POM; - my $pod = $parser->parse_file (CFClient::find_rcfile "pod/skill_help.pod"); - - my %skill_tooltip; - - for my $head2 ($pod->head2) { - $skill_tooltip{$head2->title} = CFClient::pod_to_pango $head2->content; - } - - for my $skill (values %{$self->{skill_info}}) { - $MAPWIDGET->add_command ("ready_skill $skill", - (CFClient::UI::Label::escape "Ready the skill '$skill'\n\n") - . $skill_tooltip{$skill}); - $MAPWIDGET->add_command ("use_skill $skill", - (CFClient::UI::Label::escape "Immediately use the skill '$skill'\n\n") - . $skill_tooltip{$skill}); - } -} - -sub conn::eof { - $MAPWIDGET->clr_commands; - - stop_game; -} - -sub conn::image_info { - my ($self, $numfaces) = @_; - - $self->{num_faces} = $numfaces; - $self->{face_prefetch} = [1 .. $numfaces]; - $self->face_prefetch; -} - -sub conn::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"); - - $STATUSBOX->add (CFClient::UI::Label::escape "prefetching $todo", - group => "prefetch", timeout => 2, fg => [1, 1, 0, 0.5]); - } elsif (!exists $self->{num_faces}) { - $self->send ("requestinfo image_info"); - - $self->{num_faces} = 0; - - $STATUSBOX->add (CFClient::UI::Label::escape "starting to prefetch", - group => "prefetch", timeout => 2, fg => [1, 1, 0, 0.5]); - } -} - # check once/second for faces that need to be prefetched # this should, of course, only run on demand, but # SDL forces worse things on us.... @@ -1740,123 +1276,6 @@ if $CONN; }); -sub update_floorbox { - $CFClient::UI::ROOT->on_refresh ($FLOORBOX => sub { - return unless $CONN; - - $FLOORBOX->clear; - $FLOORBOX->add (0, 1, new CFClient::UI::Empty expand => 1); - - my $row; - for (@{ $CONN->{container}{0} }) { - if (++$row < 7) { - local $_->{face_widget}; # hack to force recreation of widget - local $_->{desc_widget}; # hack to force recreation of widget - CFClient::Item::update_widgets $_; - - $FLOORBOX->add (0, $row, $_->{face_widget}); - $FLOORBOX->add (1, $row, $_->{desc_widget}); - } else { - $FLOORBOX->add (new CFClient::UI::Label text => "More..."); - last; - } - } - }); - - $WANT_REFRESH++; -} - -sub conn::container_add { - my ($self, $tag, $items) = @_; - - #d# print "container_add: container $tag ($self->{player}{tag})\n"; - - if ($tag == 0) { - update_floorbox; - $OPENCONT = 0; - $INVR_LBL->set_text ("Floor"); - $INVR->set_items ($self->{container}{0}); - } elsif ($tag == $self->{player}{tag}) { - $INVR_LBL->set_text ("Player"); - $INV->set_items ($self->{container}{$self->{player}{tag}}) - } else { - $OPENCONT = $tag; - $INVR_LBL->set_text (CFClient::UI::InventoryItem::_item_to_desc ($self->{item}->{$OPENCONT})); - $INVR->set_items ($self->{container}{$tag}); - } - - # $self-<{player}{tag} => player inv - #use PApp::Util; warn PApp::Util::dumpval $self->{container}{$self->{player}{tag}}; -} - -sub conn::container_clear { - my ($self, $tag) = @_; - - #d# print "container_clear: container $tag ($self->{player}{tag})\n"; - - if ($tag == 0) { - update_floorbox; - $OPENCONT = 0; - $INVR_LBL->set_text ("Floor"); - $INVR->set_items ($self->{container}{0}); - } elsif ($tag == $self->{player}{tag}) { - $INVR_LBL->set_text ("Player"); - $INV->set_items ($self->{container}{$tag}) - } else { - $OPENCONT = $tag; - $INVR_LBL->set_text (CFClient::UI::InventoryItem::_item_to_desc ($self->{item}->{$OPENCONT})); - $INVR->set_items ($self->{container}{$tag}); - } - -# use PApp::Util; warn PApp::Util::dumpval $self->{container}{0}; -} - -sub conn::item_delete { - my ($self, @items) = @_; - - for (@items) { - #d# print "item_delete: $_->{tag} from $_->{container} ($self->{player}{tag})\n"; - - if ($_->{container} == 0) { - update_floorbox; - $OPENCONT = 0; - $INVR_LBL->set_text ("Floor"); - $INVR->set_items ($self->{container}{0}); - } elsif ($_->{container} == $self->{player}{tag}) { - $INVR_LBL->set_text ("Player"); - $INV->set_items ($self->{container}{$self->{player}{tag}}) - } else { - $OPENCONT = $_->{container}; - $INVR_LBL->set_text (CFClient::UI::InventoryItem::_item_to_desc ($self->{item}->{$OPENCONT})); - $INVR->set_items ($self->{container}{$_->{container}}); - } - } -} - -sub conn::item_update { - my ($self, $item) = @_; - - #d# print "item_update: $item->{tag} in $item->{container} ($self->{player}{tag}) ($OPENCONT)\n"; - - if ($item->{tag} == $OPENCONT && not ($item->{flags} & Crossfire::Protocol::F_OPEN)) { - $OPENCONT = 0; - $INVR_LBL->set_text ("Floor"); - $INVR->set_items ($self->{container}{0}); - - $item->{widget}->update_item - if $item->{widget}; - } else { - if ($item->{container} == 0) { - update_floorbox; - $OPENCONT = 0; - $INVR_LBL->set_text ("Floor"); - $INVR->set_items ($self->{container}{0}); - } elsif ($item->{container} == $self->{player}{tag}) { - $INV->set_items ($self->{container}{$item->{container}}) - } - } -} - %SDL_CB = ( CFClient::SDL_QUIT => sub { Event::unloop -1; @@ -1901,9 +1320,6 @@ CFClient::read_cfg "$Crossfire::VARDIR/pclientrc"; - $TILECACHE = CFClient::db_table "tilecache"; - $FACEMAP = CFClient::db_table "facemap"; - my %DEF_CFG = ( sdl_mode => 0, width => 640,