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.4 by root, Mon Apr 2 18:04:45 2007 UTC vs.
Revision 1.14 by root, Sat Dec 13 20:34:37 2008 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 ( 28 (version => $msg{version} >= 2 ? 2 : 0)
29 version => 2,
30 )
31};
32
33my %dialog; # currently active dialogs
34
35my $timer = Event->timer (interval => 0.2, parked => 1, data => cf::WF_AUTOCANCEL, cb => sub {
36 while (my ($id, $dialog) = each %dialog) {
37 my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc});
38 next if (abs $dx) <= 2 && (abs $dy) <= 2;
39
40 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "out of range");
41 delete $dialog{$id};
42 }
43
44 $_[0]->w->stop unless keys %dialog;
45}); 29};
46 30
47sub dialog_tell { 31sub dialog_tell {
48 my ($id, $dialog, $msg) = @_; 32 my ($id, $dialog, $msg) = @_;
49 33
50 my $pl = $dialog->{ob}->contr; 34 my $pl = $dialog->{pl};
51 my ($reply, @kw) = $dialog->tell ($msg); 35 my ($reply, @kw) = $dialog->tell ($msg);
36
52 $reply = "..." unless $reply; 37 $reply = "..." unless defined $reply;
53 38
54 $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
55} 41}
56 42
57=item ... = extcmd lookat { dx => $dx, dy => $dy } 43=item ... = extcmd lookat { dx => $dx, dy => $dy }
58 44
59"Looks at" the mapspace displaced (dx|dy) relative to the player 45"Looks at" the mapspace displaced (dx|dy) relative to the player
65 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.
66 52
67=cut 53=cut
68 54
69cf::register_extcmd lookat => sub { 55cf::register_extcmd lookat => sub {
70 my ($pl, $msg) = @_; 56 my ($pl, $dx, $dy) = @_;
71 my ($dx, $dy) = @$msg{qw(dx dy)};
72 57
73 return unless $pl->ob && $pl->ob->map; 58 return unless $pl->ob && $pl->ob->map;
74 59
75 my $near = (abs $dx) <= 2 && (abs $dy) <= 2; 60 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
76 61
77 my %res; 62 my %res;
78 63
79 if ($pl->cell_visible ($dx, $dy)) { 64 if ($pl->cell_visible ($dx, $dy)) {
80 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)) {
81 $res{npc_dialog} = $ob->name 66 $res{npc_dialog} = [$ob->name, $dx, $dy]
82 if $near && NPC_Dialogue::has_dialogue $ob; 67 if $near && $ob->has_dialogue && !$pl->{npc_dialog};
83 } 68 }
84 } 69 }
85 70
86 %res 71 %res
87}; 72};
91Tries 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
92C<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
93messages related to this dialog interaction. 78messages related to this dialog interaction.
94 79
95It 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
96the npc "hi" and returning a reply strcuture as with C<extcmd 81the npc "hi" and returning a reply structure as with C<extcmd
97npc_dialog_tell>. 82npc_dialog_tell>.
98 83
99=cut 84=cut
100 85
101cf::register_extcmd npc_dialog_begin => sub { 86cf::register_extcmd npc_dialog_begin => sub {
102 my ($pl, $msg) = @_; 87 my ($pl, $id, $token) = @_;
103 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
104 91
105 return unless $pl->ob && $pl->ob->map; 92 return unless $pl->ob && $pl->ob->map;
93
94 my ($name, $dx, $dy) = @$token;
95
106 return unless (abs $dx) <= 2 && (abs $dy) <= 2; 96 return (error => "too far away") unless (abs $dx) <= 2 && (abs $dy) <= 2;
107 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
108 99
109 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)) {
110 if (NPC_Dialogue::has_dialogue $npc) { 101 if ($npc->has_dialogue) {
102 $pl->attach ("npc_dialog_active");
111 $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc; 103 $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id;
112 dialog_tell $id, $dialog{$id}, "hi"; 104 dialog_tell $id, $pl->{npc_dialog}, "hi";
113 $timer->start;
114 return; 105 return;
115 } 106 }
116 } 107 }
117 108
118 (msgtype => "error", msg => "nothing to talk to found") 109 (error => "nothing to talk to to found")
119}; 110};
120 111
121=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text } 112=item ... = extcmd npc_dialog_tell { msgid => $id, msg => $text }
122 113
123Tells 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
124can have the following keys: 115can have the following keys:
125 116
126 msgtype => "reply"
127 msg => $reply_text, 117 msg => $reply_text,
128 add_topics => [additional topic strings] 118 add_topics => [additional topic strings]
129 del_topics => [invalidated topic strings] 119 del_topics => [invalidated topic strings]
130 120
131=cut 121=cut
132 122
133cf::register_extcmd npc_dialog_tell => sub { 123cf::register_extcmd npc_dialog_tell => sub {
134 my ($pl, $msg) = @_; 124 my ($pl, $id, $msg) = @_;
135 125
136 dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg} 126 if (my $dialog = $pl->{npc_dialog}) {
137 if $dialog{$msg->{msgid}}; 127 dialog_tell $id, $dialog, $msg;
138 128 }
139 ()
140}; 129};
141 130
142=item extcmd npc_dialog_end { msgid => $id } 131=item extcmd npc_dialog_end { msgid => $id }
143 132
144Finishes the dialog, invalidating the handle. 133Finishes the dialog, invalidating the handle.
145 134
146=cut 135=cut
147 136
148cf::register_extcmd npc_dialog_end => sub { 137cf::register_extcmd npc_dialog_end => sub {
149 my ($pl, $msg) = @_; 138 my ($pl, $id) = @_;
150 139
151 delete $dialog{$msg->{msgid}}; 140 if (my $dialog = delete $pl->{npc_dialog}) {
152 141 $pl->detach ("ncp_dialog_active");
153 ()
154};
155
156cf::player->attach (
157 on_logout => sub {
158 my ($pl) = @_;
159
160 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog;
161 }, 142 }
162); 143};
163 144
164=item ... = extcmd editor_support 145=item ... = extcmd editor_support
165 146
166Returns 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
167upload maps from/to the server. 148upload maps from/to the server.
168 149
169 servertype => (game|test) type of this server 150 servertype => (game|test) type of this server
170 gameserver => the hostname:port of the normal game server 151 gameserver => the hostname:port of the normal game server
171 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
172 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
173 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
174 upload => the (http) url where clients can upload maps 155 upload => the (http) url where clients can upload maps
175 156
176If 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
177support downloading, uploading, testing, respectively. 158support downloading, uploading, testing, respectively.
178 159
182 path: absolute server-side map path beginning with / 163 path: absolute server-side map path beginning with /
183 map: the map file itself 164 map: the map file itself
184 mapdir: the cvs root url originally used to download the map 165 mapdir: the cvs root url originally used to download the map
185 revision: cvs-revision originally used to download the map 166 revision: cvs-revision originally used to download the map
186 comment: a comment supplied by the user that documents the changes 167 comment: a comment supplied by the user that documents the changes
187 cf_login: crossfire server login 168 login: deliantra server login
188 cf_password: crossfire server password, optionally used for authentication purposes 169 password: deliantra server password, optionally used for authentication purposes
189 170
190=cut 171=cut
191 172
192cf::register_extcmd editor_support => sub { 173cf::register_extcmd editor_support => sub {
193 my ($pl, $msg) = @_; 174 my ($pl, %msg) = @_;
194 175
195 map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui) 176 map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui)
196}; 177};
197 178
198sub unload { 179sub unload {
199 while (my ($id, $dialog) = each %dialog) { 180 for my $pl (cf::player::list) {
200 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "npc dialogue module was reloaded"); 181 if (my $dialog = delete $pl->{npc_dialog}) {
182 $pl->detach ("npc_dialog_active");
183 $pl->ext_msg ($dialog->{id} => error => "npc dialogue module was reloaded");
184 }
201 } 185 }
202
203 %dialog = ();
204} 186}
205 187
188cf::player::attachment npc_dialog_active =>
189 on_logout => sub {
190 my ($pl) = @_;
191
192 delete $pl->{npc_dialog};
193 $pl->detach ("npc_dialog_active");
194 },
195 on_move => sub {
196 my ($pl, $dir) = @_;
197
198 # must delay a bit :/
199 my $delay; $delay = EV::timer 0, 0, sub {
200 undef $delay;
201
202 if (my $dialog = $pl->{npc_dialog}) {
203 my (undef, $dx, $dy) = $pl->ob->rangevector ($dialog->{npc});
204
205 return if (abs $dx) <= 2 && (abs $dy) <= 2;
206
207 $pl->ext_msg ($dialog->{id} => error => "out of range");
208 }
209
210 delete $pl->{npc_dialog};
211 $pl->detach ("npc_dialog_active");
212 };
213 },
214;
215
216cf::player->attach (
217 on_login => sub {
218 my ($pl) = @_;
219
220 delete $pl->{npc_dialog};
221 },
222);
223
206=back 224=back
207 225
208=cut 226=cut
209 227

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines