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.303 by root, Wed Jul 11 15:57:31 2007 UTC vs.
Revision 1.314 by root, Mon Jul 23 16:53:15 2007 UTC

166=item cf::wait_for_tick, cf::wait_for_tick_begin 166=item cf::wait_for_tick, cf::wait_for_tick_begin
167 167
168These are functions that inhibit the current coroutine one tick. cf::wait_for_tick_begin only 168These are functions that inhibit the current coroutine one tick. cf::wait_for_tick_begin only
169returns directly I<after> the tick processing (and consequently, can only wake one process 169returns directly I<after> the tick processing (and consequently, can only wake one process
170per tick), while cf::wait_for_tick wakes up all waiters after tick processing. 170per tick), while cf::wait_for_tick wakes up all waiters after tick processing.
171
172=item @cf::INVOKE_RESULTS
173
174This array contains the results of the last C<invoke ()> call. When
175C<cf::override> is called C<@cf::INVOKE_RESULTS> is set to the parameters of
176that call.
171 177
172=back 178=back
173 179
174=cut 180=cut
175 181
316 }; 322 };
317 $TICK_WATCHER->stop; 323 $TICK_WATCHER->stop;
318 $guard 324 $guard
319} 325}
320 326
327=item cf::get_slot $time[, $priority]
328
329Allocate $time seconds of blocking CPU time at priority C<$priority>:
330This call blocks and returns only when you have at least C<$time> seconds
331of cpu time till the next tick. The slot is only valid till the next cede.
332
333Useful for short background jobs.
334
335=cut
336
337our @SLOT_QUEUE;
338our $SLOT_QUEUE;
339
340$SLOT_QUEUE->cancel if $SLOT_QUEUE;
341$SLOT_QUEUE = Coro::async {
342 my $signal = new Coro::Signal;
343
344 while () {
345 next_job:
346 my $avail = cf::till_tick;
347 if ($avail > 0.01) {
348 for (0 .. $#SLOT_QUEUE) {
349 if ($SLOT_QUEUE[$_][0] < $avail) {
350 my $job = splice @SLOT_QUEUE, $_, 1, ();
351 $job->[2]->send;
352 Coro::cede;
353 goto next_job;
354 }
355 }
356 }
357
358 if (@SLOT_QUEUE) {
359 # we do not use wait_For_tick() as it returns immediately when tick is inactive
360 push @cf::WAIT_FOR_TICK, $signal;
361 $signal->wait;
362 } else {
363 Coro::schedule;
364 }
365 }
366};
367
368sub get_slot($;$) {
369 my ($time, $pri) = @_;
370
371 push @SLOT_QUEUE, [$time, $pri, my $sig = new Coro::Signal];
372 @SLOT_QUEUE = sort { $b->[1] <=> $a->[1] } @SLOT_QUEUE;
373 $SLOT_QUEUE->ready;
374 $sig->wait;
375}
376
321=item cf::async { BLOCK } 377=item cf::async { BLOCK }
322 378
323Currently the same as Coro::async_pool, meaning you cannot use 379Currently the same as Coro::async_pool, meaning you cannot use
324C<on_destroy>, C<join> or other gimmicks on these coroutines. The only 380C<on_destroy>, C<join> or other gimmicks on these coroutines. The only
325thing you are allowed to do is call C<prio> on it. 381thing you are allowed to do is call C<prio> on it.
866 "; 922 ";
867 die if $@; 923 die if $@;
868} 924}
869 925
870our $override; 926our $override;
871our @invoke_results = (); # referenced from .xs code. TODO: play tricks with reify and mortals? 927our @INVOKE_RESULTS = (); # referenced from .xs code. TODO: play tricks with reify and mortals?
872 928
873sub override { 929sub override {
874 $override = 1; 930 $override = 1;
875 @invoke_results = (); 931 @INVOKE_RESULTS = (@_);
876} 932}
877 933
878sub do_invoke { 934sub do_invoke {
879 my $event = shift; 935 my $event = shift;
880 my $callbacks = shift; 936 my $callbacks = shift;
881 937
882 @invoke_results = (); 938 @INVOKE_RESULTS = ();
883 939
884 local $override; 940 local $override;
885 941
886 for (@$callbacks) { 942 for (@$callbacks) {
887 eval { &{$_->[1]} }; 943 eval { &{$_->[1]} };
904 960
905Generate an object-specific event with the given arguments. 961Generate an object-specific event with the given arguments.
906 962
907This API is preliminary (most likely, the EVENT_CLASS_xxx prefix will be 963This API is preliminary (most likely, the EVENT_CLASS_xxx prefix will be
908removed in future versions), and there is no public API to access override 964removed in future versions), and there is no public API to access override
909results (if you must, access C<@cf::invoke_results> directly). 965results (if you must, access C<@cf::INVOKE_RESULTS> directly).
910 966
911=back 967=back
912 968
913=cut 969=cut
914 970
915############################################################################# 971#############################################################################
916# object support 972# object support
973#
974
975sub _can_merge {
976 my ($ob1, $ob2) = @_;
977
978 local $Storable::canonical = 1;
979 my $fob1 = Storable::freeze $ob1;
980 my $fob2 = Storable::freeze $ob2;
981
982 $fob1 eq $fob2
983}
917 984
918sub reattach { 985sub reattach {
919 # basically do the same as instantiate, without calling instantiate 986 # basically do the same as instantiate, without calling instantiate
920 my ($obj) = @_; 987 my ($obj) = @_;
921 988
1489 my ($path) = @_; 1556 my ($path) = @_;
1490 1557
1491 my ($match, $specificity); 1558 my ($match, $specificity);
1492 1559
1493 for my $region (list) { 1560 for my $region (list) {
1494 if ($region->match && $path =~ $region->match) { 1561 if ($region->{match} && $path =~ $region->{match}) {
1495 ($match, $specificity) = ($region, $region->specificity) 1562 ($match, $specificity) = ($region, $region->specificity)
1496 if $region->specificity > $specificity; 1563 if $region->specificity > $specificity;
1497 } 1564 }
1498 } 1565 }
1499 1566
1619 $self->init; # pass $1 etc. 1686 $self->init; # pass $1 etc.
1620 return $self; 1687 return $self;
1621 } 1688 }
1622 } 1689 }
1623 1690
1624 Carp::carp "unable to resolve path '$path' (base '$base')."; 1691 Carp::cluck "unable to resolve path '$path' (base '$base').";
1625 () 1692 ()
1626} 1693}
1627 1694
1628sub init { 1695sub init {
1629 my ($self) = @_; 1696 my ($self) = @_;
1907 1974
1908 undef $MAP_PREFETCH{$path}; 1975 undef $MAP_PREFETCH{$path};
1909 $MAP_PREFETCHER ||= cf::async { 1976 $MAP_PREFETCHER ||= cf::async {
1910 while (%MAP_PREFETCH) { 1977 while (%MAP_PREFETCH) {
1911 for my $path (keys %MAP_PREFETCH) { 1978 for my $path (keys %MAP_PREFETCH) {
1912 my $map = find $path 1979 if (my $map = find $path) {
1913 or next;
1914 $map->load; 1980 $map->load;
1981 }
1915 1982
1916 delete $MAP_PREFETCH{$path}; 1983 delete $MAP_PREFETCH{$path};
1917 } 1984 }
1918 } 1985 }
1919 undef $MAP_PREFETCHER; 1986 undef $MAP_PREFETCHER;
2256 2323
2257 local $self->{_prev_pos} = $link_pos; # ugly hack for rent.ext 2324 local $self->{_prev_pos} = $link_pos; # ugly hack for rent.ext
2258 $self->enter_map ($map, $x, $y); 2325 $self->enter_map ($map, $x, $y);
2259} 2326}
2260 2327
2261=item $player_object->goto ($path, $x, $y[, $check->($map)]) 2328=item $player_object->goto ($path, $x, $y[, $check->($map)[, $done->()]])
2262 2329
2263Moves the player to the given map-path and coordinates by first freezing 2330Moves the player to the given map-path and coordinates by first freezing
2264her, loading and preparing them map, calling the provided $check callback 2331her, loading and preparing them map, calling the provided $check callback
2265that has to return the map if sucecssful, and then unfreezes the player on 2332that has to return the map if sucecssful, and then unfreezes the player on
2266the new (success) or old (failed) map position. 2333the new (success) or old (failed) map position. In either case, $done will
2334be called at the end of this process.
2267 2335
2268=cut 2336=cut
2269 2337
2270our $GOTOGEN; 2338our $GOTOGEN;
2271 2339
2272sub cf::object::player::goto { 2340sub cf::object::player::goto {
2273 my ($self, $path, $x, $y, $check) = @_; 2341 my ($self, $path, $x, $y, $check, $done) = @_;
2274 2342
2275 # do generation counting so two concurrent goto's will be executed in-order 2343 # do generation counting so two concurrent goto's will be executed in-order
2276 my $gen = $self->{_goto_generation} = ++$GOTOGEN; 2344 my $gen = $self->{_goto_generation} = ++$GOTOGEN;
2277 2345
2278 $self->enter_link; 2346 $self->enter_link;
2298 2366
2299 if ($gen == $self->{_goto_generation}) { 2367 if ($gen == $self->{_goto_generation}) {
2300 delete $self->{_goto_generation}; 2368 delete $self->{_goto_generation};
2301 $self->leave_link ($map, $x, $y); 2369 $self->leave_link ($map, $x, $y);
2302 } 2370 }
2371
2372 $done->() if $done;
2303 })->prio (1); 2373 })->prio (1);
2304} 2374}
2305 2375
2306=item $player_object->enter_exit ($exit_object) 2376=item $player_object->enter_exit ($exit_object)
2307 2377
2416 2486
2417 utf8::encode $text; 2487 utf8::encode $text;
2418 $self->send_packet (sprintf "drawinfo %d %s", $flags || cf::NDI_BLACK, $text); 2488 $self->send_packet (sprintf "drawinfo %d %s", $flags || cf::NDI_BLACK, $text);
2419} 2489}
2420 2490
2421=item $client->send_msg ($color, $type, $msg, [extra...]) 2491=item $client->send_msg ($channel, $msg, $color, [extra...])
2422 2492
2423Send a drawinfo or msg packet to the client, formatting the msg for the 2493Send a drawinfo or msg packet to the client, formatting the msg for the
2424client if neccessary. C<$type> should be a string identifying the type of 2494client if neccessary. C<$type> should be a string identifying the type of
2425the message, with C<log> being the default. If C<$color> is negative, suppress 2495the message, with C<log> being the default. If C<$color> is negative, suppress
2426the message unless the client supports the msg packet. 2496the message unless the client supports the msg packet.
2427 2497
2428=cut 2498=cut
2429 2499
2430sub cf::client::send_msg { 2500sub cf::client::send_msg {
2431 my ($self, $color, $type, $msg, @extra) = @_; 2501 my ($self, $channel, $msg, $color, @extra) = @_;
2432 2502
2433 $msg = $self->pl->expand_cfpod ($msg); 2503 $msg = $self->pl->expand_cfpod ($msg);
2434 2504
2505 $color &= ~cf::NDI_UNIQUE; # just in case...
2506
2507 if (ref $channel) {
2508 # send meta info to client, if not yet sent
2509 unless (exists $self->{channel}{$channel->{id}}) {
2510 $self->{channel}{$channel->{id}} = $channel;
2511 $self->ext_event (channel_info => %$channel);
2512 }
2513
2514 $channel = $channel->{id};
2515 }
2516
2435 return unless @extra || length $msg; 2517 return unless @extra || length $msg;
2436 2518
2437 if ($self->can_msg) { 2519 if ($self->can_msg) {
2438 $self->send_packet ("msg " . $self->{json_coder}->encode ([$color, $type, $msg, @extra])); 2520 $self->send_packet ("msg " . $self->{json_coder}->encode ([$color, $channel, $msg, @extra]));
2439 } else { 2521 } else {
2440 # replace some tags by gcfclient-compatible ones 2522 # replace some tags by gcfclient-compatible ones
2441 for ($msg) { 2523 for ($msg) {
2442 1 while 2524 1 while
2443 s/<b>([^<]*)<\/b>/[b]${1}[\/b]/ 2525 s/<b>([^<]*)<\/b>/[b]${1}[\/b]/
2464 2546
2465=cut 2547=cut
2466 2548
2467sub cf::client::ext_event($$%) { 2549sub cf::client::ext_event($$%) {
2468 my ($self, $type, %msg) = @_; 2550 my ($self, $type, %msg) = @_;
2551
2552 return unless $self->extcmd;
2469 2553
2470 $msg{msgtype} = "event_$type"; 2554 $msg{msgtype} = "event_$type";
2471 $self->send_packet ("ext " . $self->{json_coder}->encode (\%msg)); 2555 $self->send_packet ("ext " . $self->{json_coder}->encode (\%msg));
2472} 2556}
2473 2557
2766 my $meta = $enc->encode ({ 2850 my $meta = $enc->encode ({
2767 name => $name, 2851 name => $name,
2768 type => $info->{type}, 2852 type => $info->{type},
2769 copyright => $info->{copyright}, #TODO# 2853 copyright => $info->{copyright}, #TODO#
2770 }); 2854 });
2771 my $data = pack "(w/a*)*", $meta, $info->{data};
2772 my $chk = Digest::MD5::md5 "$info->{chksum},$meta"; # mangle data checksum and metadata
2773 2855
2774 my $idx = (cf::face::find $name) || cf::face::alloc $name; 2856 my $idx = (cf::face::find $name) || cf::face::alloc $name;
2857
2858 if ($name =~ /\.jpg$/) {
2859 cf::face::set_data $idx, 0, $info->{data}, $info->{chksum};#d# temp hack
2860 cf::face::set_data $idx, 1, $info->{data}, $info->{chksum};#d# temp hack
2861 } else {
2862 my $data = pack "(w/a*)*", $meta, $info->{data};
2863 my $chk = Digest::MD5::md5 "$info->{chksum},$meta"; # mangle data checksum and metadata
2864
2775 cf::face::set_type $idx, 1; 2865 cf::face::set_type $idx, 1;
2776 cf::face::set_data $idx, 0, $data, $chk; 2866 cf::face::set_data $idx, 0, $data, $chk;
2867 }
2777 2868
2778 cf::cede_to_tick; 2869 cf::cede_to_tick;
2779 } 2870 }
2780 } 2871 }
2781 2872
2783} 2874}
2784 2875
2785sub reload_regions { 2876sub reload_regions {
2786 load_resource_file "$MAPDIR/regions" 2877 load_resource_file "$MAPDIR/regions"
2787 or die "unable to load regions file\n"; 2878 or die "unable to load regions file\n";
2879
2880 for (cf::region::list) {
2881 $_->{match} = qr/$_->{match}/
2882 if exists $_->{match};
2883 }
2788} 2884}
2789 2885
2790sub reload_facedata { 2886sub reload_facedata {
2791 load_facedata "$DATADIR/facedata" 2887 load_facedata "$DATADIR/facedata"
2792 or die "unable to load facedata\n"; 2888 or die "unable to load facedata\n";

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines