ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/ext/cfplus.ext
Revision: 1.3
Committed: Thu Dec 21 22:41:34 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
CVS Tags: rel-2_0
Changes since 1.2: +2 -2 lines
Log Message:
- updated cf.pm to use a more generic and extendable syntax,
  now that it is clear that we will have multiple "attachable" objects.
  maybe bite the bullet in C++ and make attachable virtual?
- completely rework the syntax for attaching and attachments
- update all extensions

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