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.288 by root, Mon Jun 25 07:40:53 2007 UTC vs.
Revision 1.300 by root, Tue Jul 10 06:44:29 2007 UTC

248 248
249Converts a perl data structure into its JSON representation. 249Converts a perl data structure into its JSON representation.
250 250
251=cut 251=cut
252 252
253our $json_coder = JSON::XS->new->convert_blessed->utf8->max_size (1e6); # accept ~1mb max 253our $json_coder = JSON::XS->new->utf8->max_size (1e6); # accept ~1mb max
254 254
255sub to_json ($) { $json_coder->encode ($_[0]) } 255sub to_json ($) { $json_coder->encode ($_[0]) }
256sub from_json ($) { $json_coder->decode ($_[0]) } 256sub from_json ($) { $json_coder->decode ($_[0]) }
257 257
258=item cf::lock_wait $string 258=item cf::lock_wait $string
409Coro::Storable. May, of course, block. Note that the executed sub may 409Coro::Storable. May, of course, block. Note that the executed sub may
410never block itself or use any form of Event handling. 410never block itself or use any form of Event handling.
411 411
412=cut 412=cut
413 413
414sub _store_scalar {
415 open my $fh, ">", \my $buf
416 or die "fork_call: cannot open fh-to-buf in child : $!";
417 Storable::store_fd $_[0], $fh;
418 close $fh;
419
420 $buf
421}
422
414sub fork_call(&@) { 423sub fork_call(&@) {
415 my ($cb, @args) = @_; 424 my ($cb, @args) = @_;
416 425
417# socketpair my $fh1, my $fh2, Socket::AF_UNIX, Socket::SOCK_STREAM, Socket::PF_UNSPEC 426# socketpair my $fh1, my $fh2, Socket::AF_UNIX, Socket::SOCK_STREAM, Socket::PF_UNSPEC
418# or die "socketpair: $!"; 427# or die "socketpair: $!";
421 430
422 if (my $pid = fork) { 431 if (my $pid = fork) {
423 close $fh2; 432 close $fh2;
424 433
425 my $res = (Coro::Handle::unblock $fh1)->readline (undef); 434 my $res = (Coro::Handle::unblock $fh1)->readline (undef);
435 warn "pst<$res>" unless $res =~ /^pst/;
426 $res = Coro::Storable::thaw $res; 436 $res = Coro::Storable::thaw $res;
427 437
428 waitpid $pid, 0; # should not block anymore, we expect the child to simply behave 438 waitpid $pid, 0; # should not block anymore, we expect the child to simply behave
429 439
430 die $$res unless "ARRAY" eq ref $res; 440 Carp::confess $$res unless "ARRAY" eq ref $res;
431 441
432 return wantarray ? @$res : $res->[-1]; 442 return wantarray ? @$res : $res->[-1];
433 } else { 443 } else {
434 reset_signals; 444 reset_signals;
435 local $SIG{__WARN__}; 445 local $SIG{__WARN__};
436 local $SIG{__DIE__}; 446 local $SIG{__DIE__};
447 # just in case, this hack effectively disables event
448 # in the child. cleaner and slower would be canceling all watchers,
449 # but this works for the time being.
450 local $Coro::idle;
451 $Coro::current->prio (Coro::PRIO_MAX);
452
437 eval { 453 eval {
438 close $fh1; 454 close $fh1;
439 455
440 my @res = eval { $cb->(@args) }; 456 my @res = eval { $cb->(@args) };
457
441 syswrite $fh2, Coro::Storable::freeze +($@ ? \"$@" : \@res); 458 syswrite $fh2, _store_scalar $@ ? \"$@" : \@res;
459 close $fh2;
442 }; 460 };
443 461
444 warn $@ if $@; 462 warn $@ if $@;
445 _exit 0; 463 _exit 0;
446 } 464 }
1086 cf::override; 1104 cf::override;
1087 }, 1105 },
1088 on_extcmd => sub { 1106 on_extcmd => sub {
1089 my ($pl, $buf) = @_; 1107 my ($pl, $buf) = @_;
1090 1108
1091 my $msg = eval { from_json $buf }; 1109 my $msg = eval { $pl->ns->{json_coder}->decode ($buf) };
1092 1110
1093 if (ref $msg) { 1111 if (ref $msg) {
1094 if (my $cb = $EXTCMD{$msg->{msgtype}}) { 1112 if (my $cb = $EXTCMD{$msg->{msgtype}}) {
1095 if (my %reply = $cb->($pl, $msg)) { 1113 if (my %reply = $cb->($pl, $msg)) {
1096 $pl->ext_reply ($msg->{msgid}, %reply); 1114 $pl->ext_reply ($msg->{msgid}, %reply);
1400 # replace G<male|female> tags 1418 # replace G<male|female> tags
1401 || s{G<([^>|]*)\|([^>]*)>}{ 1419 || s{G<([^>|]*)\|([^>]*)>}{
1402 $self->gender ? $2 : $1 1420 $self->gender ? $2 : $1
1403 }ge 1421 }ge
1404 # replace H<hint text> 1422 # replace H<hint text>
1405 || s/H<([^\>]*)>/<fg name="lightblue">[$1]<\/fg>/g; 1423 || s{H<([^\>]*)>}
1424 {
1425 ("<fg name=\"lightblue\">[$1 (Use hintmode to suppress hints)]</fg>",
1426 "<fg name=\"lightblue\">[Hint suppressed, see hintmode]</fg>",
1427 "")
1428 [$self->{hintmode}]
1429 }ge;
1406 1430
1407 # create single paragraphs (very hackish) 1431 # create single paragraphs (very hackish)
1408 s/(?<=\S)\n(?=\w)/ /g; 1432 s/(?<=\S)\n(?=\w)/ /g;
1409 1433
1434 # compress some whitespace
1435 s/\s+\n/\n/g; # ws line-ends
1436 s/\n\n+/\n/g; # double lines
1437 s/^\n+//; # beginning lines
1438 s/\n+$//; # ending lines
1439
1440 warn $_;#d#
1410 $_ 1441 $_
1442}
1443
1444sub hintmode {
1445 $_[0]{hintmode} = $_[1] if @_ > 1;
1446 $_[0]{hintmode}
1411} 1447}
1412 1448
1413=item $player->ext_reply ($msgid, %msg) 1449=item $player->ext_reply ($msgid, %msg)
1414 1450
1415Sends an ext reply to the player. 1451Sends an ext reply to the player.
1418 1454
1419sub ext_reply($$%) { 1455sub ext_reply($$%) {
1420 my ($self, $id, %msg) = @_; 1456 my ($self, $id, %msg) = @_;
1421 1457
1422 $msg{msgid} = $id; 1458 $msg{msgid} = $id;
1423 $self->send ("ext " . cf::to_json \%msg); 1459 $self->send ("ext " . $self->ns->{json_coder}->encode (\%msg));
1424} 1460}
1425 1461
1426=item $player->ext_event ($type, %msg) 1462=item $player->ext_event ($type, %msg)
1427 1463
1428Sends an ext event to the client. 1464Sends an ext event to the client.
2340 my $hp = $exit->stats->hp; 2376 my $hp = $exit->stats->hp;
2341 my $sp = $exit->stats->sp; 2377 my $sp = $exit->stats->sp;
2342 2378
2343 $self->enter_link; 2379 $self->enter_link;
2344 2380
2381 # if exit is damned, update players death & WoR home-position
2382 $self->contr->savebed ($slaying, $hp, $sp)
2383 if $exit->flag (FLAG_DAMNED);
2384
2345 (async { 2385 (async {
2346 $self->deactivate_recursive; # just to be sure 2386 $self->deactivate_recursive; # just to be sure
2347 unless (eval { 2387 unless (eval {
2348 $self->goto ($slaying, $hp, $sp); 2388 $self->goto ($slaying, $hp, $sp);
2349 2389
2390sub cf::client::send_msg { 2430sub cf::client::send_msg {
2391 my ($self, $color, $type, $msg, @extra) = @_; 2431 my ($self, $color, $type, $msg, @extra) = @_;
2392 2432
2393 $msg = $self->pl->expand_cfpod ($msg); 2433 $msg = $self->pl->expand_cfpod ($msg);
2394 2434
2435 return unless @extra || length $msg;
2436
2395 if ($self->can_msg) { 2437 if ($self->can_msg) {
2396 $self->send_packet ("msg " . cf::to_json [$color, $type, $msg, @extra]); 2438 $self->send_packet ("msg " . $self->{json_coder}->encode ([$color, $type, $msg, @extra]));
2397 } else { 2439 } else {
2398 # replace some tags by gcfclient-compatible ones 2440 # replace some tags by gcfclient-compatible ones
2399 for ($msg) { 2441 for ($msg) {
2400 1 while 2442 1 while
2401 s/<b>([^<]*)<\/b>/[b]${1}[\/b]/ 2443 s/<b>([^<]*)<\/b>/[b]${1}[\/b]/
2424 2466
2425sub cf::client::ext_event($$%) { 2467sub cf::client::ext_event($$%) {
2426 my ($self, $type, %msg) = @_; 2468 my ($self, $type, %msg) = @_;
2427 2469
2428 $msg{msgtype} = "event_$type"; 2470 $msg{msgtype} = "event_$type";
2429 $self->send_packet ("ext " . cf::to_json \%msg); 2471 $self->send_packet ("ext " . $self->{json_coder}->encode (\%msg));
2430} 2472}
2431 2473
2432=item $success = $client->query ($flags, "text", \&cb) 2474=item $success = $client->query ($flags, "text", \&cb)
2433 2475
2434Queues a query to the client, calling the given callback with 2476Queues a query to the client, calling the given callback with
2457 2499
2458 1 2500 1
2459} 2501}
2460 2502
2461cf::client->attach ( 2503cf::client->attach (
2504 on_connect => sub {
2505 my ($ns) = @_;
2506
2507 $ns->{json_coder} = JSON::XS->new->utf8->max_size (1e6)->convert_blessed;
2508 },
2462 on_reply => sub { 2509 on_reply => sub {
2463 my ($ns, $msg) = @_; 2510 my ($ns, $msg) = @_;
2464 2511
2465 # this weird shuffling is so that direct followup queries 2512 # this weird shuffling is so that direct followup queries
2466 # get handled first 2513 # get handled first
2481 } 2528 }
2482 }, 2529 },
2483 on_exticmd => sub { 2530 on_exticmd => sub {
2484 my ($ns, $buf) = @_; 2531 my ($ns, $buf) = @_;
2485 2532
2486 my $msg = eval { from_json $buf }; 2533 my $msg = eval { $ns->{json_coder}->decode ($buf) };
2487 2534
2488 if (ref $msg) { 2535 if (ref $msg) {
2489 if (my $cb = $EXTICMD{$msg->{msgtype}}) { 2536 if (my $cb = $EXTICMD{$msg->{msgtype}}) {
2490 if (my %reply = $cb->($ns, $msg)) { 2537 if (my %reply = $cb->($ns, $msg)) {
2491 $reply{msgid} = $msg->{msgid}; 2538 $reply{msgid} = $msg->{msgid};
2492 $ns->send ("ext " . cf::to_json \%reply); 2539 $ns->send ("ext " . $ns->{json_coder}->encode (\%reply));
2493 } 2540 }
2494 } 2541 }
2495 } else { 2542 } else {
2496 warn "client " . ($ns->pl ? $ns->pl->ob->name : $ns->host) . " sent unparseable exti message: <$buf>\n"; 2543 warn "client " . ($ns->pl ? $ns->pl->ob->name : $ns->host) . " sent unparseable exti message: <$buf>\n";
2497 } 2544 }
2554 2601
2555=pod 2602=pod
2556 2603
2557The following functions and methods are available within a safe environment: 2604The following functions and methods are available within a safe environment:
2558 2605
2559 cf::object contr pay_amount pay_player map 2606 cf::object
2607 contr pay_amount pay_player map x y force_find force_add
2608 insert remove
2609
2560 cf::object::player player 2610 cf::object::player
2561 cf::player peaceful 2611 player
2562 cf::map trigger 2612
2613 cf::player
2614 peaceful
2615
2616 cf::map
2617 trigger
2563 2618
2564=cut 2619=cut
2565 2620
2566for ( 2621for (
2567 ["cf::object" => qw(contr pay_amount pay_player map)], 2622 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y
2623 insert remove)],
2568 ["cf::object::player" => qw(player)], 2624 ["cf::object::player" => qw(player)],
2569 ["cf::player" => qw(peaceful)], 2625 ["cf::player" => qw(peaceful)],
2570 ["cf::map" => qw(trigger)], 2626 ["cf::map" => qw(trigger)],
2571) { 2627) {
2572 no strict 'refs'; 2628 no strict 'refs';
2708 load_facedata "$DATADIR/facedata" 2764 load_facedata "$DATADIR/facedata"
2709 or die "unable to load facedata\n"; 2765 or die "unable to load facedata\n";
2710} 2766}
2711 2767
2712sub reload_archetypes { 2768sub reload_archetypes {
2769 load_resource_file "$DATADIR/archetypes"
2770 or die "unable to load archetypes\n";
2771 #d# NEED to laod twice to resolve forward references
2772 # this really needs to be done in an extra post-pass
2773 # (which needs to be synchronous, so solve it differently)
2713 load_resource_file "$DATADIR/archetypes" 2774 load_resource_file "$DATADIR/archetypes"
2714 or die "unable to load archetypes\n"; 2775 or die "unable to load archetypes\n";
2715} 2776}
2716 2777
2717sub reload_treasures { 2778sub reload_treasures {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines