ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/cfplus.ext
Revision: 1.8
Committed: Sun Jun 24 04:09:29 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.7: +1 -1 lines
Log Message:
first rough cut of msg rewriting, introducing cfpod, a haxored pod variant for crossfire messgaes. where will it end?

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