ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/Protocol.pm
(Generate patch)

Comparing deliantra/Deliantra-Client/DC/Protocol.pm (file contents):
Revision 1.221 by root, Sun Nov 4 02:13:53 2012 UTC vs.
Revision 1.228 by root, Wed Nov 21 13:23:10 2012 UTC

7use Deliantra::Protocol::Constants; 7use Deliantra::Protocol::Constants;
8 8
9use DC; 9use DC;
10use DC::DB; 10use DC::DB;
11use DC::UI; 11use DC::UI;
12use DC::Pod;
13use DC::Macro; 12use DC::Macro;
14use DC::Item; 13use DC::Item;
15 14
16use base 'Deliantra::Protocol::Base'; 15use base 'Deliantra::Protocol::Base';
17 16
18our $TEX_DIALOGUE = new_from_resource DC::Texture 17our $TEX_DIALOGUE = new_from_resource DC::Texture
19 "dialogue.png", minify => 1, mipmap => 1; 18 "dialogue.png", minify => 1, mipmap => 1;
20 19
21our $TEX_NOFACE = new_from_resource DC::Texture 20our $TEX_NOFACE = new_from_resource DC::Texture
22 "noface.png", minify => 1, mipmap => 1, wrap => 1; 21 "noface.png", minify => 1, mipmap => 1, wrap => 1;
23 22
24sub MIN_TEXTURE_UNUSED() { 1 }#d# 23sub MIN_TEXTURE_UNUSED() { 1 }#d#
34 }, 33 },
35 ); 34 );
36 35
37 $self->update_fx_want; 36 $self->update_fx_want;
38 37
39 my $guard = $self->addme_guard; 38 my $exp_guard = $self->addme_guard;
39 my $skl_guard = $self->addme_guard;
40 my $spl_guard = $self->addme_guard;
40 $self->send_exti_req (resource => "exp_table", sub { 41 $self->send_exti_req (resource => qw(exp_table skill_info spell_paths), sub {
41 my ($idx) = @_; 42 my ($exp, $skl, $spl) = @_;
42 43
43 $self->register_face_handler ($idx, sub { 44 $self->register_face_handler ($exp, sub {
44 my ($face) = @_; 45 my ($face) = @_;
45 46
46 undef $guard; 47 undef $exp_guard;
47 $self->{exp_table} = $self->{json_coder}->decode (delete $face->{data}); 48 $self->{exp_table} = $self->{json_coder}->decode (delete $face->{data});
48 $_->() for values %{ $self->{on_exp_update} }; 49 $_->() for values %{ $self->{on_exp_update} };
49 }); 50 });
50 51
51 ()
52 });
53
54 my $guard = $self->addme_guard;
55 $self->send_exti_req (resource => "skill_info", sub {
56 my ($idx) = @_;
57
58 $self->register_face_handler ($idx, sub { 52 $self->register_face_handler ($skl, sub {
59 my ($face) = @_; 53 my ($face) = @_;
60 54
61 undef $guard; 55 undef $skl_guard;
62 my $info = $self->{json_coder}->decode (delete $face->{data}); 56 my $info = $self->{json_coder}->decode (delete $face->{data});
63 $self->{skill_info} = { map { CS_STAT_SKILLINFO + $_ => $info->[$_][0] } 0 .. $#$info }; 57 $self->{skill_info} = { map { CS_STAT_SKILLINFO + $_ => $info->[$_][0] } 0 .. $#$info };
64 }); 58 });
65 59
66 ()
67 });
68
69 my $guard = $self->addme_guard;
70 $self->send_exti_req (resource => "spell_paths", sub {
71 my ($idx) = @_;
72
73 $self->register_face_handler ($idx, sub { 60 $self->register_face_handler ($spl, sub {
74 my ($face) = @_; 61 my ($face) = @_;
75 62
76 undef $guard; 63 undef $spl_guard;
77 my $info = $self->{json_coder}->decode (delete $face->{data}); 64 my $info = $self->{json_coder}->decode (delete $face->{data});
78 $self->{spell_paths} = { map { (1 << $_) => $info->[$_][0] } 0 .. $#$info }; 65 $self->{spell_paths} = { map { (1 << $_) => $info->[$_][0] } 0 .. $#$info };
79 }); 66 });
80 67
81 () 68 ()
82 }); 69 });
83 70
84 $self->{map_widget}->clr_commands; 71 $::COMPLETER->reset;
85
86 my @cmd_help = map {
87 $_->[DC::Pod::N_KW][0] =~ /^(\S+) (?:\s+ \( ([^\)]*) \) )?/x
88 or die "unparseable command help: $_->[DC::Pod::N_KW][0]";
89
90 my $cmd = $1;
91 my @args = split /\|/, $2;
92 @args = (".*") unless @args;
93
94 my (undef, @par) = DC::Pod::section_of $_;
95 my $text = DC::Pod::as_label @par;
96
97 $_ = $_ eq ".*" ? "" : " $_"
98 for @args;
99
100 map ["$cmd$_", $text],
101 sort { (length $a) <=> (length $b) }
102 @args
103 } sort { $a->[DC::Pod::N_PAR] <=> $b->[DC::Pod::N_PAR] }
104 DC::Pod::find command => "*";
105 72
106 $self->{json_coder} 73 $self->{json_coder}
107 ->convert_blessed 74 ->convert_blessed
108 ->filter_json_single_key_object ("\fw" => sub { 75 ->filter_json_single_key_object ("\fw" => sub {
109 $self->{widget}{$_[0]} 76 $self->{widget}{$_[0]}
126 $::INV->clear; 93 $::INV->clear;
127 $::INVR->clear; 94 $::INVR->clear;
128 $::INVR_HB->clear; 95 $::INVR_HB->clear;
129 $::FLOORBOX->clear; 96 $::FLOORBOX->clear;
130 }); 97 });
131
132 $self->{map_widget}->add_command (@$_)
133 for @cmd_help;
134 98
135 { 99 {
136 $self->{dialogue} = my $tex = $TEX_DIALOGUE; 100 $self->{dialogue} = my $tex = $TEX_DIALOGUE;
137 $self->{map}->set_texture (1, @$tex{qw(name w h s t)}, @{$tex->{minified}}); 101 $self->{map}->set_texture (1, @$tex{qw(name w h s t)}, @{$tex->{minified}});
138 } 102 }
163 $self->{mapcache} = "mapcache_$self->{host}_$self->{port}"; 127 $self->{mapcache} = "mapcache_$self->{host}_$self->{port}";
164 128
165 $self 129 $self
166} 130}
167 131
132 #$self->send_exti_req (nickmon => 1, sub { use Data::Dump; ddx \@_ });#d#
133#sub ext_nicklist { shift; use Data::Dump; ddx \@_; } #d#
134
168sub update_fx_want { 135sub update_fx_want {
169 my ($self) = @_; 136 my ($self) = @_;
170 137
171 $self->send_exti_msg (fx_want => { 138 $self->send_exti_msg (fx_want => {
172 3 => !!$::CFG->{bgm_enable}, # FT_MUSIC 139 3 => !!$::CFG->{bgm_enable}, # FT_MUSIC
193} 160}
194 161
195sub ext_ambient_music { 162sub ext_ambient_music {
196 my ($self, $songs) = @_; 163 my ($self, $songs) = @_;
197 &::audio_music_set_ambient ($songs); 164 &::audio_music_set_ambient ($songs);
165}
166
167sub ext_command_list {
168 my ($self, @faces) = @_;
169
170 my $handler = $self->{command_facehandler} = {};
171 my $commands = $::COMPLETER->{command_list} = {};
172
173 for my $idx (@faces) {
174 $handler->{$idx} = $self->register_face_handler ($idx, sub {
175 my ($face) = @_;
176
177 $commands->{$idx} =
178 $face->{cache} ||= $self->{json_coder}->decode ($face->{data});
179 });
180 }
198} 181}
199 182
200############################################################################# 183#############################################################################
201 184
202sub widget_associate { 185sub widget_associate {
643 # progress 626 # progress
644 (new DC::UI::ExperienceProgress), 627 (new DC::UI::ExperienceProgress),
645 628
646 # label 629 # label
647 (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,
648 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"),
649 ]; 632 ];
650 633
651 push @add, 634 push @add,
652 $x * 4 + 0, $y, $sw->[0], 635 $x * 4 + 0, $y, $sw->[0],
653 $x * 4 + 1, $y, $sw->[1], 636 $x * 4 + 1, $y, $sw->[1],
1074 1057
1075 $prompt = $LAST_QUERY unless length $prompt; 1058 $prompt = $LAST_QUERY unless length $prompt;
1076 $LAST_QUERY = $prompt; 1059 $LAST_QUERY = $prompt;
1077 1060
1078 $self->{query}->($self, $flags, $prompt); 1061 $self->{query}->($self, $flags, $prompt);
1079}
1080
1081sub sanitise_xml($) {
1082 local $_ = shift;
1083
1084 # we now weed out all tags we do not support
1085 s{ <(?! /?i> | /?u> | /?b> | /?big | /?small | /?s | /?tt | fg\ | /fg>)
1086 }{
1087 "&lt;"
1088 }gex;
1089
1090 # now all entities
1091 s/&(?!amp;|lt;|gt;|apos;|quot;|#[0-9]+;|#x[0-9a-fA-F]+;)/&amp;/g;
1092
1093 # handle some elements
1094 s/<fg name='([^']*)'>(.*?)<\/fg>/<span foreground='$1'>$2<\/span>/gs;
1095 s/<fg name="([^"]*)">(.*?)<\/fg>/<span foreground="$1">$2<\/span>/gs;
1096
1097 s/\s+$//;
1098
1099 $_
1100} 1062}
1101 1063
1102our %NAME_TO_COLOR = ( 1064our %NAME_TO_COLOR = (
1103 black => 0, 1065 black => 0,
1104 white => 1, 1066 white => 1,
1115 tan => 12, 1077 tan => 12,
1116); 1078);
1117 1079
1118our @CF_COLOR = ( 1080our @CF_COLOR = (
1119 [1.00, 1.00, 1.00], #[0.00, 0.00, 0.00], 1081 [1.00, 1.00, 1.00], #[0.00, 0.00, 0.00],
1120 [1.00, 1.00, 1.00], 1082 [1.00, 1.00, 1.00], #[0.00, 0.00, 0.00],
1121 [0.50, 0.50, 1.00], #[0.00, 0.00, 0.55] 1083 [0.50, 0.50, 1.00], #[0.00, 0.00, 0.55],
1122 [1.00, 0.00, 0.00], 1084 [1.00, 0.00, 0.00],
1123 [1.00, 0.54, 0.00], 1085 [1.00, 0.54, 0.00],
1124 [0.11, 0.56, 1.00], 1086 [0.11, 0.56, 1.00],
1125 [0.93, 0.46, 0.00], 1087 [0.93, 0.46, 0.00],
1126 [0.18, 0.54, 0.34], 1088 [0.18, 0.54, 0.34],
1132); 1094);
1133 1095
1134sub msg { 1096sub msg {
1135 my ($self, $color, $type, $text, @extra) = @_; 1097 my ($self, $color, $type, $text, @extra) = @_;
1136 1098
1137 $text = sanitise_xml $text; 1099 $text = DC::sanitise_cfxml $text;
1138 1100
1139 if (my $cb = $self->{cb_msg}{$type}) { 1101 if (my $cb = $self->{cb_msg}{$type}) {
1140 $_->($self, $color, $type, $text, @extra) for values %$cb; 1102 $_->($self, $color, $type, $text, @extra) for values %$cb;
1141 } elsif ($type =~ /^(?:chargen-race-title|chargen-race-description)$/) { 1103 } elsif ($type =~ /^(?:chargen-race-title|chargen-race-description)$/) {
1142 $type =~ s/-/_/g; 1104 $type =~ s/-/_/g;
1171} 1133}
1172 1134
1173sub spell_add { 1135sub spell_add {
1174 my ($self, $spell) = @_; 1136 my ($self, $spell) = @_;
1175 1137
1176 # try to create single paragraphs out of the multiple lines sent by the server
1177 $spell->{message} =~ s/(?<=\S)\n(?=\w)/ /g;
1178 $spell->{message} =~ s/\n+$//;
1179 $spell->{message} ||= "Server did not provide a description for this spell.";
1180
1181 $::SPELL_LIST->add_spell ($spell); 1138 $::SPELL_LIST->add_spell ($spell);
1182 1139 delete $::COMPLETER->{command_list}{spells};
1183 $self->{map_widget}->add_command ("invoke $spell->{name}", DC::asxml $spell->{message});
1184 $self->{map_widget}->add_command ("cast $spell->{name}", DC::asxml $spell->{message});
1185} 1140}
1186 1141
1187sub spell_delete { 1142sub spell_delete {
1188 my ($self, $spell) = @_; 1143 my ($self, $spell) = @_;
1189 1144
1190 $::SPELL_LIST->remove_spell ($spell); 1145 $::SPELL_LIST->remove_spell ($spell);
1146 delete $::COMPLETER->{command_list}{spells};
1191} 1147}
1192 1148
1193sub setup { 1149sub setup {
1194 my ($self, $setup) = @_; 1150 my ($self, $setup) = @_;
1195 1151
1196 $self->{map_widget}->set_tilesize ($self->{tilesize}); 1152 $self->{map_widget}->set_tilesize ($self->{tilesize});
1197 $::MAP->resize ($self->{mapw}, $self->{maph}); 1153 $::MAP->resize ($self->{mapw}, $self->{maph});
1198} 1154}
1199 1155
1200sub addme_success {
1201 my ($self) = @_;
1202
1203 my %skill_help;
1204
1205 for my $node (DC::Pod::find skill_description => "*") {
1206 my (undef, @par) = DC::Pod::section_of $node;
1207 $skill_help{$node->[DC::Pod::N_KW][0]} = DC::Pod::as_label @par;
1208 };
1209
1210 for my $skill (values %{$self->{skill_info}}) {
1211 $self->{map_widget}->add_command ("ready_skill $skill",
1212 (DC::asxml "Ready the skill '$skill'\n\n")
1213 . $skill_help{$skill});
1214 $self->{map_widget}->add_command ("use_skill $skill",
1215 (DC::asxml "Immediately use the skill '$skill'\n\n")
1216 . $skill_help{$skill});
1217 }
1218}
1219
1220sub eof { 1156sub eof {
1221 my ($self) = @_; 1157 my ($self) = @_;
1222 1158
1223 $self->{map_widget}->clr_commands; 1159 $::COMPLETER->reset;
1224 1160
1225 ::stop_game (); 1161 ::stop_game ();
1226} 1162}
1227 1163
1228sub update_floorbox { 1164sub update_floorbox {
1549 1485
1550 $self->{kw}{$_} = 1 for @{$info{add_topics} || []}; 1486 $self->{kw}{$_} = 1 for @{$info{add_topics} || []};
1551 $self->{kw}{$_} = 0 for @{$info{del_topics} || []}; 1487 $self->{kw}{$_} = 0 for @{$info{del_topics} || []};
1552 1488
1553 if (exists $info{msg}) { 1489 if (exists $info{msg}) {
1554 my $text = "\n" . DC::Protocol::sanitise_xml $info{msg}; 1490 my $text = "\n" . DC::sanitise_cfxml $info{msg};
1555 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} };
1556 my @link; 1492 my @link;
1557 $text =~ s{ 1493 $text =~ s{
1558 ($match) 1494 ($match)
1559 }{ 1495 }{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines