ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/cfplus.ext
Revision: 1.6
Committed: Tue Jun 19 17:32:56 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.5: +1 -1 lines
Log Message:
fix some dialog bugs (by elmex)

File Contents

# Content
1 #! perl
2
3 # additional support for cfplus client
4
5 use NPC_Dialogue;
6
7 =head1 CF+ protocol extensions
8
9 This module implements protocol extensions for use by the CF+ client, but
10 can be used by other clients as well. It uses the C<extcmd> mechanism
11 exclusively.
12
13 =over 4
14
15 =item ... = extcmd cfplus_support { version => $client_version }
16
17 Registers the client the the server. the client should send the highest
18 version of the protocol it supports itself, and the server returns the
19 highest version of the protocol it supports in the C<version> key itself.
20
21 =cut
22
23 cf::register_extcmd cfplus_support => sub {
24 my ($pl, $msg) = @_;
25
26 # $msg->{version}
27
28 (
29 version => 2,
30 )
31 };
32
33 sub dialog_tell {
34 my ($id, $dialog, $msg) = @_;
35
36 my $pl = $dialog->{pl};
37 my ($reply, @kw) = $dialog->tell ($msg);
38 $reply = "..." unless $reply;
39
40 $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw);
41 }
42
43 =item ... = extcmd lookat { dx => $dx, dy => $dy }
44
45 "Looks at" the mapspace displaced (dx|dy) relative to the player
46 and returns "interesting" information about it.
47
48 Keys it can return include:
49
50 npc_dialog => $name
51 There is an npc or other object that can "talk" to the player.
52
53 =cut
54
55 cf::register_extcmd lookat => sub {
56 my ($pl, $msg) = @_;
57 my ($dx, $dy) = @$msg{qw(dx dy)};
58
59 return unless $pl->ob && $pl->ob->map;
60
61 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
62
63 my %res;
64
65 if ($pl->cell_visible ($dx, $dy)) {
66 for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
67 $res{npc_dialog} = $ob->name
68 if $near && NPC_Dialogue::has_dialogue $ob && !$pl->{npc_dialog};
69 }
70 }
71
72 %res
73 };
74
75 =item ... = extcmd npc_dialog_begin { msgid => $id, dx => $dx, dy => $dy }
76
77 Tries to start a dialogue with the mapspace specified by $dx and $dy (see
78 C<extcmd lookat>). The $msgid will be used as a handle for all future
79 messages related to this dialog interaction.
80
81 It either replies with an error reply or starts a dialog by telling
82 the npc "hi" and returning a reply structure as with C<extcmd
83 npc_dialog_tell>.
84
85 =cut
86
87 cf::register_extcmd npc_dialog_begin => sub {
88 my ($pl, $msg) = @_;
89 my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)};
90
91 return unless $pl->ob && $pl->ob->map;
92 return unless (abs $dx) <= 2 && (abs $dy) <= 2;
93 return unless $pl->cell_visible ($dx, $dy);
94 return if $pl->{npc_dialog}; # only one dialog at a time
95
96 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
97 if (NPC_Dialogue::has_dialogue $npc) {
98 $pl->attach ("npc_dialog_active");
99 $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id;
100 dialog_tell $id, $pl->{npc_dialog}, "hi";
101 return;
102 }
103 }
104
105 (msgtype => "error", msg => "nothing to talk to found")
106 };
107
108 =item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text }
109
110 Tells the NPC the given $text message and returns a reply structure which
111 can have the following keys:
112
113 msgtype => "reply"
114 msg => $reply_text,
115 add_topics => [additional topic strings]
116 del_topics => [invalidated topic strings]
117
118 =cut
119
120 cf::register_extcmd npc_dialog_tell => sub {
121 my ($pl, $msg) = @_;
122
123 if (my $dialog = $pl->{npc_dialog}) {
124 dialog_tell $msg->{msgid}, $dialog, $msg->{msg};
125 }
126
127 ()
128 };
129
130 =item extcmd npc_dialog_end { msgid => $id }
131
132 Finishes the dialog, invalidating the handle.
133
134 =cut
135
136 cf::register_extcmd npc_dialog_end => sub {
137 my ($pl, $msg) = @_;
138
139 if (my $dialog = delete $pl->{npc_dialog}) {
140 $pl->detach ("ncpa_dialog_active");
141 }
142
143 ()
144 };
145
146 =item ... = extcmd editor_support
147
148 Returns the value required by clients that have an editor to download and
149 upload maps from/to the server.
150
151 servertype => (game|test) type of this server
152 gameserver => the hostname:port of the normal game server
153 testserver => the hostname:port of the test server the maps can be tested on
154 cvs_root => the (http) url where the cvs root for downloading is located
155 lib_root => the (http) url where crossfire.0 and archetypes can be found
156 upload => the (http) url where clients can upload maps
157
158 If those values are not supplied or empty strings, the server does not
159 support downloading, uploading, testing, respectively.
160
161 The upload script expects the following values in a multipart form upload:
162
163 client: a descriptive string describing the editor and version used to upload
164 path: absolute server-side map path beginning with /
165 map: the map file itself
166 mapdir: the cvs root url originally used to download the map
167 revision: cvs-revision originally used to download the map
168 comment: a comment supplied by the user that documents the changes
169 cf_login: crossfire server login
170 cf_password: crossfire server password, optionally used for authentication purposes
171
172 =cut
173
174 cf::register_extcmd editor_support => sub {
175 my ($pl, $msg) = @_;
176
177 map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui)
178 };
179
180 sub unload {
181 for my $pl (cf::player::list) {
182 if (my $dialog = delete $pl->{npc_dialog}) {
183 $pl->detach ("npc_dialog_active");
184 $pl->ext_reply ($dialog->{id} => msgtype => "error", msg => "npc dialogue module was reloaded");
185 }
186 }
187 }
188
189 cf::player::attachment npc_dialog_active =>
190 on_logout => sub {
191 my ($pl) = @_;
192
193 delete $pl->{npc_dialog};
194 $pl->detach ("npc_dialog_active");
195 },
196 on_move => sub {
197 my ($pl, $dir) = @_;
198
199 if (my $dialog = $pl->{npc_dialog}) {
200 warn "on_move<@_>\n";#d#
201 warn $pl->ob;
202 warn $dialog;
203 warn $dialog->{npc};
204 warn $dialog->{npc}->is_valid;
205
206 my (undef, $dx, $dy) = $pl->ob->rangevector ($dialog->{npc});
207
208 return if (abs $dx) <= 2 && (abs $dy) <= 2;
209
210 $pl->ext_reply ($dialog->{id} => msgtype => "error", msg => "out of range");
211 }
212
213 delete $pl->{npc_dialog};
214 $pl->detach ("npc_dialog_active");
215 },
216 ;
217
218 cf::player->attach (
219 on_login => sub {
220 my ($pl) = @_;
221
222 delete $pl->{npc_dialog};
223 },
224 );
225
226 =back
227
228 =cut
229