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.92 by root, Thu Dec 21 06:42:28 2006 UTC vs.
Revision 1.93 by root, Thu Dec 21 22:41:35 2006 UTC

74 print STDERR "cfperl: $msg"; 74 print STDERR "cfperl: $msg";
75 LOG llevError, "cfperl: $msg"; 75 LOG llevError, "cfperl: $msg";
76 }; 76 };
77} 77}
78 78
79@safe::cf::global::ISA = @cf::global::ISA = 'cf::attachable';
80@safe::cf::object::ISA = @cf::object::ISA = 'cf::attachable';
81@safe::cf::player::ISA = @cf::player::ISA = 'cf::attachable';
82@safe::cf::client::ISA = @cf::client::ISA = 'cf::attachable';
83@safe::cf::map::ISA = @cf::map::ISA = 'cf::attachable';
79@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object'; 84@safe::cf::object::player::ISA = @cf::object::player::ISA = 'cf::object';
80 85
81# we bless all objects into (empty) derived classes to force a method lookup 86# we bless all objects into (empty) derived classes to force a method lookup
82# within the Safe compartment. 87# within the Safe compartment.
83for my $pkg (qw( 88for my $pkg (qw(
89 cf::global
84 cf::object cf::object::player 90 cf::object cf::object::player
85 cf::client cf::player 91 cf::client cf::player
86 cf::arch cf::living 92 cf::arch cf::living
87 cf::map cf::party cf::region 93 cf::map cf::party cf::region
88)) { 94)) {
132 138
133=cut 139=cut
134 140
135############################################################################# 141#############################################################################
136 142
137=head2 EVENTS AND OBJECT ATTACHMENTS 143=head2 ATTACHABLE OBJECTS
144
145You can define and attach attachments to each "attachable" object in
146crossfire+ (objects, players, clients, maps and the special "global"
147class). In the following description, CLASS can be any of C<global>,
148C<object> C<player>, C<client> or C<map>.
138 149
139=over 4 150=over 4
140 151
141=item $object->attach ($attachment, key => $value...) 152=item cf::CLASS::attachment $name, ...
142 153
143=item $object->detach ($attachment) 154Register an attachment by name through which attachable objects can refer
155to this attachment.
144 156
145Attach/detach a pre-registered attachment to an object.
146
147=item $player->attach ($attachment, key => $value...)
148
149=item $player->detach ($attachment)
150
151Attach/detach a pre-registered attachment to a player.
152
153=item $map->attach ($attachment, key => $value...)
154
155=item $map->detach ($attachment)
156
157Attach/detach a pre-registered attachment to a client.
158
159=item $client->attach ($attachment, key => $value...)
160
161=item $client->detach ($attachment)
162
163Attach/detach a pre-registered attachment to a map.
164
165=item $bool = $object->attached ($name)
166
167=item $bool = $player->attached ($name)
168
169=item $bool = $client->attached ($name) 157=item $bool = $attachable->attached ($name)
170
171=item $bool = $map->attached ($name)
172 158
173Checks wether the named attachment is currently attached to the object. 159Checks wether the named attachment is currently attached to the object.
174 160
175=item cf::attach_global ... 161=item $attachable->attach ($attachment, key => $value...)
176 162
177Attach handlers for global events. 163=item $attachable->detach ($attachment)
178 164
179This and all following C<attach_*>-functions expect any number of the 165Attach/detach a pre-registered attachment either to a specific object
180following handler/hook descriptions: 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
172descriptions:
181 173
182=over 4 174=over 4
183 175
184=item prio => $number 176=item prio => $number
185 177
187by another C<prio> setting). Lower priority handlers get executed 179by another C<prio> setting). Lower priority handlers get executed
188earlier. The default priority is C<0>, and many built-in handlers are 180earlier. The default priority is C<0>, and many built-in handlers are
189registered at priority C<-1000>, so lower priorities should not be used 181registered at priority C<-1000>, so lower priorities should not be used
190unless you know what you are doing. 182unless you know what you are doing.
191 183
184=item type => $type
185
186(Only for C<< cf::object->attach >> calls), limits the attachment to the
187given type of objects only (the additional parameter C<subtype> can be
188used to further limit to the given subtype).
189
192=item on_I<event> => \&cb 190=item on_I<event> => \&cb
193 191
194Call the given code reference whenever the named event happens (event is 192Call the given code reference whenever the named event happens (event is
195something like C<instantiate>, C<apply>, C<use_skill> and so on, and which 193something like C<instantiate>, C<apply>, C<use_skill> and so on, and which
196handlers are recognised generally depends on the type of object these 194handlers are recognised generally depends on the type of object these
204Look for sub functions of the name C<< on_I<event> >> in the given 202Look for sub functions of the name C<< on_I<event> >> in the given
205package and register them. Only handlers for eevents supported by the 203package and register them. Only handlers for eevents supported by the
206object/class are recognised. 204object/class are recognised.
207 205
208=back 206=back
209
210=item cf::attach_to_type $object_type, $subtype, ...
211
212Attach handlers for a specific object type (e.g. TRANSPORT) and
213subtype. If C<$subtype> is zero or undef, matches all objects of the given
214type.
215
216=item cf::attach_to_objects ...
217
218Attach handlers to all objects. Do not use this except for debugging or
219very rare events, as handlers are (obviously) called for I<all> objects in
220the game.
221
222=item cf::attach_to_players ...
223
224Attach handlers to all players.
225
226=item cf::attach_to_clients ...
227
228Attach handlers to all players.
229
230=item cf::attach_to_maps ...
231
232Attach handlers to all maps.
233
234=item cf:register_attachment $name, ...
235
236Register an attachment by name through which objects can refer to this
237attachment.
238
239=item cf:register_player_attachment $name, ...
240
241Register an attachment by name through which players can refer to this
242attachment.
243
244=item cf:register_map_attachment $name, ...
245
246Register an attachment by name through which maps can refer to this
247attachment.
248 207
249=cut 208=cut
250 209
251# the following variables are defined in .xs and must not be re-created 210# the following variables are defined in .xs and must not be re-created
252our @CB_GLOBAL = (); # registry for all global events 211our @CB_GLOBAL = (); # registry for all global events
256our @CB_TYPE = (); # registry for type (cf-object class) based events 215our @CB_TYPE = (); # registry for type (cf-object class) based events
257our @CB_MAP = (); 216our @CB_MAP = ();
258 217
259my %attachment; 218my %attachment;
260 219
261sub _attach_cb($\%$$$) { 220sub _attach_cb($$$$) {
262 my ($registry, $undo, $event, $prio, $cb) = @_; 221 my ($registry, $event, $prio, $cb) = @_;
263 222
264 use sort 'stable'; 223 use sort 'stable';
265 224
266 $cb = [$prio, $cb]; 225 $cb = [$prio, $cb];
267 226
268 @{$registry->[$event]} = sort 227 @{$registry->[$event]} = sort
269 { $a->[0] cmp $b->[0] } 228 { $a->[0] cmp $b->[0] }
270 @{$registry->[$event] || []}, $cb; 229 @{$registry->[$event] || []}, $cb;
271
272 push @{$undo->{cb}}, [$event, $cb];
273} 230}
274 231
275# attach handles attaching event callbacks 232# attach handles attaching event callbacks
276# the only thing the caller has to do is pass the correct 233# the only thing the caller has to do is pass the correct
277# registry (== where the callback attaches to). 234# registry (== where the callback attaches to).
278sub _attach(\@$@) { 235sub _attach {
279 my ($registry, $klass, @arg) = @_; 236 my ($registry, $klass, @arg) = @_;
280 237
238 my $object_type;
281 my $prio = 0; 239 my $prio = 0;
282
283 my %undo = (
284 registry => $registry,
285 cb => [],
286 );
287
288 my %cb_id = map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == $klass, 0 .. $#EVENT; 240 my %cb_id = map +("on_" . lc $EVENT[$_][0], $_) , grep $EVENT[$_][1] == $klass, 0 .. $#EVENT;
289 241
290 while (@arg) { 242 while (@arg) {
291 my $type = shift @arg; 243 my $type = shift @arg;
292 244
293 if ($type eq "prio") { 245 if ($type eq "prio") {
294 $prio = shift @arg; 246 $prio = shift @arg;
295 247
248 } elsif ($type eq "type") {
249 $object_type = shift @arg;
250 $registry = $CB_TYPE[$object_type] ||= [];
251
252 } elsif ($type eq "subtype") {
253 defined $object_type or Carp::croak "subtype specified without type";
254 my $object_subtype = shift @arg;
255 $registry = $CB_TYPE[$object_type + $object_subtype * NUM_SUBTYPES] ||= [];
256
296 } elsif ($type eq "package") { 257 } elsif ($type eq "package") {
297 my $pkg = shift @arg; 258 my $pkg = shift @arg;
298 259
299 while (my ($name, $id) = each %cb_id) { 260 while (my ($name, $id) = each %cb_id) {
300 if (my $cb = $pkg->can ($name)) { 261 if (my $cb = $pkg->can ($name)) {
301 _attach_cb $registry, %undo, $id, $prio, $cb; 262 _attach_cb $registry, $id, $prio, $cb;
302 } 263 }
303 } 264 }
304 265
305 } elsif (exists $cb_id{$type}) { 266 } elsif (exists $cb_id{$type}) {
306 _attach_cb $registry, %undo, $cb_id{$type}, $prio, shift @arg; 267 _attach_cb $registry, $cb_id{$type}, $prio, shift @arg;
307 268
308 } elsif (ref $type) { 269 } elsif (ref $type) {
309 warn "attaching objects not supported, ignoring.\n"; 270 warn "attaching objects not supported, ignoring.\n";
310 271
311 } else { 272 } else {
312 shift @arg; 273 shift @arg;
313 warn "attach argument '$type' not supported, ignoring.\n"; 274 warn "attach argument '$type' not supported, ignoring.\n";
314 } 275 }
315 } 276 }
316
317 \%undo
318} 277}
319 278
320sub _attach_attachment { 279sub _object_attach {
321 my ($obj, $name, %arg) = @_; 280 my ($obj, $name, %arg) = @_;
322 281
323 return if exists $obj->{_attachment}{$name}; 282 return if exists $obj->{_attachment}{$name};
324
325 my $res;
326 283
327 if (my $attach = $attachment{$name}) { 284 if (my $attach = $attachment{$name}) {
328 my $registry = $obj->registry; 285 my $registry = $obj->registry;
329 286
330 for (@$attach) { 287 for (@$attach) {
331 my ($klass, @attach) = @$_; 288 my ($klass, @attach) = @$_;
332 $res = _attach @$registry, $klass, @attach; 289 _attach $registry, $klass, @attach;
333 } 290 }
334 291
335 $obj->{$name} = \%arg; 292 $obj->{$name} = \%arg;
336 } else { 293 } else {
337 warn "object uses attachment '$name' that is not available, postponing.\n"; 294 warn "object uses attachment '$name' that is not available, postponing.\n";
338 } 295 }
339 296
340 $obj->{_attachment}{$name} = undef; 297 $obj->{_attachment}{$name} = undef;
341
342 $res->{attachment} = $name;
343 $res
344} 298}
345 299
346*cf::object::attach = 300sub cf::attachable::attach {
347*cf::player::attach = 301 if (ref $_[0]) {
348*cf::client::attach = 302 _object_attach @_;
349*cf::map::attach = sub { 303 } else {
350 my ($obj, $name, %arg) = @_; 304 _attach shift->_attach_registry, @_;
351 305 }
352 _attach_attachment $obj, $name, %arg;
353}; 306};
354 307
355# all those should be optimised 308# all those should be optimised
356*cf::object::detach = 309sub cf::attachable::detach {
357*cf::player::detach =
358*cf::client::detach =
359*cf::map::detach = sub {
360 my ($obj, $name) = @_; 310 my ($obj, $name) = @_;
361 311
312 if (ref $obj) {
362 delete $obj->{_attachment}{$name}; 313 delete $obj->{_attachment}{$name};
363 reattach ($obj); 314 reattach ($obj);
315 } else {
316 Carp::croak "cannot, currently, detach class attachments";
317 }
364}; 318};
365 319
366*cf::object::attached = 320sub cf::attachable::attached {
367*cf::player::attached =
368*cf::client::attached =
369*cf::map::attached = sub {
370 my ($obj, $name) = @_; 321 my ($obj, $name) = @_;
371 322
372 exists $obj->{_attachment}{$name} 323 exists $obj->{_attachment}{$name}
373};
374
375sub attach_global {
376 _attach @CB_GLOBAL, KLASS_GLOBAL, @_
377} 324}
378 325
379sub attach_to_type { 326for my $klass (qw(GLOBAL OBJECT PLAYER CLIENT MAP)) {
380 my $type = shift; 327 eval "#line " . __LINE__ . " 'cf.pm'
381 my $subtype = shift; 328 sub cf::\L$klass\E::_attach_registry {
329 (\\\@CB_$klass, KLASS_$klass)
330 }
382 331
383 _attach @{$CB_TYPE[$type + $subtype * NUM_SUBTYPES]}, KLASS_OBJECT, @_ 332 sub cf::\L$klass\E::attachment {
384}
385
386sub attach_to_objects {
387 _attach @CB_OBJECT, KLASS_OBJECT, @_
388}
389
390sub attach_to_players {
391 _attach @CB_PLAYER, KLASS_PLAYER, @_
392}
393
394sub attach_to_clients {
395 _attach @CB_CLIENT, KLASS_CLIENT, @_
396}
397
398sub attach_to_maps {
399 _attach @CB_MAP, KLASS_MAP, @_
400}
401
402sub register_attachment {
403 my $name = shift; 333 my \$name = shift;
404 334
405 $attachment{$name} = [[KLASS_OBJECT, @_]];
406}
407
408sub register_player_attachment {
409 my $name = shift;
410
411 $attachment{$name} = [[KLASS_PLAYER, @_]];
412}
413
414sub register_client_attachment {
415 my $name = shift;
416
417 $attachment{$name} = [[KLASS_CLIENT, @_]];
418}
419
420sub register_map_attachment {
421 my $name = shift;
422
423 $attachment{$name} = [[KLASS_MAP, @_]]; 335 \$attachment{\$name} = [[KLASS_$klass, \@_]];
336 }
337 ";
338 die if $@;
424} 339}
425 340
426our $override; 341our $override;
427our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals? 342our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals?
428 343
474 389
475=cut 390=cut
476 391
477############################################################################# 392#############################################################################
478 393
479=head2 METHODS VALID FOR ALL CORE OBJECTS 394=head2 METHODS VALID FOR ALL ATTACHABLE OBJECTS
395
396Attachable objects includes objects, players, clients and maps.
480 397
481=over 4 398=over 4
482 399
483=item $object->valid, $player->valid, $client->valid, $map->valid 400=item $object->valid
484 401
485Just because you have a perl object does not mean that the corresponding 402Just because you have a perl object does not mean that the corresponding
486C-level object still exists. If you try to access an object that has no 403C-level object still exists. If you try to access an object that has no
487valid C counterpart anymore you get an exception at runtime. This method 404valid C counterpart anymore you get an exception at runtime. This method
488can be used to test for existence of the C object part without causing an 405can be used to test for existence of the C object part without causing an
490 407
491=back 408=back
492 409
493=cut 410=cut
494 411
495*cf::object::valid =
496*cf::player::valid =
497*cf::client::valid =
498*cf::map::valid = \&cf::_valid;
499
500############################################################################# 412#############################################################################
501# object support 413# object support
502 414
503sub instantiate { 415sub instantiate {
504 my ($obj, $data) = @_; 416 my ($obj, $data) = @_;
523 435
524 for my $name (keys %{ $obj->{_attachment} || {} }) { 436 for my $name (keys %{ $obj->{_attachment} || {} }) {
525 if (my $attach = $attachment{$name}) { 437 if (my $attach = $attachment{$name}) {
526 for (@$attach) { 438 for (@$attach) {
527 my ($klass, @attach) = @$_; 439 my ($klass, @attach) = @$_;
528 _attach @$registry, $klass, @attach; 440 _attach $registry, $klass, @attach;
529 } 441 }
530 } else { 442 } else {
531 warn "object uses attachment '$name' that is not available, postponing.\n"; 443 warn "object uses attachment '$name' that is not available, postponing.\n";
532 } 444 }
533 } 445 }
589 } 501 }
590 502
591 () 503 ()
592} 504}
593 505
594attach_to_objects 506cf::object->attach (
595 prio => -1000000, 507 prio => -1000000,
596 on_clone => sub { 508 on_clone => sub {
597 my ($src, $dst) = @_; 509 my ($src, $dst) = @_;
598 510
599 @{$dst->registry} = @{$src->registry}; 511 @{$dst->registry} = @{$src->registry};
601 %$dst = %$src; 513 %$dst = %$src;
602 514
603 %{$dst->{_attachment}} = %{$src->{_attachment}} 515 %{$dst->{_attachment}} = %{$src->{_attachment}}
604 if exists $src->{_attachment}; 516 if exists $src->{_attachment};
605 }, 517 },
606; 518);
607 519
608############################################################################# 520#############################################################################
609# command handling &c 521# command handling &c
610 522
611=item cf::register_command $name => \&callback($ob,$args); 523=item cf::register_command $name => \&callback($ob,$args);
640 #warn "registering extcmd '$name' to '$caller'"; 552 #warn "registering extcmd '$name' to '$caller'";
641 553
642 $EXTCMD{$name} = [$cb, $caller]; 554 $EXTCMD{$name} = [$cb, $caller];
643} 555}
644 556
645attach_to_players 557cf::player->attach (
646 on_command => sub { 558 on_command => sub {
647 my ($pl, $name, $params) = @_; 559 my ($pl, $name, $params) = @_;
648 560
649 my $cb = $COMMAND{$name} 561 my $cb = $COMMAND{$name}
650 or return; 562 or return;
670 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n"; 582 warn "player " . ($pl->ob->name) . " sent unparseable ext message: <$buf>\n";
671 } 583 }
672 584
673 cf::override; 585 cf::override;
674 }, 586 },
675; 587);
676 588
677sub register { 589sub register {
678 my ($base, $pkg) = @_; 590 my ($base, $pkg) = @_;
679 591
680 #TODO 592 #TODO
770 defined $path or return; 682 defined $path or return;
771 683
772 unlink "$path.pst"; 684 unlink "$path.pst";
773}; 685};
774 686
775attach_to_maps prio => -10000, package => cf::mapsupport::; 687cf::map->attach (prio => -10000, package => cf::mapsupport::);
776 688
777############################################################################# 689#############################################################################
778# load/save perl data associated with player->ob objects 690# load/save perl data associated with player->ob objects
779 691
780sub all_objects(@) { 692sub all_objects(@) {
781 @_, map all_objects ($_->inv), @_ 693 @_, map all_objects ($_->inv), @_
782} 694}
783 695
784# TODO: compatibility cruft, remove when no longer needed 696# TODO: compatibility cruft, remove when no longer needed
785attach_to_players 697cf::player->attach (
786 on_load => sub { 698 on_load => sub {
787 my ($pl, $path) = @_; 699 my ($pl, $path) = @_;
788 700
789 for my $o (all_objects $pl->ob) { 701 for my $o (all_objects $pl->ob) {
790 if (my $value = $o->get_ob_key_value ("_perl_data")) { 702 if (my $value = $o->get_ob_key_value ("_perl_data")) {
792 704
793 %$o = %{ Storable::thaw pack "H*", $value }; 705 %$o = %{ Storable::thaw pack "H*", $value };
794 } 706 }
795 } 707 }
796 }, 708 },
797; 709);
798 710
799############################################################################# 711#############################################################################
800 712
801=head2 CORE EXTENSIONS 713=head2 CORE EXTENSIONS
802 714
1078 $DB->{$_[0]} = $_[1]; 990 $DB->{$_[0]} = $_[1];
1079 } 991 }
1080 db_dirty; 992 db_dirty;
1081 } 993 }
1082 994
1083 attach_global 995 cf::global->attach (
1084 prio => 10000, 996 prio => 10000,
1085 on_cleanup => sub { 997 on_cleanup => sub {
1086 db_sync; 998 db_sync;
1087 }, 999 },
1088 ; 1000 );
1089} 1001}
1090 1002
1091############################################################################# 1003#############################################################################
1092# the server's main() 1004# the server's main()
1093 1005

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines