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 )