… | |
… | |
140 | |
140 | |
141 | ############################################################################# |
141 | ############################################################################# |
142 | |
142 | |
143 | =head2 ATTACHABLE OBJECTS |
143 | =head2 ATTACHABLE OBJECTS |
144 | |
144 | |
145 | You can define and attach attachments to each "attachable" object in |
145 | Many objects in crossfire are so-called attachable objects. That means you can |
146 | crossfire+ (objects, players, clients, maps and the special "global" |
146 | attach callbacks/event handlers (a collection of which is called an "attachment") |
|
|
147 | to it. All such attachable objects support the following methods. |
|
|
148 | |
147 | class). In the following description, CLASS can be any of C<global>, |
149 | In the following description, CLASS can be any of C<global>, C<object> |
148 | C<object> C<player>, C<client> or C<map>. |
150 | C<player>, C<client> or C<map> (i.e. the attachable objects in |
|
|
151 | crossfire+). |
149 | |
152 | |
150 | =over 4 |
153 | =over 4 |
151 | |
154 | |
|
|
155 | =item $attachable->attach ($attachment, key => $value...) |
|
|
156 | |
|
|
157 | =item $attachable->detach ($attachment) |
|
|
158 | |
|
|
159 | Attach/detach a pre-registered attachment to a specific object and give it |
|
|
160 | the specified key/value pairs as arguments. |
|
|
161 | |
|
|
162 | Example, attach a minesweeper attachment to the given object, making it a |
|
|
163 | 10x10 minesweeper game: |
|
|
164 | |
|
|
165 | $obj->attach (minesweeper => width => 10, height => 10); |
|
|
166 | |
|
|
167 | =item $bool = $attachable->attached ($name) |
|
|
168 | |
|
|
169 | Checks wether the named attachment is currently attached to the object. |
|
|
170 | |
|
|
171 | =item cf::CLASS->attach ... |
|
|
172 | |
|
|
173 | =item cf::CLASS->detach ... |
|
|
174 | |
|
|
175 | Define an anonymous attachment and attach it to all objects of the given |
|
|
176 | CLASS. See the next function for an explanation of its arguments. |
|
|
177 | |
|
|
178 | You can attach to global events by using the C<cf::global> class. |
|
|
179 | |
|
|
180 | Example, log all player logins: |
|
|
181 | |
|
|
182 | cf::player->attach ( |
|
|
183 | on_login => sub { |
|
|
184 | my ($pl) = @_; |
|
|
185 | ... |
|
|
186 | }, |
|
|
187 | ); |
|
|
188 | |
|
|
189 | Example, attach to the jeweler skill: |
|
|
190 | |
|
|
191 | cf::object->attach ( |
|
|
192 | type => cf::SKILL, |
|
|
193 | subtype => cf::SK_JEWELER, |
|
|
194 | on_use_skill => sub { |
|
|
195 | my ($sk, $ob, $part, $dir, $msg) = @_; |
|
|
196 | ... |
|
|
197 | }, |
|
|
198 | ); |
|
|
199 | |
152 | =item cf::CLASS::attachment $name, ... |
200 | =item cf::CLASS::attachment $name, ... |
153 | |
201 | |
154 | Register an attachment by name through which attachable objects can refer |
202 | Register an attachment by C<$name> through which attachable objects of the |
155 | to this attachment. |
203 | given CLASS can refer to this attachment. |
156 | |
204 | |
157 | =item $bool = $attachable->attached ($name) |
205 | Some classes such as crossfire maps and objects can specify attachments |
|
|
206 | that are attached at load/instantiate time, thus the need for a name. |
158 | |
207 | |
159 | Checks wether the named attachment is currently attached to the object. |
|
|
160 | |
|
|
161 | =item $attachable->attach ($attachment, key => $value...) |
|
|
162 | |
|
|
163 | =item $attachable->detach ($attachment) |
|
|
164 | |
|
|
165 | Attach/detach a pre-registered attachment either to a specific object |
|
|
166 | (C<$attachable>) or all objects of the given class (if C<$attachable> is a |
|
|
167 | class in a static method call). |
|
|
168 | |
|
|
169 | You can attach to global events by using the C<cf::global> class. |
|
|
170 | |
|
|
171 | These method calls expect any number of the following handler/hook |
208 | These calls expect any number of the following handler/hook descriptions: |
172 | descriptions: |
|
|
173 | |
209 | |
174 | =over 4 |
210 | =over 4 |
175 | |
211 | |
176 | =item prio => $number |
212 | =item prio => $number |
177 | |
213 | |
… | |
… | |
202 | Look for sub functions of the name C<< on_I<event> >> in the given |
238 | Look for sub functions of the name C<< on_I<event> >> in the given |
203 | package and register them. Only handlers for eevents supported by the |
239 | package and register them. Only handlers for eevents supported by the |
204 | object/class are recognised. |
240 | object/class are recognised. |
205 | |
241 | |
206 | =back |
242 | =back |
|
|
243 | |
|
|
244 | Example, define an attachment called "sockpuppet" that calls the given |
|
|
245 | event handler when a monster attacks: |
|
|
246 | |
|
|
247 | cf::object::attachment sockpuppet => |
|
|
248 | on_skill_attack => sub { |
|
|
249 | my ($self, $victim) = @_; |
|
|
250 | ... |
|
|
251 | } |
|
|
252 | } |
207 | |
253 | |
208 | =cut |
254 | =cut |
209 | |
255 | |
210 | # the following variables are defined in .xs and must not be re-created |
256 | # the following variables are defined in .xs and must not be re-created |
211 | our @CB_GLOBAL = (); # registry for all global events |
257 | our @CB_GLOBAL = (); # registry for all global events |
… | |
… | |
712 | |
758 | |
713 | =head2 CORE EXTENSIONS |
759 | =head2 CORE EXTENSIONS |
714 | |
760 | |
715 | Functions and methods that extend core crossfire objects. |
761 | Functions and methods that extend core crossfire objects. |
716 | |
762 | |
|
|
763 | =head3 cf::player |
|
|
764 | |
717 | =over 4 |
765 | =over 4 |
718 | |
766 | |
719 | =item cf::player::exists $login |
767 | =item cf::player::exists $login |
720 | |
768 | |
721 | Returns true when the given account exists. |
769 | Returns true when the given account exists. |
… | |
… | |
725 | sub cf::player::exists($) { |
773 | sub cf::player::exists($) { |
726 | cf::player::find $_[0] |
774 | cf::player::find $_[0] |
727 | or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; |
775 | or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; |
728 | } |
776 | } |
729 | |
777 | |
|
|
778 | =item $player->ext_reply ($msgid, $msgtype, %msg) |
|
|
779 | |
|
|
780 | Sends an ext reply to the player. |
|
|
781 | |
|
|
782 | =cut |
|
|
783 | |
|
|
784 | sub cf::player::ext_reply($$$%) { |
|
|
785 | my ($self, $id, %msg) = @_; |
|
|
786 | |
|
|
787 | $msg{msgid} = $id; |
|
|
788 | |
|
|
789 | $self->send ("ext " . to_json \%msg); |
|
|
790 | } |
|
|
791 | |
|
|
792 | =back |
|
|
793 | |
|
|
794 | =head3 cf::object::player |
|
|
795 | |
|
|
796 | =over 4 |
|
|
797 | |
730 | =item $player_object->reply ($npc, $msg[, $flags]) |
798 | =item $player_object->reply ($npc, $msg[, $flags]) |
731 | |
799 | |
732 | Sends a message to the player, as if the npc C<$npc> replied. C<$npc> |
800 | Sends a message to the player, as if the npc C<$npc> replied. C<$npc> |
733 | can be C<undef>. Does the right thing when the player is currently in a |
801 | can be C<undef>. Does the right thing when the player is currently in a |
734 | dialogue with the given NPC character. |
802 | dialogue with the given NPC character. |
735 | |
803 | |
736 | =cut |
804 | =cut |
737 | |
805 | |
738 | # rough implementation of a future "reply" method that works |
806 | # rough implementation of a future "reply" method that works |
739 | # with dialog boxes. |
807 | # with dialog boxes. |
|
|
808 | #TODO: the first argument must go, split into a $npc->reply_to ( method |
740 | sub cf::object::player::reply($$$;$) { |
809 | sub cf::object::player::reply($$$;$) { |
741 | my ($self, $npc, $msg, $flags) = @_; |
810 | my ($self, $npc, $msg, $flags) = @_; |
742 | |
811 | |
743 | $flags = cf::NDI_BROWN | cf::NDI_UNIQUE unless @_ >= 4; |
812 | $flags = cf::NDI_BROWN | cf::NDI_UNIQUE unless @_ >= 4; |
744 | |
813 | |
… | |
… | |
748 | $msg = $npc->name . " says: $msg" if $npc; |
817 | $msg = $npc->name . " says: $msg" if $npc; |
749 | $self->message ($msg, $flags); |
818 | $self->message ($msg, $flags); |
750 | } |
819 | } |
751 | } |
820 | } |
752 | |
821 | |
753 | =item $player->ext_reply ($msgid, $msgtype, %msg) |
|
|
754 | |
|
|
755 | Sends an ext reply to the player. |
|
|
756 | |
|
|
757 | =cut |
|
|
758 | |
|
|
759 | sub cf::player::ext_reply($$$%) { |
|
|
760 | my ($self, $id, %msg) = @_; |
|
|
761 | |
|
|
762 | $msg{msgid} = $id; |
|
|
763 | |
|
|
764 | $self->send ("ext " . to_json \%msg); |
|
|
765 | } |
|
|
766 | |
|
|
767 | =item $player_object->may ("access") |
822 | =item $player_object->may ("access") |
768 | |
823 | |
769 | Returns wether the given player is authorized to access resource "access" |
824 | Returns wether the given player is authorized to access resource "access" |
770 | (e.g. "command_wizcast"). |
825 | (e.g. "command_wizcast"). |
771 | |
826 | |
… | |
… | |
778 | (ref $cf::CFG{"may_$access"} |
833 | (ref $cf::CFG{"may_$access"} |
779 | ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}} |
834 | ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}} |
780 | : $cf::CFG{"may_$access"}) |
835 | : $cf::CFG{"may_$access"}) |
781 | } |
836 | } |
782 | |
837 | |
783 | =cut |
838 | =head3 cf::client |
784 | |
839 | |
785 | ############################################################################# |
840 | =over 4 |
|
|
841 | |
|
|
842 | =item $client->send_drawinfo ($text, $flags) |
|
|
843 | |
|
|
844 | Sends a drawinfo packet to the client. Circumvents output buffering so |
|
|
845 | should not be used under normal circumstances. |
|
|
846 | |
|
|
847 | =cut |
|
|
848 | |
|
|
849 | sub cf::client::send_drawinfo { |
|
|
850 | my ($self, $text, $flags) = @_; |
|
|
851 | |
|
|
852 | utf8::encode $text; |
|
|
853 | $self->send_packet (sprintf "drawinfo %d %s", $flags, $text); |
|
|
854 | } |
|
|
855 | |
|
|
856 | |
|
|
857 | =item $success = $client->query ($flags, "text", \&cb) |
|
|
858 | |
|
|
859 | Queues a query to the client, calling the given callback with |
|
|
860 | the reply text on a reply. flags can be C<cf::CS_QUERY_YESNO>, |
|
|
861 | C<cf::CS_QUERY_SINGLECHAR> or C<cf::CS_QUERY_HIDEINPUT> or C<0>. |
|
|
862 | |
|
|
863 | Queries can fail, so check the return code. Or don't, as queries will become |
|
|
864 | reliable at some point in the future. |
|
|
865 | |
|
|
866 | =cut |
|
|
867 | |
|
|
868 | sub cf::client::query { |
|
|
869 | my ($self, $flags, $text, $cb) = @_; |
|
|
870 | |
|
|
871 | return unless $self->state == ST_PLAYING |
|
|
872 | || $self->state == ST_SETUP |
|
|
873 | || $self->state == ST_CUSTOM; |
|
|
874 | |
|
|
875 | $self->state (ST_CUSTOM); |
|
|
876 | |
|
|
877 | utf8::encode $text; |
|
|
878 | push @{ $self->{query_queue} }, [(sprintf "query %d %s", $flags, $text), $cb]; |
|
|
879 | |
|
|
880 | $self->send_packet ($self->{query_queue}[0][0]) |
|
|
881 | if @{ $self->{query_queue} } == 1; |
|
|
882 | } |
|
|
883 | |
|
|
884 | cf::client->attach ( |
|
|
885 | on_reply => sub { |
|
|
886 | my ($ns, $msg) = @_; |
|
|
887 | |
|
|
888 | # this weird shuffling is so that direct followup queries |
|
|
889 | # get handled first |
|
|
890 | my $queue = delete $ns->{query_queue}; |
|
|
891 | |
|
|
892 | (shift @$queue)->[1]->($msg); |
|
|
893 | |
|
|
894 | push @{ $ns->{query_queue} }, @$queue; |
|
|
895 | |
|
|
896 | if (@{ $ns->{query_queue} } == @$queue) { |
|
|
897 | if (@$queue) { |
|
|
898 | $ns->send_packet ($ns->{query_queue}[0][0]); |
|
|
899 | } else { |
|
|
900 | $ns->state (ST_PLAYING); |
|
|
901 | } |
|
|
902 | } |
|
|
903 | }, |
|
|
904 | ); |
|
|
905 | |
|
|
906 | =back |
|
|
907 | |
786 | |
908 | |
787 | =head2 SAFE SCRIPTING |
909 | =head2 SAFE SCRIPTING |
788 | |
910 | |
789 | Functions that provide a safe environment to compile and execute |
911 | Functions that provide a safe environment to compile and execute |
790 | snippets of perl code without them endangering the safety of the server |
912 | snippets of perl code without them endangering the safety of the server |