ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/cfplus.ext
Revision: 1.17
Committed: Sun Apr 11 04:52:07 2010 UTC (14 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-3_1, rel-3_0, HEAD
Changes since 1.16: +1 -1 lines
Log Message:
prefer AE functions over EV functions#

File Contents

# User Rev Content
1 root 1.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 root 1.9 my ($pl, %msg) = @_;
25 root 1.1
26 root 1.9 $pl->ns->{cfplus_ext} = $msg{version};
27 root 1.1
28 root 1.9 (version => $msg{version} >= 2 ? 2 : 0)
29 root 1.1 };
30    
31     sub dialog_tell {
32     my ($id, $dialog, $msg) = @_;
33    
34 root 1.5 my $pl = $dialog->{pl};
35 root 1.1 my ($reply, @kw) = $dialog->tell ($msg);
36 elmex 1.7
37     $reply = "..." unless defined $reply;
38 root 1.1
39 root 1.9 $pl->ext_msg ($id, update => msg => $pl->expand_cfpod ($reply), add_topics => \@kw)
40     if $reply ne ""; # NPC might not want to say, or wants to say something later
41 root 1.1 }
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 root 1.9 my ($pl, $dx, $dy) = @_;
57 root 1.1
58 root 1.2 return unless $pl->ob && $pl->ob->map;
59    
60 root 1.1 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
61    
62     my %res;
63    
64     if ($pl->cell_visible ($dx, $dy)) {
65     for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
66 root 1.9 $res{npc_dialog} = [$ob->name, $dx, $dy]
67 root 1.12 if $near && $ob->has_dialogue && !$pl->{npc_dialog};
68 root 1.1 }
69     }
70    
71     %res
72     };
73    
74     =item ... = extcmd npc_dialog_begin { msgid => $id, dx => $dx, dy => $dy }
75    
76     Tries to start a dialogue with the mapspace specified by $dx and $dy (see
77     C<extcmd lookat>). The $msgid will be used as a handle for all future
78     messages related to this dialog interaction.
79    
80     It either replies with an error reply or starts a dialog by telling
81 root 1.5 the npc "hi" and returning a reply structure as with C<extcmd
82 root 1.1 npc_dialog_tell>.
83    
84     =cut
85    
86     cf::register_extcmd npc_dialog_begin => sub {
87 root 1.9 my ($pl, $id, $token) = @_;
88    
89     #TODO:
90 root 1.14 # this is not a request, so returning does no good: make it a request and die on error
91 root 1.1
92 root 1.2 return unless $pl->ob && $pl->ob->map;
93 root 1.9
94     my ($name, $dx, $dy) = @$token;
95    
96     return (error => "too far away") unless (abs $dx) <= 2 && (abs $dy) <= 2;
97     return (error => "nothing to talk there") unless $pl->cell_visible ($dx, $dy);
98     return (error => "only one dialog can be open at a time") if $pl->{npc_dialog}; # only one dialog at a time
99 root 1.1
100     for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
101 root 1.12 if ($npc->has_dialogue) {
102 root 1.5 $pl->attach ("npc_dialog_active");
103 root 1.6 $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id;
104 root 1.5 dialog_tell $id, $pl->{npc_dialog}, "hi";
105 root 1.1 return;
106     }
107     }
108    
109 root 1.9 (error => "nothing to talk to to found")
110 root 1.1 };
111    
112     =item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text }
113    
114     Tells the NPC the given $text message and returns a reply structure which
115     can have the following keys:
116    
117     msg => $reply_text,
118     add_topics => [additional topic strings]
119     del_topics => [invalidated topic strings]
120    
121     =cut
122    
123     cf::register_extcmd npc_dialog_tell => sub {
124 root 1.9 my ($pl, $id, $msg) = @_;
125 root 1.1
126 root 1.5 if (my $dialog = $pl->{npc_dialog}) {
127 root 1.9 dialog_tell $id, $dialog, $msg;
128 root 1.5 }
129 root 1.1 };
130    
131     =item extcmd npc_dialog_end { msgid => $id }
132    
133     Finishes the dialog, invalidating the handle.
134    
135     =cut
136    
137     cf::register_extcmd npc_dialog_end => sub {
138 root 1.9 my ($pl, $id) = @_;
139 root 1.1
140 root 1.5 if (my $dialog = delete $pl->{npc_dialog}) {
141 root 1.9 $pl->detach ("ncp_dialog_active");
142 root 1.5 }
143 root 1.1 };
144    
145     =item ... = extcmd editor_support
146    
147     Returns the value required by clients that have an editor to download and
148     upload maps from/to the server.
149    
150     servertype => (game|test) type of this server
151     gameserver => the hostname:port of the normal game server
152     testserver => the hostname:port of the test server the maps can be tested on
153     cvs_root => the (http) url where the cvs root for downloading is located
154 root 1.13 lib_root => the (http) url where archetypes data can be found
155 root 1.1 upload => the (http) url where clients can upload maps
156    
157     If those values are not supplied or empty strings, the server does not
158     support downloading, uploading, testing, respectively.
159    
160     The upload script expects the following values in a multipart form upload:
161    
162     client: a descriptive string describing the editor and version used to upload
163     path: absolute server-side map path beginning with /
164     map: the map file itself
165     mapdir: the cvs root url originally used to download the map
166     revision: cvs-revision originally used to download the map
167     comment: a comment supplied by the user that documents the changes
168 root 1.13 login: deliantra server login
169     password: deliantra server password, optionally used for authentication purposes
170 root 1.1
171     =cut
172    
173     cf::register_extcmd editor_support => sub {
174 root 1.9 my ($pl, %msg) = @_;
175 root 1.1
176 root 1.16 my %cfg = map +($_ => $cf::CFG{"editor_$_"}), qw(servertype servertypes gameserver testserver cvs_root lib_root builder_ui);
177    
178     # clients 2.10 and below check for type and "nameserver" :/
179     $cfg{type} = $cfg{servertype};
180     $cfg{nameserver} = $cfg{gameserver};
181    
182     %cfg
183 root 1.1 };
184    
185     sub unload {
186 root 1.5 for my $pl (cf::player::list) {
187     if (my $dialog = delete $pl->{npc_dialog}) {
188     $pl->detach ("npc_dialog_active");
189 root 1.9 $pl->ext_msg ($dialog->{id} => error => "npc dialogue module was reloaded");
190 root 1.5 }
191 root 1.1 }
192 root 1.5 }
193 root 1.1
194 root 1.5 cf::player::attachment npc_dialog_active =>
195     on_logout => sub {
196     my ($pl) = @_;
197    
198     delete $pl->{npc_dialog};
199     $pl->detach ("npc_dialog_active");
200     },
201 root 1.15 on_map_change => sub {
202     my ($pl) = @_;
203    
204     my $dialog = delete $pl->{npc_dialog}
205     or return;
206    
207     $pl->ext_msg ($dialog->{id} => error => "out of range");
208     $pl->detach ("npc_dialog_active");
209     },
210 root 1.5 on_move => sub {
211     my ($pl, $dir) = @_;
212    
213 root 1.9 # must delay a bit :/
214 root 1.17 my $delay; $delay = AE::timer 0, 0, sub {
215 root 1.10 undef $delay;
216 root 1.9
217     if (my $dialog = $pl->{npc_dialog}) {
218     my (undef, $dx, $dy) = $pl->ob->rangevector ($dialog->{npc});
219    
220     return if (abs $dx) <= 2 && (abs $dy) <= 2;
221 root 1.5
222 root 1.15 delete $pl->{npc_dialog};
223 root 1.9 $pl->ext_msg ($dialog->{id} => error => "out of range");
224 root 1.15 $pl->detach ("npc_dialog_active");
225 root 1.9 }
226 root 1.11 };
227 root 1.5 },
228     ;
229    
230     cf::player->attach (
231     on_login => sub {
232     my ($pl) = @_;
233    
234     delete $pl->{npc_dialog};
235     },
236     );
237 root 1.1
238     =back
239    
240     =cut
241