Deliantra-Client

 view release on metacpan or  search on metacpan

DC/Protocol.pm  view on Meta::CPAN

      0
   });

   $self->update_server_info;

   $self->send_command ("output-rate $::CFG->{output_rate}") if $::CFG->{output_rate} > 0;
   $self->send_pickup ($::CFG->{pickup});
}

sub lookat {
   my ($self, $x, $y) = @_;

   if ($self->{cfplus_ext}) {
      $self->send_ext_req (lookat => $x, $y, sub {
         my (%msg) = @_;

         if (exists $msg{npc_dialog}) {
            # start npc chat dialog
            $self->{npc_dialog} = new DC::NPCDialog::
               token => $msg{npc_dialog},
               title => "$msg{npc_dialog}[0] (NPC)",
               conn  => $self,
            ;
         }
      });
   }

   $self->send ("lookat $x $y");
}

sub destroy {
   my ($self) = @_;

   (delete $self->{npc_dialog})->destroy
      if $self->{npc_dialog};

   $self->SUPER::destroy;

   %$self = ();
}

package DC::NPCDialog;

our @ISA = 'DC::UI::Toplevel';

sub new {
   my $class = shift;

   my $self = $class->SUPER::new (
      x       => 'center',
      y       => 'center',
      name    => "npc_dialog",
      force_w => $::WIDTH * 0.7,
      force_h => $::HEIGHT * 0.7,
      title   => "NPC Dialog",
      kw      => { hi => 0, yes => 0, no => 0 },
      has_close_button => 1,
      @_,
   );

   DC::weaken (my $this = $self);

   $self->connect (delete => sub { $this->destroy; 1 });

   # better use a pane...
   $self->add (my $hbox = new DC::UI::HBox);
   $hbox->add ($self->{textview} = new DC::UI::TextScroller expand => 1);

   $hbox->add (my $vbox = new DC::UI::VBox);

   $vbox->add (new DC::UI::Label text => "Message Entry:");
   $vbox->add ($self->{entry} = new DC::UI::Entry
      tooltip     => "#npc_message_entry",
      on_activate => sub {
         my ($entry, $text) = @_;

         return unless $text =~ /\S/;

         $entry->set_text ("");
         $this->send ($text);

         0
      },
   );

   $vbox->add ($self->{options} = new DC::UI::VBox);

   $self->{bye_button} = new DC::UI::Button
      text        => "Bye (close)",
      tooltip     => "Use this button to end talking to the NPC. This also closes the dialog window.",
      on_activate => sub { $this->destroy; 1 },
   ;

   $self->update_options;

   $self->{id} = "npc-channel-" . $self->{conn}->token;
   $self->{conn}->connect_ext ($self->{id} => sub {
      $this->feed (@_) if $this;
   });

   $self->{conn}->send_ext_msg (npc_dialog_begin => $self->{id}, $self->{token});

   $self->{entry}->grab_focus;

   $self->{textview}->add_paragraph ({
      fg     => [1, 1, 0, 1],
      markup => "<small>[starting conversation with <b>$self->{title}</b>]</small>\n\n",
   });

   $self->show;
   $self
};

sub update_options {
   my ($self) = @_;

   DC::weaken $self;

   $self->{options}->clear;
   $self->{options}->add ($self->{bye_button});

   for my $kw (sort keys %{ $self->{kw} }) {
      $self->{options}->add (new DC::UI::Button
         text => $kw,
         on_activate => sub {
            $self->send ($kw);
            0
         },
      );
   }
}

sub feed {
   my ($self, $type, @arg) = @_;

   DC::weaken $self;

   if ($type eq "update") {
      my (%info) = @arg;

      $self->{kw}{$_} = 1 for @{$info{add_topics} || []};
      $self->{kw}{$_} = 0 for @{$info{del_topics} || []};
      
      if (exists $info{msg}) {
         my $text = "\n" . DC::Protocol::sanitise_xml $info{msg};
         my $match = join "|", map "\\b\Q$_\E\\b", sort { (length $b) <=> (length $a) } keys %{ $self->{kw} };
         my @link;
         $text =~ s{
            ($match)
         }{
            my $kw = $1;

            push @link, new DC::UI::Label
               markup     => "<span foreground='#c0c0ff' underline='single'>$kw</span>",
               can_hover  => 1,
               can_events => 1,
               padding_x  => 0,
               padding_y  => 0,
               on_button_up => sub {
                  $self->send ($kw);
               };

            "\x{fffc}"
         }giex;
         
         $self->{textview}->add_paragraph ({ markup => $text, widget => \@link });
         $self->{textview}->scroll_to_bottom;
      }

      $self->update_options;
   } else {
      $self->destroy;
   }

   1
}

sub send {
   my ($self, $msg) = @_;

   $self->{textview}->add_paragraph ({
      markup =>
         "\n<span foreground='#ffff00'><b>"
         . (DC::asxml $msg)
         . "</b></span>"
   });
   $self->{textview}->scroll_to_bottom;

   $self->{conn}->send_ext_msg (npc_dialog_tell => $self->{id}, $msg);
}

sub destroy {
   my ($self) = @_;

   #Carp::cluck "debug\n";#d# #todo# enable: destroy gets called twice because scalar keys {} is 1



( run in 0.536 second using v1.01-cache-2.11-cpan-39bf76dae61 )