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.1 by root, Fri Dec 15 19:29:18 2006 UTC vs.
Revision 1.17 by root, Sun Apr 11 04:52:07 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)}; 57
58 return unless $pl->ob && $pl->ob->map;
70 59
71 my $near = (abs $dx) <= 2 && (abs $dy) <= 2; 60 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
72 61
73 my %res; 62 my %res;
74 63
75 if ($pl->cell_visible ($dx, $dy)) { 64 if ($pl->cell_visible ($dx, $dy)) {
76 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)) {
77 $res{npc_dialog} = $ob->name 66 $res{npc_dialog} = [$ob->name, $dx, $dy]
78 if $near && NPC_Dialogue::has_dialogue $ob; 67 if $near && $ob->has_dialogue && !$pl->{npc_dialog};
79 } 68 }
80 } 69 }
81 70
82 %res 71 %res
83}; 72};
87Tries 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
88C<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
89messages related to this dialog interaction. 78messages related to this dialog interaction.
90 79
91It 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
92the npc "hi" and returning a reply strcuture as with C<extcmd 81the npc "hi" and returning a reply structure as with C<extcmd
93npc_dialog_tell>. 82npc_dialog_tell>.
94 83
95=cut 84=cut
96 85
97cf::register_extcmd npc_dialog_begin => sub { 86cf::register_extcmd npc_dialog_begin => sub {
98 my ($pl, $msg) = @_; 87 my ($pl, $id, $token) = @_;
99 my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)};
100 88
89 #TODO:
90 # this is not a request, so returning does no good: make it a request and die on error
91
92 return unless $pl->ob && $pl->ob->map;
93
94 my ($name, $dx, $dy) = @$token;
95
101 return unless (abs $dx) <= 2 && (abs $dy) <= 2; 96 return (error => "too far away") unless (abs $dx) <= 2 && (abs $dy) <= 2;
102 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
103 99
104 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)) {
105 if (NPC_Dialogue::has_dialogue $npc) { 101 if ($npc->has_dialogue) {
102 $pl->attach ("npc_dialog_active");
106 $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc; 103 $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id;
107 dialog_tell $id, $dialog{$id}, "hi"; 104 dialog_tell $id, $pl->{npc_dialog}, "hi";
108 $timer->start;
109 return; 105 return;
110 } 106 }
111 } 107 }
112 108
113 (msgtype => "error", msg => "nothing to talk to found") 109 (error => "nothing to talk to to found")
114}; 110};
115 111
116=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text } 112=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text }
117 113
118Tells 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
119can have the following keys: 115can have the following keys:
120 116
121 msgtype => "reply"
122 msg => $reply_text, 117 msg => $reply_text,
123 add_topics => [additional topic strings] 118 add_topics => [additional topic strings]
124 del_topics => [invalidated topic strings] 119 del_topics => [invalidated topic strings]
125 120
126=cut 121=cut
127 122
128cf::register_extcmd npc_dialog_tell => sub { 123cf::register_extcmd npc_dialog_tell => sub {
129 my ($pl, $msg) = @_; 124 my ($pl, $id, $msg) = @_;
130 125
131 dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg} 126 if (my $dialog = $pl->{npc_dialog}) {
132 if $dialog{$msg->{msgid}}; 127 dialog_tell $id, $dialog, $msg;
133 128 }
134 ()
135}; 129};
136 130
137=item extcmd npc_dialog_end { msgid => $id } 131=item extcmd npc_dialog_end { msgid => $id }
138 132
139Finishes the dialog, invalidating the handle. 133Finishes the dialog, invalidating the handle.
140 134
141=cut 135=cut
142 136
143cf::register_extcmd npc_dialog_end => sub { 137cf::register_extcmd npc_dialog_end => sub {
144 my ($pl, $msg) = @_; 138 my ($pl, $id) = @_;
145 139
146 delete $dialog{$msg->{msgid}}; 140 if (my $dialog = delete $pl->{npc_dialog}) {
147 141 $pl->detach ("ncp_dialog_active");
148 ()
149};
150
151cf::attach_to_players
152 on_logout => sub {
153 my ($pl) = @_;
154
155 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog;
156 }, 142 }
157; 143};
158 144
159=item ... = extcmd editor_support 145=item ... = extcmd editor_support
160 146
161Returns 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
162upload maps from/to the server. 148upload maps from/to the server.
163 149
164 servertype => (game|test) type of this server 150 servertype => (game|test) type of this server
165 gameserver => the hostname:port of the normal game server 151 gameserver => the hostname:port of the normal game server
166 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
167 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
168 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
169 upload => the (http) url where clients can upload maps 155 upload => the (http) url where clients can upload maps
170 156
171If 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
172support downloading, uploading, testing, respectively. 158support downloading, uploading, testing, respectively.
173 159
177 path: absolute server-side map path beginning with / 163 path: absolute server-side map path beginning with /
178 map: the map file itself 164 map: the map file itself
179 mapdir: the cvs root url originally used to download the map 165 mapdir: the cvs root url originally used to download the map
180 revision: cvs-revision originally used to download the map 166 revision: cvs-revision originally used to download the map
181 comment: a comment supplied by the user that documents the changes 167 comment: a comment supplied by the user that documents the changes
182 cf_login: crossfire server login 168 login: deliantra server login
183 cf_password: crossfire server password, optionally used for authentication purposes 169 password: deliantra server password, optionally used for authentication purposes
184 170
185=cut 171=cut
186 172
187cf::register_extcmd editor_support => sub { 173cf::register_extcmd editor_support => sub {
188 my ($pl, $msg) = @_; 174 my ($pl, %msg) = @_;
189 175
190 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
191}; 183};
192 184
193sub unload { 185sub unload {
194 while (my ($id, $dialog) = each %dialog) { 186 for my $pl (cf::player::list) {
195 $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 }
196 } 191 }
197
198 %dialog = ();
199} 192}
200 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 = AE::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
201=back 238=back
202 239
203=cut 240=cut
204 241

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines