ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.93 by root, Thu Dec 21 22:41:35 2006 UTC vs.
Revision 1.97 by root, Fri Dec 22 06:03:20 2006 UTC

1package cf; 1package cf;
2
3use utf8;
4use strict;
2 5
3use Symbol; 6use Symbol;
4use List::Util; 7use List::Util;
5use Storable; 8use Storable;
6use Opcode; 9use Opcode;
7use Safe; 10use Safe;
8use Safe::Hole; 11use Safe::Hole;
9 12
13use Coro;
14use Coro::Event;
15use Coro::Timer;
16use Coro::Signal;
17use Coro::Semaphore;
18
10use IO::AIO (); 19use IO::AIO;
11use YAML::Syck (); 20use YAML::Syck ();
12use Time::HiRes; 21use Time::HiRes;
13use Event; 22
14$Event::Eval = 1; # no idea why this is required, but it is 23use Event; $Event::Eval = 1; # no idea why this is required, but it is
15 24
16# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode? 25# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
17$YAML::Syck::ImplicitUnicode = 1; 26$YAML::Syck::ImplicitUnicode = 1;
18 27
19use strict; 28$Coro::main->prio (Coro::PRIO_MIN);
20 29
21sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload 30sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload
22 31
23our %COMMAND = (); 32our %COMMAND = ();
24our %COMMAND_TIME = (); 33our %COMMAND_TIME = ();
140 149
141############################################################################# 150#############################################################################
142 151
143=head2 ATTACHABLE OBJECTS 152=head2 ATTACHABLE OBJECTS
144 153
145You can define and attach attachments to each "attachable" object in 154Many objects in crossfire are so-called attachable objects. That means you can
146crossfire+ (objects, players, clients, maps and the special "global" 155attach callbacks/event handlers (a collection of which is called an "attachment")
156to it. All such attachable objects support the following methods.
157
147class). In the following description, CLASS can be any of C<global>, 158In the following description, CLASS can be any of C<global>, C<object>
148C<object> C<player>, C<client> or C<map>. 159C<player>, C<client> or C<map> (i.e. the attachable objects in
160crossfire+).
149 161
150=over 4 162=over 4
151 163
164=item $attachable->attach ($attachment, key => $value...)
165
166=item $attachable->detach ($attachment)
167
168Attach/detach a pre-registered attachment to a specific object and give it
169the specified key/value pairs as arguments.
170
171Example, attach a minesweeper attachment to the given object, making it a
17210x10 minesweeper game:
173
174 $obj->attach (minesweeper => width => 10, height => 10);
175
176=item $bool = $attachable->attached ($name)
177
178Checks wether the named attachment is currently attached to the object.
179
180=item cf::CLASS->attach ...
181
182=item cf::CLASS->detach ...
183
184Define an anonymous attachment and attach it to all objects of the given
185CLASS. See the next function for an explanation of its arguments.
186
187You can attach to global events by using the C<cf::global> class.
188
189Example, log all player logins:
190
191 cf::player->attach (
192 on_login => sub {
193 my ($pl) = @_;
194 ...
195 },
196 );
197
198Example, attach to the jeweler skill:
199
200 cf::object->attach (
201 type => cf::SKILL,
202 subtype => cf::SK_JEWELER,
203 on_use_skill => sub {
204 my ($sk, $ob, $part, $dir, $msg) = @_;
205 ...
206 },
207 );
208
152=item cf::CLASS::attachment $name, ... 209=item cf::CLASS::attachment $name, ...
153 210
154Register an attachment by name through which attachable objects can refer 211Register an attachment by C<$name> through which attachable objects of the
155to this attachment. 212given CLASS can refer to this attachment.
156 213
157=item $bool = $attachable->attached ($name) 214Some classes such as crossfire maps and objects can specify attachments
215that are attached at load/instantiate time, thus the need for a name.
158 216
159Checks 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
165Attach/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
167class in a static method call).
168
169You can attach to global events by using the C<cf::global> class.
170
171These method calls expect any number of the following handler/hook 217These calls expect any number of the following handler/hook descriptions:
172descriptions:
173 218
174=over 4 219=over 4
175 220
176=item prio => $number 221=item prio => $number
177 222
202Look for sub functions of the name C<< on_I<event> >> in the given 247Look for sub functions of the name C<< on_I<event> >> in the given
203package and register them. Only handlers for eevents supported by the 248package and register them. Only handlers for eevents supported by the
204object/class are recognised. 249object/class are recognised.
205 250
206=back 251=back
252
253Example, define an attachment called "sockpuppet" that calls the given
254event handler when a monster attacks:
255
256 cf::object::attachment sockpuppet =>
257 on_skill_attack => sub {
258 my ($self, $victim) = @_;
259 ...
260 }
261 }
262
263=item $attachable->valid
264
265Just because you have a perl object does not mean that the corresponding
266C-level object still exists. If you try to access an object that has no
267valid C counterpart anymore you get an exception at runtime. This method
268can be used to test for existence of the C object part without causing an
269exception.
207 270
208=cut 271=cut
209 272
210# the following variables are defined in .xs and must not be re-created 273# the following variables are defined in .xs and must not be re-created
211our @CB_GLOBAL = (); # registry for all global events 274our @CB_GLOBAL = (); # registry for all global events
367 } 430 }
368 431
369 0 432 0
370} 433}
371 434
372=item $bool = cf::invoke EVENT_GLOBAL_XXX, ... 435=item $bool = cf::global::invoke (EVENT_CLASS_XXX, ...)
373 436
374=item $bool = $object->invoke (EVENT_OBJECT_XXX, ...)
375
376=item $bool = $player->invoke (EVENT_PLAYER_XXX, ...)
377
378=item $bool = $client->invoke (EVENT_CLIENT_XXX, ...) 437=item $bool = $attachable->invoke (EVENT_CLASS_XXX, ...)
379 438
380=item $bool = $map->invoke (EVENT_MAP_XXX, ...)
381
382Generate a global/object/player/map-specific event with the given arguments. 439Generate an object-specific event with the given arguments.
383 440
384This API is preliminary (most likely, the EVENT_KLASS_xxx prefix will be 441This API is preliminary (most likely, the EVENT_CLASS_xxx prefix will be
385removed in future versions), and there is no public API to access override 442removed in future versions), and there is no public API to access override
386results (if you must, access C<@cf::invoke_results> directly). 443results (if you must, access C<@cf::invoke_results> directly).
387
388=back
389
390=cut
391
392#############################################################################
393
394=head2 METHODS VALID FOR ALL ATTACHABLE OBJECTS
395
396Attachable objects includes objects, players, clients and maps.
397
398=over 4
399
400=item $object->valid
401
402Just because you have a perl object does not mean that the corresponding
403C-level object still exists. If you try to access an object that has no
404valid C counterpart anymore you get an exception at runtime. This method
405can be used to test for existence of the C object part without causing an
406exception.
407 444
408=back 445=back
409 446
410=cut 447=cut
411 448
712 749
713=head2 CORE EXTENSIONS 750=head2 CORE EXTENSIONS
714 751
715Functions and methods that extend core crossfire objects. 752Functions and methods that extend core crossfire objects.
716 753
754=head3 cf::player
755
717=over 4 756=over 4
718 757
719=item cf::player::exists $login 758=item cf::player::exists $login
720 759
721Returns true when the given account exists. 760Returns true when the given account exists.
725sub cf::player::exists($) { 764sub cf::player::exists($) {
726 cf::player::find $_[0] 765 cf::player::find $_[0]
727 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2; 766 or -f sprintf "%s/%s/%s/%s.pl", cf::localdir, cf::playerdir, ($_[0]) x 2;
728} 767}
729 768
769=item $player->ext_reply ($msgid, $msgtype, %msg)
770
771Sends an ext reply to the player.
772
773=cut
774
775sub cf::player::ext_reply($$$%) {
776 my ($self, $id, %msg) = @_;
777
778 $msg{msgid} = $id;
779
780 $self->send ("ext " . to_json \%msg);
781}
782
783=back
784
785=head3 cf::object::player
786
787=over 4
788
730=item $player_object->reply ($npc, $msg[, $flags]) 789=item $player_object->reply ($npc, $msg[, $flags])
731 790
732Sends a message to the player, as if the npc C<$npc> replied. C<$npc> 791Sends a message to the player, as if the npc C<$npc> replied. C<$npc>
733can be C<undef>. Does the right thing when the player is currently in a 792can be C<undef>. Does the right thing when the player is currently in a
734dialogue with the given NPC character. 793dialogue with the given NPC character.
735 794
736=cut 795=cut
737 796
738# rough implementation of a future "reply" method that works 797# rough implementation of a future "reply" method that works
739# with dialog boxes. 798# with dialog boxes.
799#TODO: the first argument must go, split into a $npc->reply_to ( method
740sub cf::object::player::reply($$$;$) { 800sub cf::object::player::reply($$$;$) {
741 my ($self, $npc, $msg, $flags) = @_; 801 my ($self, $npc, $msg, $flags) = @_;
742 802
743 $flags = cf::NDI_BROWN | cf::NDI_UNIQUE unless @_ >= 4; 803 $flags = cf::NDI_BROWN | cf::NDI_UNIQUE unless @_ >= 4;
744 804
748 $msg = $npc->name . " says: $msg" if $npc; 808 $msg = $npc->name . " says: $msg" if $npc;
749 $self->message ($msg, $flags); 809 $self->message ($msg, $flags);
750 } 810 }
751} 811}
752 812
753=item $player->ext_reply ($msgid, $msgtype, %msg)
754
755Sends an ext reply to the player.
756
757=cut
758
759sub 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") 813=item $player_object->may ("access")
768 814
769Returns wether the given player is authorized to access resource "access" 815Returns wether the given player is authorized to access resource "access"
770(e.g. "command_wizcast"). 816(e.g. "command_wizcast").
771 817
778 (ref $cf::CFG{"may_$access"} 824 (ref $cf::CFG{"may_$access"}
779 ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}} 825 ? scalar grep $self->name eq $_, @{$cf::CFG{"may_$access"}}
780 : $cf::CFG{"may_$access"}) 826 : $cf::CFG{"may_$access"})
781} 827}
782 828
783=cut 829=head3 cf::client
784 830
785############################################################################# 831=over 4
832
833=item $client->send_drawinfo ($text, $flags)
834
835Sends a drawinfo packet to the client. Circumvents output buffering so
836should not be used under normal circumstances.
837
838=cut
839
840sub cf::client::send_drawinfo {
841 my ($self, $text, $flags) = @_;
842
843 utf8::encode $text;
844 $self->send_packet (sprintf "drawinfo %d %s", $flags, $text);
845}
846
847
848=item $success = $client->query ($flags, "text", \&cb)
849
850Queues a query to the client, calling the given callback with
851the reply text on a reply. flags can be C<cf::CS_QUERY_YESNO>,
852C<cf::CS_QUERY_SINGLECHAR> or C<cf::CS_QUERY_HIDEINPUT> or C<0>.
853
854Queries can fail, so check the return code. Or don't, as queries will become
855reliable at some point in the future.
856
857=cut
858
859sub cf::client::query {
860 my ($self, $flags, $text, $cb) = @_;
861
862 return unless $self->state == ST_PLAYING
863 || $self->state == ST_SETUP
864 || $self->state == ST_CUSTOM;
865
866 $self->state (ST_CUSTOM);
867
868 utf8::encode $text;
869 push @{ $self->{query_queue} }, [(sprintf "query %d %s", $flags, $text), $cb];
870
871 $self->send_packet ($self->{query_queue}[0][0])
872 if @{ $self->{query_queue} } == 1;
873}
874
875cf::client->attach (
876 on_reply => sub {
877 my ($ns, $msg) = @_;
878
879 # this weird shuffling is so that direct followup queries
880 # get handled first
881 my $queue = delete $ns->{query_queue};
882
883 (shift @$queue)->[1]->($msg);
884
885 push @{ $ns->{query_queue} }, @$queue;
886
887 if (@{ $ns->{query_queue} } == @$queue) {
888 if (@$queue) {
889 $ns->send_packet ($ns->{query_queue}[0][0]);
890 } else {
891 $ns->state (ST_PLAYING);
892 }
893 }
894 },
895);
896
897=item $client->coro (\&cb)
898
899Create a new coroutine, running the specified callback. The coroutine will
900be automatically cancelled when the client gets destroyed (e.g. on logout,
901or loss of connection).
902
903=cut
904
905sub cf::client::coro {
906 my ($self, $cb) = @_;
907
908 my $coro; $coro = async {
909 eval {
910 $cb->();
911 };
912 warn $@ if $@;
913 delete $self->{_coro}{$coro+0};
914 };
915
916 $self->{_coro}{$coro+0} = $coro;
917}
918
919cf::client->attach (
920 on_destroy => sub {
921 my ($ns) = @_;
922
923 $_->cancel for values %{ (delete $ns->{_coro}) || {} };
924 },
925);
926
927=back
928
786 929
787=head2 SAFE SCRIPTING 930=head2 SAFE SCRIPTING
788 931
789Functions that provide a safe environment to compile and execute 932Functions that provide a safe environment to compile and execute
790snippets of perl code without them endangering the safety of the server 933snippets of perl code without them endangering the safety of the server

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines