ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/cfplus.ext
(Generate patch)

Comparing deliantra/server/ext/cfplus.ext (file contents):
Revision 1.3 by root, Thu Dec 21 22:41:34 2006 UTC vs.
Revision 1.16 by root, Tue Mar 16 20:28:22 2010 UTC

19highest version of the protocol it supports in the C<version> key itself. 19highest version of the protocol it supports in the C<version> key itself.
20 20
21=cut 21=cut
22 22
23cf::register_extcmd cfplus_support => sub { 23cf::register_extcmd cfplus_support => sub {
24 my ($pl, $msg) = @_; 24 my ($pl, %msg) = @_;
25 25
26 # $msg->{version} 26 $pl->ns->{cfplus_ext} = $msg{version};
27 27
28 (version => 2) 28 (version => $msg{version} >= 2 ? 2 : 0)
29};
30
31my %dialog; # currently active dialogs
32
33my $timer = Event->timer (interval => 0.2, parked => 1, data => cf::WF_AUTOCANCEL, cb => sub {
34 while (my ($id, $dialog) = each %dialog) {
35 my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc});
36 next if (abs $dx) <= 2 && (abs $dy) <= 2;
37
38 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "out of range");
39 delete $dialog{$id};
40 }
41
42 $_[0]->w->stop unless keys %dialog;
43}); 29};
44 30
45sub dialog_tell { 31sub dialog_tell {
46 my ($id, $dialog, $msg) = @_; 32 my ($id, $dialog, $msg) = @_;
47 33
48 my $pl = $dialog->{ob}->contr; 34 my $pl = $dialog->{pl};
49 my ($reply, @kw) = $dialog->tell ($msg); 35 my ($reply, @kw) = $dialog->tell ($msg);
36
50 $reply = "..." unless $reply; 37 $reply = "..." unless defined $reply;
51 38
52 $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw); 39 $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
53} 41}
54 42
55=item ... = extcmd lookat { dx => $dx, dy => $dy } 43=item ... = extcmd lookat { dx => $dx, dy => $dy }
56 44
57"Looks at" the mapspace displaced (dx|dy) relative to the player 45"Looks at" the mapspace displaced (dx|dy) relative to the player
63 There is an npc or other object that can "talk" to the player. 51 There is an npc or other object that can "talk" to the player.
64 52
65=cut 53=cut
66 54
67cf::register_extcmd lookat => sub { 55cf::register_extcmd lookat => sub {
68 my ($pl, $msg) = @_; 56 my ($pl, $dx, $dy) = @_;
69 my ($dx, $dy) = @$msg{qw(dx dy)};
70 57
71 return unless $pl->ob && $pl->ob->map; 58 return unless $pl->ob && $pl->ob->map;
72 59
73 my $near = (abs $dx) <= 2 && (abs $dy) <= 2; 60 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
74 61
75 my %res; 62 my %res;
76 63
77 if ($pl->cell_visible ($dx, $dy)) { 64 if ($pl->cell_visible ($dx, $dy)) {
78 for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { 65 for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
79 $res{npc_dialog} = $ob->name 66 $res{npc_dialog} = [$ob->name, $dx, $dy]
80 if $near && NPC_Dialogue::has_dialogue $ob; 67 if $near && $ob->has_dialogue && !$pl->{npc_dialog};
81 } 68 }
82 } 69 }
83 70
84 %res 71 %res
85}; 72};
89Tries to start a dialogue with the mapspace specified by $dx and $dy (see 76Tries to start a dialogue with the mapspace specified by $dx and $dy (see
90C<extcmd lookat>). The $msgid will be used as a handle for all future 77C<extcmd lookat>). The $msgid will be used as a handle for all future
91messages related to this dialog interaction. 78messages related to this dialog interaction.
92 79
93It either replies with an error reply or starts a dialog by telling 80It either replies with an error reply or starts a dialog by telling
94the npc "hi" and returning a reply strcuture as with C<extcmd 81the npc "hi" and returning a reply structure as with C<extcmd
95npc_dialog_tell>. 82npc_dialog_tell>.
96 83
97=cut 84=cut
98 85
99cf::register_extcmd npc_dialog_begin => sub { 86cf::register_extcmd npc_dialog_begin => sub {
100 my ($pl, $msg) = @_; 87 my ($pl, $id, $token) = @_;
101 my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)}; 88
89 #TODO:
90 # this is not a request, so returning does no good: make it a request and die on error
102 91
103 return unless $pl->ob && $pl->ob->map; 92 return unless $pl->ob && $pl->ob->map;
93
94 my ($name, $dx, $dy) = @$token;
95
104 return unless (abs $dx) <= 2 && (abs $dy) <= 2; 96 return (error => "too far away") unless (abs $dx) <= 2 && (abs $dy) <= 2;
105 return unless $pl->cell_visible ($dx, $dy); 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
106 99
107 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { 100 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
108 if (NPC_Dialogue::has_dialogue $npc) { 101 if ($npc->has_dialogue) {
102 $pl->attach ("npc_dialog_active");
109 $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc; 103 $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id;
110 dialog_tell $id, $dialog{$id}, "hi"; 104 dialog_tell $id, $pl->{npc_dialog}, "hi";
111 $timer->start;
112 return; 105 return;
113 } 106 }
114 } 107 }
115 108
116 (msgtype => "error", msg => "nothing to talk to found") 109 (error => "nothing to talk to to found")
117}; 110};
118 111
119=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text } 112=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text }
120 113
121Tells the NPC the given $text message and returns a reply structure which 114Tells the NPC the given $text message and returns a reply structure which
122can have the following keys: 115can have the following keys:
123 116
124 msgtype => "reply"
125 msg => $reply_text, 117 msg => $reply_text,
126 add_topics => [additional topic strings] 118 add_topics => [additional topic strings]
127 del_topics => [invalidated topic strings] 119 del_topics => [invalidated topic strings]
128 120
129=cut 121=cut
130 122
131cf::register_extcmd npc_dialog_tell => sub { 123cf::register_extcmd npc_dialog_tell => sub {
132 my ($pl, $msg) = @_; 124 my ($pl, $id, $msg) = @_;
133 125
134 dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg} 126 if (my $dialog = $pl->{npc_dialog}) {
135 if $dialog{$msg->{msgid}}; 127 dialog_tell $id, $dialog, $msg;
136 128 }
137 ()
138}; 129};
139 130
140=item extcmd npc_dialog_end { msgid => $id } 131=item extcmd npc_dialog_end { msgid => $id }
141 132
142Finishes the dialog, invalidating the handle. 133Finishes the dialog, invalidating the handle.
143 134
144=cut 135=cut
145 136
146cf::register_extcmd npc_dialog_end => sub { 137cf::register_extcmd npc_dialog_end => sub {
147 my ($pl, $msg) = @_; 138 my ($pl, $id) = @_;
148 139
149 delete $dialog{$msg->{msgid}}; 140 if (my $dialog = delete $pl->{npc_dialog}) {
150 141 $pl->detach ("ncp_dialog_active");
151 ()
152};
153
154cf::player->attach (
155 on_logout => sub {
156 my ($pl) = @_;
157
158 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog;
159 }, 142 }
160); 143};
161 144
162=item ... = extcmd editor_support 145=item ... = extcmd editor_support
163 146
164Returns the value required by clients that have an editor to download and 147Returns the value required by clients that have an editor to download and
165upload maps from/to the server. 148upload maps from/to the server.
166 149
167 servertype => (game|test) type of this server 150 servertype => (game|test) type of this server
168 gameserver => the hostname:port of the normal game server 151 gameserver => the hostname:port of the normal game server
169 testserver => the hostname:port of the test server the maps can be tested on 152 testserver => the hostname:port of the test server the maps can be tested on
170 cvs_root => the (http) url where the cvs root for downloading is located 153 cvs_root => the (http) url where the cvs root for downloading is located
171 lib_root => the (http) url where crossfire.0 and archetypes can be found 154 lib_root => the (http) url where archetypes data can be found
172 upload => the (http) url where clients can upload maps 155 upload => the (http) url where clients can upload maps
173 156
174If those values are not supplied or empty strings, the server does not 157If those values are not supplied or empty strings, the server does not
175support downloading, uploading, testing, respectively. 158support downloading, uploading, testing, respectively.
176 159
180 path: absolute server-side map path beginning with / 163 path: absolute server-side map path beginning with /
181 map: the map file itself 164 map: the map file itself
182 mapdir: the cvs root url originally used to download the map 165 mapdir: the cvs root url originally used to download the map
183 revision: cvs-revision originally used to download the map 166 revision: cvs-revision originally used to download the map
184 comment: a comment supplied by the user that documents the changes 167 comment: a comment supplied by the user that documents the changes
185 cf_login: crossfire server login 168 login: deliantra server login
186 cf_password: crossfire server password, optionally used for authentication purposes 169 password: deliantra server password, optionally used for authentication purposes
187 170
188=cut 171=cut
189 172
190cf::register_extcmd editor_support => sub { 173cf::register_extcmd editor_support => sub {
191 my ($pl, $msg) = @_; 174 my ($pl, %msg) = @_;
192 175
193 map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui) 176 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
194}; 183};
195 184
196sub unload { 185sub unload {
197 while (my ($id, $dialog) = each %dialog) { 186 for my $pl (cf::player::list) {
198 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "npc dialogue module was reloaded"); 187 if (my $dialog = delete $pl->{npc_dialog}) {
188 $pl->detach ("npc_dialog_active");
189 $pl->ext_msg ($dialog->{id} => error => "npc dialogue module was reloaded");
190 }
199 } 191 }
200
201 %dialog = ();
202} 192}
203 193
194cf::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 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 on_move => sub {
211 my ($pl, $dir) = @_;
212
213 # must delay a bit :/
214 my $delay; $delay = EV::timer 0, 0, sub {
215 undef $delay;
216
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
222 delete $pl->{npc_dialog};
223 $pl->ext_msg ($dialog->{id} => error => "out of range");
224 $pl->detach ("npc_dialog_active");
225 }
226 };
227 },
228;
229
230cf::player->attach (
231 on_login => sub {
232 my ($pl) = @_;
233
234 delete $pl->{npc_dialog};
235 },
236);
237
204=back 238=back
205 239
206=cut 240=cut
207 241

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines