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.429 by root, Sat May 3 15:17:13 2008 UTC vs.
Revision 1.435 by root, Thu May 29 03:33:20 2008 UTC

25use strict; 25use strict;
26 26
27use Symbol; 27use Symbol;
28use List::Util; 28use List::Util;
29use Socket; 29use Socket;
30use EV 3.2; 30use EV;
31use Opcode; 31use Opcode;
32use Safe; 32use Safe;
33use Safe::Hole; 33use Safe::Hole;
34use Storable (); 34use Storable ();
35 35
36use Coro 4.50 (); 36use Coro ();
37use Coro::State; 37use Coro::State;
38use Coro::Handle; 38use Coro::Handle;
39use Coro::EV; 39use Coro::AnyEvent;
40use Coro::Timer; 40use Coro::Timer;
41use Coro::Signal; 41use Coro::Signal;
42use Coro::Semaphore; 42use Coro::Semaphore;
43use Coro::AnyEvent;
43use Coro::AIO; 44use Coro::AIO;
44use Coro::BDB; 45use Coro::BDB;
45use Coro::Storable; 46use Coro::Storable;
46use Coro::Util (); 47use Coro::Util ();
47 48
49use BDB (); 50use BDB ();
50use Data::Dumper; 51use Data::Dumper;
51use Digest::MD5; 52use Digest::MD5;
52use Fcntl; 53use Fcntl;
53use YAML (); 54use YAML ();
54use IO::AIO 2.51 (); 55use IO::AIO ();
55use Time::HiRes; 56use Time::HiRes;
56use Compress::LZF; 57use Compress::LZF;
57use Digest::MD5 (); 58use Digest::MD5 ();
59
60AnyEvent::detect;
58 61
59# configure various modules to our taste 62# configure various modules to our taste
60# 63#
61$Storable::canonical = 1; # reduce rsync transfers 64$Storable::canonical = 1; # reduce rsync transfers
62Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator 65Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator
90our $RANDOMDIR = "$LOCALDIR/random"; 93our $RANDOMDIR = "$LOCALDIR/random";
91our $BDBDIR = "$LOCALDIR/db"; 94our $BDBDIR = "$LOCALDIR/db";
92our %RESOURCE; 95our %RESOURCE;
93 96
94our $TICK = MAX_TIME * 1e-6; # this is a CONSTANT(!) 97our $TICK = MAX_TIME * 1e-6; # this is a CONSTANT(!)
95our $AIO_POLL_WATCHER;
96our $NEXT_RUNTIME_WRITE; # when should the runtime file be written 98our $NEXT_RUNTIME_WRITE; # when should the runtime file be written
97our $NEXT_TICK; 99our $NEXT_TICK;
98our $USE_FSYNC = 1; # use fsync to write maps - default off 100our $USE_FSYNC = 1; # use fsync to write maps - default off
99 101
100our $BDB_POLL_WATCHER;
101our $BDB_DEADLOCK_WATCHER; 102our $BDB_DEADLOCK_WATCHER;
102our $BDB_CHECKPOINT_WATCHER; 103our $BDB_CHECKPOINT_WATCHER;
103our $BDB_TRICKLE_WATCHER; 104our $BDB_TRICKLE_WATCHER;
104our $DB_ENV; 105our $DB_ENV;
105 106
1523 $pl->{deny_save} = 1; 1524 $pl->{deny_save} = 1;
1524 $pl->password ("*"); # this should lock out the player until we nuked the dir 1525 $pl->password ("*"); # this should lock out the player until we nuked the dir
1525 1526
1526 $pl->invoke (cf::EVENT_PLAYER_LOGOUT, 1) if $pl->active; 1527 $pl->invoke (cf::EVENT_PLAYER_LOGOUT, 1) if $pl->active;
1527 $pl->deactivate; 1528 $pl->deactivate;
1529 my $killer = cf::arch::get "killer_quit"; $pl->killer ($killer); $killer->destroy;
1530 $pl->ob->check_score;
1528 $pl->invoke (cf::EVENT_PLAYER_QUIT); 1531 $pl->invoke (cf::EVENT_PLAYER_QUIT);
1529 $pl->ns->destroy if $pl->ns; 1532 $pl->ns->destroy if $pl->ns;
1530 1533
1531 my $path = playerdir $pl; 1534 my $path = playerdir $pl;
1532 my $temp = "$path~$cf::RUNTIME~deleting~"; 1535 my $temp = "$path~$cf::RUNTIME~deleting~";
2698} 2701}
2699 2702
2700sub prepare_random_map { 2703sub prepare_random_map {
2701 my ($exit) = @_; 2704 my ($exit) = @_;
2702 2705
2703 my $guard = cf::lock_acquire "exit_prepare:$exit";
2704
2705 # all this does is basically replace the /! path by 2706 # all this does is basically replace the /! path by
2706 # a new random map path (?random/...) with a seed 2707 # a new random map path (?random/...) with a seed
2707 # that depends on the exit object 2708 # that depends on the exit object
2708 2709
2709 my $rmp = parse_random_map_params $exit->msg; 2710 my $rmp = parse_random_map_params $exit->msg;
2711 if ($exit->map) { 2712 if ($exit->map) {
2712 $rmp->{region} = $exit->region->name; 2713 $rmp->{region} = $exit->region->name;
2713 $rmp->{origin_map} = $exit->map->path; 2714 $rmp->{origin_map} = $exit->map->path;
2714 $rmp->{origin_x} = $exit->x; 2715 $rmp->{origin_x} = $exit->x;
2715 $rmp->{origin_y} = $exit->y; 2716 $rmp->{origin_y} = $exit->y;
2717
2718 $exit->map->touch;
2716 } 2719 }
2717 2720
2718 $rmp->{random_seed} ||= $exit->random_seed; 2721 $rmp->{random_seed} ||= $exit->random_seed;
2719 2722
2720 my $data = JSON::XS->new->utf8->pretty->canonical->encode ($rmp); 2723 my $data = JSON::XS->new->utf8->pretty->canonical->encode ($rmp);
2724 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) { 2727 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) {
2725 aio_write $fh, 0, (length $data), $data, 0; 2728 aio_write $fh, 0, (length $data), $data, 0;
2726 undef $fh; 2729 undef $fh;
2727 aio_rename "$meta~", $meta; 2730 aio_rename "$meta~", $meta;
2728 2731
2732 my $slaying = "?random/$md5";
2733
2734 if ($exit->valid) {
2729 $exit->slaying ("?random/$md5"); 2735 $exit->slaying ("?random/$md5");
2730 $exit->msg (undef); 2736 $exit->msg (undef);
2737 }
2731 } 2738 }
2732} 2739}
2733 2740
2734sub cf::object::player::enter_exit { 2741sub cf::object::player::enter_exit {
2735 my ($self, $exit) = @_; 2742 my ($self, $exit) = @_;
2736 2743
2737 return unless $self->type == cf::PLAYER; 2744 return unless $self->type == cf::PLAYER;
2738 2745
2739 if ($exit->slaying eq "/!") {
2740 #TODO: this should de-fi-ni-te-ly not be a sync-job
2741 # the problem is that $exit might not survive long enough
2742 # so it needs to be done right now, right here
2743 cf::sync_job { prepare_random_map $exit };
2744 }
2745
2746 my $slaying = cf::map::normalise $exit->slaying, $exit->map && $exit->map->path;
2747 my $hp = $exit->stats->hp;
2748 my $sp = $exit->stats->sp;
2749
2750 $self->enter_link; 2746 $self->enter_link;
2751 2747
2752 # if exit is damned, update players death & WoR home-position
2753 $self->contr->savebed ($slaying, $hp, $sp)
2754 if $exit->flag (FLAG_DAMNED);
2755
2756 (async { 2748 (async {
2757 $Coro::current->{desc} = "enter_exit $slaying $hp $sp"; 2749 $Coro::current->{desc} = "enter_exit";
2758 2750
2759 $self->deactivate_recursive; # just to be sure
2760 unless (eval { 2751 unless (eval {
2752 $self->deactivate_recursive; # just to be sure
2753
2754 # random map handling
2755 {
2756 my $guard = cf::lock_acquire "exit_prepare:$exit";
2757
2758 prepare_random_map $exit
2759 if $exit->slaying eq "/!";
2760 }
2761
2762 my $map = cf::map::normalise $exit->slaying, $exit->map && $exit->map->path;
2763 my $x = $exit->stats->hp;
2764 my $y = $exit->stats->sp;
2765
2761 $self->goto ($slaying, $hp, $sp); 2766 $self->goto ($map, $x, $y);
2762 2767
2768 # if exit is damned, update players death & WoR home-position
2769 $self->contr->savebed ($map, $x, $y)
2770 if $exit->flag (cf::FLAG_DAMNED);
2771
2763 1; 2772 1
2764 }) { 2773 }) {
2765 $self->message ("Something went wrong deep within the crossfire server. " 2774 $self->message ("Something went wrong deep within the crossfire server. "
2766 . "I'll try to bring you back to the map you were before. " 2775 . "I'll try to bring you back to the map you were before. "
2767 . "Please report this to the dungeon master!", 2776 . "Please report this to the dungeon master!",
2768 cf::NDI_UNIQUE | cf::NDI_RED); 2777 cf::NDI_UNIQUE | cf::NDI_RED);
3115 3124
3116=cut 3125=cut
3117 3126
3118for ( 3127for (
3119 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y 3128 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y
3120 insert remove inv name archname title slaying race 3129 insert remove inv nrof name archname title slaying race
3121 decrease split destroy)], 3130 decrease split destroy)],
3122 ["cf::object::player" => qw(player)], 3131 ["cf::object::player" => qw(player)],
3123 ["cf::player" => qw(peaceful)], 3132 ["cf::player" => qw(peaceful)],
3124 ["cf::map" => qw(trigger)], 3133 ["cf::map" => qw(trigger)],
3125) { 3134) {
3387} 3396}
3388 3397
3389sub init { 3398sub init {
3390 my $guard = freeze_mainloop; 3399 my $guard = freeze_mainloop;
3391 3400
3401 evthread_start IO::AIO::poll_fileno;
3402
3392 reload_resources; 3403 reload_resources;
3393} 3404}
3394 3405
3395sub reload_config { 3406sub reload_config {
3396 open my $fh, "<:utf8", "$CONFDIR/config" 3407 open my $fh, "<:utf8", "$CONFDIR/config"
3428 reload_config; 3439 reload_config;
3429 db_init; 3440 db_init;
3430 load_extensions; 3441 load_extensions;
3431 3442
3432 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority 3443 $Coro::current->prio (Coro::PRIO_MAX); # give the main loop max. priority
3433 evthread_start IO::AIO::poll_fileno;
3434 } 3444 }
3435 3445
3436 EV::loop; 3446 EV::loop;
3437} 3447}
3438 3448
3779{ 3789{
3780 # configure BDB 3790 # configure BDB
3781 3791
3782 BDB::min_parallel 8; 3792 BDB::min_parallel 8;
3783 BDB::max_poll_reqs $TICK * 0.1; 3793 BDB::max_poll_reqs $TICK * 0.1;
3784 $Coro::BDB::WATCHER->priority (1); 3794 $AnyEvent::BDB::WATCHER->priority (1);
3785 3795
3786 unless ($DB_ENV) { 3796 unless ($DB_ENV) {
3787 $DB_ENV = BDB::db_env_create; 3797 $DB_ENV = BDB::db_env_create;
3788 $DB_ENV->set_flags (BDB::AUTO_COMMIT | BDB::REGION_INIT | BDB::TXN_NOSYNC 3798 $DB_ENV->set_flags (BDB::AUTO_COMMIT | BDB::REGION_INIT | BDB::TXN_NOSYNC
3789 | BDB::LOG_AUTOREMOVE, 1); 3799 | BDB::LOG_AUTOREMOVE, 1);
3820{ 3830{
3821 # configure IO::AIO 3831 # configure IO::AIO
3822 3832
3823 IO::AIO::min_parallel 8; 3833 IO::AIO::min_parallel 8;
3824 IO::AIO::max_poll_time $TICK * 0.1; 3834 IO::AIO::max_poll_time $TICK * 0.1;
3825 $Coro::AIO::WATCHER->priority (1); 3835 undef $AnyEvent::AIO::WATCHER;
3826} 3836}
3827 3837
3828my $_log_backtrace; 3838my $_log_backtrace;
3829 3839
3830sub _log_backtrace { 3840sub _log_backtrace {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines