… | |
… | |
7 | use Deliantra::Protocol::Constants; |
7 | use Deliantra::Protocol::Constants; |
8 | |
8 | |
9 | use DC; |
9 | use DC; |
10 | use DC::DB; |
10 | use DC::DB; |
11 | use DC::UI; |
11 | use DC::UI; |
12 | use DC::Pod; |
|
|
13 | use DC::Macro; |
12 | use DC::Macro; |
14 | use DC::Item; |
13 | use DC::Item; |
15 | |
14 | |
16 | use base 'Deliantra::Protocol::Base'; |
15 | use base 'Deliantra::Protocol::Base'; |
17 | |
16 | |
… | |
… | |
627 | # progress |
626 | # progress |
628 | (new DC::UI::ExperienceProgress), |
627 | (new DC::UI::ExperienceProgress), |
629 | |
628 | |
630 | # label |
629 | # label |
631 | (new DC::UI::Label text => $name, on_button_down => $spell_cb, align => 0, |
630 | (new DC::UI::Label text => $name, on_button_down => $spell_cb, align => 0, |
632 | can_events => 1, can_hover => 1, tooltip => (DC::Pod::section_label skill_description => $name) . $TOOLTIP_ALL), |
631 | can_events => 1, can_hover => 1, tooltip => "#(skill/$name)$TOOLTIP_ALL"), |
633 | ]; |
632 | ]; |
634 | |
633 | |
635 | push @add, |
634 | push @add, |
636 | $x * 4 + 0, $y, $sw->[0], |
635 | $x * 4 + 0, $y, $sw->[0], |
637 | $x * 4 + 1, $y, $sw->[1], |
636 | $x * 4 + 1, $y, $sw->[1], |
… | |
… | |
1058 | |
1057 | |
1059 | $prompt = $LAST_QUERY unless length $prompt; |
1058 | $prompt = $LAST_QUERY unless length $prompt; |
1060 | $LAST_QUERY = $prompt; |
1059 | $LAST_QUERY = $prompt; |
1061 | |
1060 | |
1062 | $self->{query}->($self, $flags, $prompt); |
1061 | $self->{query}->($self, $flags, $prompt); |
1063 | } |
|
|
1064 | |
|
|
1065 | sub sanitise_xml($) { |
|
|
1066 | local $_ = shift; |
|
|
1067 | |
|
|
1068 | # we now weed out all tags we do not support |
|
|
1069 | s{ <(?! /?i> | /?u> | /?b> | /?big | /?small | /?s | /?tt | fg\ | /fg>) |
|
|
1070 | }{ |
|
|
1071 | "<" |
|
|
1072 | }gex; |
|
|
1073 | |
|
|
1074 | # now all entities |
|
|
1075 | s/&(?!amp;|lt;|gt;|apos;|quot;|#[0-9]+;|#x[0-9a-fA-F]+;)/&/g; |
|
|
1076 | |
|
|
1077 | # handle some elements |
|
|
1078 | s/<fg name='([^']*)'>(.*?)<\/fg>/<span foreground='$1'>$2<\/span>/gs; |
|
|
1079 | s/<fg name="([^"]*)">(.*?)<\/fg>/<span foreground="$1">$2<\/span>/gs; |
|
|
1080 | |
|
|
1081 | s/\s+$//; |
|
|
1082 | |
|
|
1083 | $_ |
|
|
1084 | } |
1062 | } |
1085 | |
1063 | |
1086 | our %NAME_TO_COLOR = ( |
1064 | our %NAME_TO_COLOR = ( |
1087 | black => 0, |
1065 | black => 0, |
1088 | white => 1, |
1066 | white => 1, |
… | |
… | |
1116 | ); |
1094 | ); |
1117 | |
1095 | |
1118 | sub msg { |
1096 | sub msg { |
1119 | my ($self, $color, $type, $text, @extra) = @_; |
1097 | my ($self, $color, $type, $text, @extra) = @_; |
1120 | |
1098 | |
1121 | $text = sanitise_xml $text; |
1099 | $text = DC::sanitise_cfxml $text; |
1122 | |
1100 | |
1123 | if (my $cb = $self->{cb_msg}{$type}) { |
1101 | if (my $cb = $self->{cb_msg}{$type}) { |
1124 | $_->($self, $color, $type, $text, @extra) for values %$cb; |
1102 | $_->($self, $color, $type, $text, @extra) for values %$cb; |
1125 | } elsif ($type =~ /^(?:chargen-race-title|chargen-race-description)$/) { |
1103 | } elsif ($type =~ /^(?:chargen-race-title|chargen-race-description)$/) { |
1126 | $type =~ s/-/_/g; |
1104 | $type =~ s/-/_/g; |
… | |
… | |
1155 | } |
1133 | } |
1156 | |
1134 | |
1157 | sub spell_add { |
1135 | sub spell_add { |
1158 | my ($self, $spell) = @_; |
1136 | my ($self, $spell) = @_; |
1159 | |
1137 | |
1160 | # try to create single paragraphs out of the multiple lines sent by the server |
|
|
1161 | $spell->{message} =~ s/(?<=\S)\n(?=\w)/ /g; |
|
|
1162 | $spell->{message} =~ s/\n+$//; |
|
|
1163 | $spell->{message} ||= "Server did not provide a description for this spell."; |
|
|
1164 | |
|
|
1165 | $::SPELL_LIST->add_spell ($spell); |
1138 | $::SPELL_LIST->add_spell ($spell); |
1166 | delete $::COMPLETER->{command_list}{spells}; |
1139 | delete $::COMPLETER->{command_list}{spells}; |
1167 | } |
1140 | } |
1168 | |
1141 | |
1169 | sub spell_delete { |
1142 | sub spell_delete { |
… | |
… | |
1176 | sub setup { |
1149 | sub setup { |
1177 | my ($self, $setup) = @_; |
1150 | my ($self, $setup) = @_; |
1178 | |
1151 | |
1179 | $self->{map_widget}->set_tilesize ($self->{tilesize}); |
1152 | $self->{map_widget}->set_tilesize ($self->{tilesize}); |
1180 | $::MAP->resize ($self->{mapw}, $self->{maph}); |
1153 | $::MAP->resize ($self->{mapw}, $self->{maph}); |
1181 | } |
|
|
1182 | |
|
|
1183 | sub addme_success { |
|
|
1184 | my ($self) = @_; |
|
|
1185 | |
|
|
1186 | my %skill_help; |
|
|
1187 | |
|
|
1188 | for my $node (DC::Pod::find skill_description => "*") { |
|
|
1189 | my (undef, @par) = DC::Pod::section_of $node; |
|
|
1190 | $skill_help{$node->[DC::Pod::N_KW][0]} = DC::Pod::as_label @par; |
|
|
1191 | }; |
|
|
1192 | |
|
|
1193 | for my $skill (values %{$self->{skill_info}}) { |
|
|
1194 | $self->{map_widget}->add_command ("ready_skill $skill", |
|
|
1195 | (DC::asxml "Ready the skill '$skill'\n\n") |
|
|
1196 | . $skill_help{$skill}); |
|
|
1197 | $self->{map_widget}->add_command ("use_skill $skill", |
|
|
1198 | (DC::asxml "Immediately use the skill '$skill'\n\n") |
|
|
1199 | . $skill_help{$skill}); |
|
|
1200 | } |
|
|
1201 | } |
1154 | } |
1202 | |
1155 | |
1203 | sub eof { |
1156 | sub eof { |
1204 | my ($self) = @_; |
1157 | my ($self) = @_; |
1205 | |
1158 | |
… | |
… | |
1532 | |
1485 | |
1533 | $self->{kw}{$_} = 1 for @{$info{add_topics} || []}; |
1486 | $self->{kw}{$_} = 1 for @{$info{add_topics} || []}; |
1534 | $self->{kw}{$_} = 0 for @{$info{del_topics} || []}; |
1487 | $self->{kw}{$_} = 0 for @{$info{del_topics} || []}; |
1535 | |
1488 | |
1536 | if (exists $info{msg}) { |
1489 | if (exists $info{msg}) { |
1537 | my $text = "\n" . DC::Protocol::sanitise_xml $info{msg}; |
1490 | my $text = "\n" . DC::sanitise_cfxml $info{msg}; |
1538 | my $match = join "|", map "\\b\Q$_\E\\b", sort { (length $b) <=> (length $a) } keys %{ $self->{kw} }; |
1491 | my $match = join "|", map "\\b\Q$_\E\\b", sort { (length $b) <=> (length $a) } keys %{ $self->{kw} }; |
1539 | my @link; |
1492 | my @link; |
1540 | $text =~ s{ |
1493 | $text =~ s{ |
1541 | ($match) |
1494 | ($match) |
1542 | }{ |
1495 | }{ |