--- deliantra/Deliantra-Client/bin/pclient 2006/05/15 18:23:33 1.217 +++ deliantra/Deliantra-Client/bin/pclient 2006/05/17 20:52:12 1.227 @@ -3,6 +3,7 @@ use strict; use utf8; +# do things only needed for single-binary version (par) BEGIN { if (%PAR::LibCache) { @INC = grep ref, @INC; # weed out all paths except pars loader refs @@ -15,18 +16,18 @@ } } - unshift @INC, $ENV{PAR_TEMP}; + # TODO: pango-rc file, anybody? - if ($^O eq "MSWin32") { - $ENV{GTK_RC_FILES} = "$ENV{PAR_TEMP}/share/themes/MS-Windows/gtk-2.0/gtkrc"; - } + unshift @INC, $ENV{PAR_TEMP}; } } # need to do it again because that pile of garbage called PAR nukes it before main -unshift @INC, $ENV{PAR_TEMP}; +unshift @INC, $ENV{PAR_TEMP} + if %PAR::LibCache; use Time::HiRes 'time'; +use Pod::POM; use Event; use Crossfire; @@ -102,6 +103,7 @@ our $INVWIN; our $INV; our $INVR; +our $INVR_LBL; our $OPENCONT; sub status { @@ -136,11 +138,14 @@ }; if ($CONN) { - $LOGIN_BUTTON->set_text ("Logout"); + CFClient::lowdelay fileno $CONN->{fh}; + $LOGIN_BUTTON->set_text ("Logout"); status "login successful"; - CFClient::lowdelay fileno $CONN->{fh}; + $BUTTONBAR->{children}[1]->emit ("activate") + if $BUTTONBAR->{children}[1]->{state}; + } else { status "unable to connect"; stop_game(); @@ -155,6 +160,9 @@ $CONN->destroy; $CONN = 0; # false, does not autovivify + $BUTTONBAR->{children}[1]->emit ("activate") + unless $BUTTONBAR->{children}[1]->{state}; + undef $MAPCACHE; undef $MAP; } @@ -667,7 +675,8 @@ (new CFClient::UI::Empty expand => 1), ]); - $table->add ($_ + 1, $y, new CFClient::UI::Label align => $align[$_], text => $m->[$_], fontsize => 0.8) + $table->add ($_ + 1, $y, new CFClient::UI::Label + ellipsise => 0, align => $align[$_], text => $m->[$_], fontsize => 0.8) for 0 .. $#$m; } } @@ -743,7 +752,21 @@ }, ); - $table->add (1, 8, $LOGIN_BUTTON = new CFClient::UI::Button + $table->add (0, 8, new CFClient::UI::Label valign => 0, align => 1, text => "Output-Count"); + $table->add (1, 8, new CFClient::UI::Entry + text => $CFG->{output_count}, + tooltip => "Should be set to 1 unless you know what you are doing", + connect_changed => sub { $CFG->{output_count} = $_[1] }, + ); + + $table->add (0, 9, new CFClient::UI::Label valign => 0, align => 1, text => "Output-Sync"); + $table->add (1, 9, new CFClient::UI::Entry + text => $CFG->{output_sync}, + tooltip => "Should be set to 1 unless you know what you are doing", + connect_changed => sub { $CFG->{output_sync} = $_[1] }, + ); + + $table->add (1, 10, $LOGIN_BUTTON = new CFClient::UI::Button expand => 1, align => 0, text => "Login", @@ -815,8 +838,16 @@ user_w => $WIDTH * (4/5), user_h => $HEIGHT * (4/5), title => "Inventory"; $invwin->add (my $hb = new CFClient::UI::HBox); - $hb->add ($INV = new CFClient::UI::Inventory expand => 1); - $hb->add ($INVR = new CFClient::UI::Inventory expand => 1); + + $hb->add (my $vb1 = new CFClient::UI::VBox expand => 1); + $vb1->add (my $lbl = new CFClient::UI::Label); + $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); + $INVR_LBL->set_text ("Floor"); + $vb2->add ($INVR = new CFClient::UI::Inventory expand => 1); $invwin } @@ -926,7 +957,7 @@ sub audio_channel_finished { my ($channel) = @_; - warn "channel $channel finished\n";#d# + #warn "channel $channel finished\n";#d# } sub audio_music_finished { @@ -1022,9 +1053,46 @@ @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 +} + 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); } @@ -1332,7 +1400,7 @@ my $time = sprintf "%02d:%02d:%02d", (localtime time)[2,1,0]; - $text =~ s/&/&/g; $text =~ s/\1<\/b>/g; $text =~ s/\[color=(.*?)\](.*?)\[\/color\]/\2<\/span>/g; @@ -1358,8 +1426,8 @@ # TODO # create a widget dynamically, using spell face (CF::Protocol downloads them) - $MAPWIDGET->add_command ("invoke $spell->{name}", $spell->{message}); - $MAPWIDGET->add_command ("cast $spell->{name}", $spell->{message}); + $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 { @@ -1369,18 +1437,18 @@ sub conn::addme_success { my ($self) = @_; + $self->send ("command output-sync $CFG->{output_sync}"); + $self->send ("command output-count $CFG->{output_count}"); + for my $skill (values %{$self->{skill_info}}) { - $MAPWIDGET->add_command ("ready_skill $skill", "Ready the skill '$skill'"); - $MAPWIDGET->add_command ("use_skill $skill", "Immediately use the skill '$skill'"); + $MAPWIDGET->add_command ("ready_skill $skill", CFClient::UI::Label::escape "Ready the skill '$skill'"); + $MAPWIDGET->add_command ("use_skill $skill", CFClient::UI::Label::escape "Immediately use the skill '$skill'"); } - - $MAPWIDGET->add_command ("pet\\_mode defend", "Tell pets to stay close to you and defend you"); - $MAPWIDGET->add_command ("pet\\_mode arena", "Same as petmode attack, but also attack other players"); - $MAPWIDGET->add_command ("pet\\_mode sad", "Search & Destroy - tell pets to roam about and attack enemies"); - $MAPWIDGET->add_command ("kill\\_pets", "kill your pets"); } sub conn::eof { + $MAPWIDGET->clr_commands; + stop_game; } @@ -1408,16 +1476,19 @@ sub conn::container_add { my ($self, $tag, $items) = @_; - print "container_add on conainer $tag (player: $self->{player}{tag})\n"; + #d# print "container_add: container $tag ($self->{player}{tag})\n"; if ($tag == 0) { update_floorbox; - $INVR->set_items ($self->{container}{0}); $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}); } @@ -1428,17 +1499,20 @@ sub conn::container_clear { my ($self, $tag) = @_; - print "container_clear on conainer $tag (player: $self->{player}{tag})\n"; + #d# print "container_clear: container $tag ($self->{player}{tag})\n"; if ($tag == 0) { update_floorbox; - $INVR->set_items ($self->{container}{0}); $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 { - $INVR->set_items ($self->{container}{$tag}); $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}; @@ -1448,14 +1522,20 @@ my ($self, @items) = @_; for (@items) { - print "item_delete on container $_->{container} (player: $self->{player}{tag})\n"; + #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 { - $INVR->set_items ($self->{container}{0}); + $OPENCONT = $_->{container}; + $INVR_LBL->set_text (CFClient::UI::InventoryItem::_item_to_desc ($self->{item}->{$OPENCONT})); + $INVR->set_items ($self->{container}{$_->{container}}); } } } @@ -1463,13 +1543,24 @@ sub conn::item_update { my ($self, $item) = @_; - print "item_update: container: $item->{container} (player: $self->{player}{tag})\n"; + #d# print "item_update: $item->{tag} in $item->{container} ($self->{player}{tag}) ($OPENCONT)\n"; - if ($item->{container} == 0) { - update_floorbox; + if ($item->{tag} == $OPENCONT && not ($item->{flags} & Crossfire::Protocol::F_OPEN)) { + $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}}) + + $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}}) + } } } @@ -1541,6 +1632,8 @@ audio_enable => 1, bgm_enable => 1, bgm_volume => 0.25, + output_sync => 1, + output_count => 1, ); while (my ($k, $v) = each %DEF_CFG) { @@ -1579,6 +1672,19 @@ $FONT_PROP->make_default; } +# compare mono (ft) vs. rgba (cairo) +# ft - 1.8s, cairo 3s, even in alpha-only mode +# for my $rgba (0..1) { +# my $t1 = Time::HiRes::time; +# for (1..1000) { +# my $layout = CFClient::Layout->new ($rgba); +# $layout->set_text ("hallo" x 100); +# $layout->render; +# } +# my $t2 = Time::HiRes::time; +# warn $t2-$t1; +# } + video_init; audio_init; } @@ -1642,10 +1748,14 @@ name, such as I and I. You can abbreviate commands by typing only the first character of every -word. For example, typing I will likely select I, while I will select I. Likewise, I -will likely select I and I will give you -I. +word (or even characters within the word - the client will try to make +a good guess, as long as the characters are in order). For example, +typing I will likely select I, while I +will select I. Likewise, I will likely select +I and I will give you I. + +You can enter space and other text as arguemnt to the command. For +example, C will expand to C. =head2 The map overview