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.419 by root, Sun Apr 13 01:34:09 2008 UTC vs.
Revision 1.434 by root, Thu May 29 03:27:37 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;
61
62IO::AIO::max_poll_reqs 1;#d#
58 63
59# configure various modules to our taste 64# configure various modules to our taste
60# 65#
61$Storable::canonical = 1; # reduce rsync transfers 66$Storable::canonical = 1; # reduce rsync transfers
62Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator 67Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator
90our $RANDOMDIR = "$LOCALDIR/random"; 95our $RANDOMDIR = "$LOCALDIR/random";
91our $BDBDIR = "$LOCALDIR/db"; 96our $BDBDIR = "$LOCALDIR/db";
92our %RESOURCE; 97our %RESOURCE;
93 98
94our $TICK = MAX_TIME * 1e-6; # this is a CONSTANT(!) 99our $TICK = MAX_TIME * 1e-6; # this is a CONSTANT(!)
95our $AIO_POLL_WATCHER;
96our $NEXT_RUNTIME_WRITE; # when should the runtime file be written 100our $NEXT_RUNTIME_WRITE; # when should the runtime file be written
97our $NEXT_TICK; 101our $NEXT_TICK;
98our $USE_FSYNC = 1; # use fsync to write maps - default off 102our $USE_FSYNC = 1; # use fsync to write maps - default off
99 103
100our $BDB_POLL_WATCHER;
101our $BDB_DEADLOCK_WATCHER; 104our $BDB_DEADLOCK_WATCHER;
102our $BDB_CHECKPOINT_WATCHER; 105our $BDB_CHECKPOINT_WATCHER;
103our $BDB_TRICKLE_WATCHER; 106our $BDB_TRICKLE_WATCHER;
104our $DB_ENV; 107our $DB_ENV;
105 108
427 } 430 }
428 } 431 }
429}; 432};
430 433
431sub get_slot($;$$) { 434sub get_slot($;$$) {
435 return if tick_inhibit || $Coro::current == $Coro::main;
436
432 my ($time, $pri, $name) = @_; 437 my ($time, $pri, $name) = @_;
433 438
434 $time = $TICK * .6 if $time > $TICK * .6; 439 $time = $TICK * .6 if $time > $TICK * .6;
435 my $sig = new Coro::Signal; 440 my $sig = new Coro::Signal;
436 441
1139 utf8::decode (my $decname = $filename); 1144 utf8::decode (my $decname = $filename);
1140 warn sprintf "saving %s (%d,%d)\n", 1145 warn sprintf "saving %s (%d,%d)\n",
1141 $decname, length $$rdata, scalar @$objs; 1146 $decname, length $$rdata, scalar @$objs;
1142 1147
1143 if (my $fh = aio_open "$filename~", O_WRONLY | O_CREAT, 0600) { 1148 if (my $fh = aio_open "$filename~", O_WRONLY | O_CREAT, 0600) {
1144 chmod SAVE_MODE, $fh; 1149 aio_chmod $fh, SAVE_MODE;
1145 aio_write $fh, 0, (length $$rdata), $$rdata, 0; 1150 aio_write $fh, 0, (length $$rdata), $$rdata, 0;
1146 aio_fsync $fh if $cf::USE_FSYNC; 1151 aio_fsync $fh if $cf::USE_FSYNC;
1147 close $fh; 1152 aio_close $fh;
1148 1153
1149 if (@$objs) { 1154 if (@$objs) {
1150 if (my $fh = aio_open "$filename.pst~", O_WRONLY | O_CREAT, 0600) { 1155 if (my $fh = aio_open "$filename.pst~", O_WRONLY | O_CREAT, 0600) {
1151 chmod SAVE_MODE, $fh; 1156 aio_chmod $fh, SAVE_MODE;
1152 my $data = Coro::Storable::nfreeze { version => 1, objs => $objs }; 1157 my $data = Coro::Storable::nfreeze { version => 1, objs => $objs };
1153 aio_write $fh, 0, (length $data), $data, 0; 1158 aio_write $fh, 0, (length $data), $data, 0;
1154 aio_fsync $fh if $cf::USE_FSYNC; 1159 aio_fsync $fh if $cf::USE_FSYNC;
1155 close $fh; 1160 aio_close $fh;
1156 aio_rename "$filename.pst~", "$filename.pst"; 1161 aio_rename "$filename.pst~", "$filename.pst";
1157 } 1162 }
1158 } else { 1163 } else {
1159 aio_unlink "$filename.pst"; 1164 aio_unlink "$filename.pst";
1160 } 1165 }
1454 my $f = new_from_file cf::object::thawer path $login 1459 my $f = new_from_file cf::object::thawer path $login
1455 or return; 1460 or return;
1456 1461
1457 my $pl = cf::player::load_pl $f 1462 my $pl = cf::player::load_pl $f
1458 or return; 1463 or return;
1464
1459 local $cf::PLAYER_LOADING{$login} = $pl; 1465 local $cf::PLAYER_LOADING{$login} = $pl;
1460 $f->resolve_delayed_derefs; 1466 $f->resolve_delayed_derefs;
1461 $cf::PLAYER{$login} = $pl 1467 $cf::PLAYER{$login} = $pl
1462 } 1468 }
1463 } 1469 }
1473 1479
1474 return if $pl->{deny_save}; 1480 return if $pl->{deny_save};
1475 1481
1476 aio_mkdir playerdir $pl, 0770; 1482 aio_mkdir playerdir $pl, 0770;
1477 $pl->{last_save} = $cf::RUNTIME; 1483 $pl->{last_save} = $cf::RUNTIME;
1484
1485 cf::get_slot 0.01;
1478 1486
1479 $pl->save_pl ($path); 1487 $pl->save_pl ($path);
1480 cf::cede_to_tick; 1488 cf::cede_to_tick;
1481} 1489}
1482 1490
1518 $pl->{deny_save} = 1; 1526 $pl->{deny_save} = 1;
1519 $pl->password ("*"); # this should lock out the player until we nuked the dir 1527 $pl->password ("*"); # this should lock out the player until we nuked the dir
1520 1528
1521 $pl->invoke (cf::EVENT_PLAYER_LOGOUT, 1) if $pl->active; 1529 $pl->invoke (cf::EVENT_PLAYER_LOGOUT, 1) if $pl->active;
1522 $pl->deactivate; 1530 $pl->deactivate;
1531 my $killer = cf::arch::get "killer_quit"; $pl->killer ($killer); $killer->destroy;
1532 $pl->ob->check_score;
1523 $pl->invoke (cf::EVENT_PLAYER_QUIT); 1533 $pl->invoke (cf::EVENT_PLAYER_QUIT);
1524 $pl->ns->destroy if $pl->ns; 1534 $pl->ns->destroy if $pl->ns;
1525 1535
1526 my $path = playerdir $pl; 1536 my $path = playerdir $pl;
1527 my $temp = "$path~$cf::RUNTIME~deleting~"; 1537 my $temp = "$path~$cf::RUNTIME~deleting~";
1566 1576
1567 for my $login (@$dirs) { 1577 for my $login (@$dirs) {
1568 my $path = path $login; 1578 my $path = path $login;
1569 1579
1570 # a .pst is a dead give-away for a valid player 1580 # a .pst is a dead give-away for a valid player
1571 unless (-e "$path.pst") { 1581 # if no pst file found, open and chekc for blocked users
1582 if (aio_stat "$path.pst") {
1572 my $fh = aio_open $path, Fcntl::O_RDONLY, 0 or next; 1583 my $fh = aio_open $path, Fcntl::O_RDONLY, 0 or next;
1573 aio_read $fh, 0, 512, my $buf, 0 or next; 1584 aio_read $fh, 0, 512, my $buf, 0 or next;
1574 $buf !~ /^password -------------$/m or next; # official not-valid tag 1585 $buf !~ /^password -------------$/m or next; # official not-valid tag
1575 } 1586 }
1576 1587
2025 2036
2026 cf::lock_wait "map_data:$path";#d#remove 2037 cf::lock_wait "map_data:$path";#d#remove
2027 cf::lock_wait "map_find:$path"; 2038 cf::lock_wait "map_find:$path";
2028 2039
2029 $cf::MAP{$path} || do { 2040 $cf::MAP{$path} || do {
2030 my $guard1 = cf::lock_acquire "map_find:$path";
2031 my $guard2 = cf::lock_acquire "map_data:$path"; # just for the fun of it 2041 my $guard1 = cf::lock_acquire "map_data:$path"; # just for the fun of it
2042 my $guard2 = cf::lock_acquire "map_find:$path";
2032 2043
2033 my $map = new_from_path cf::map $path 2044 my $map = new_from_path cf::map $path
2034 or return; 2045 or return;
2035 2046
2036 $map->{last_save} = $cf::RUNTIME; 2047 $map->{last_save} = $cf::RUNTIME;
2039 or return; 2050 or return;
2040 2051
2041 if ($map->should_reset) {#d#TODO# disabled, crashy (locking issue?) 2052 if ($map->should_reset) {#d#TODO# disabled, crashy (locking issue?)
2042 # doing this can freeze the server in a sync job, obviously 2053 # doing this can freeze the server in a sync job, obviously
2043 #$cf::WAIT_FOR_TICK->wait; 2054 #$cf::WAIT_FOR_TICK->wait;
2055 undef $guard2;
2044 undef $guard1; 2056 undef $guard1;
2045 undef $guard2;
2046 $map->reset; 2057 $map->reset;
2047 return find $path; 2058 return find $path;
2048 } 2059 }
2049 2060
2050 $cf::MAP{$path} = $map 2061 $cf::MAP{$path} = $map
2113 } 2124 }
2114 2125
2115 $self->{last_save} = $cf::RUNTIME; 2126 $self->{last_save} = $cf::RUNTIME;
2116 $self->last_access ($cf::RUNTIME); 2127 $self->last_access ($cf::RUNTIME);
2117 2128
2118 $self->in_memory (cf::MAP_IN_MEMORY); 2129 $self->in_memory (cf::MAP_ACTIVE);
2119 } 2130 }
2120 2131
2121 $self->post_load; 2132 $self->post_load;
2122} 2133}
2123 2134
2181 my ($path, $origin, $load) = @_; 2192 my ($path, $origin, $load) = @_;
2182 2193
2183 $path = normalise $path, $origin && $origin->{path}; 2194 $path = normalise $path, $origin && $origin->{path};
2184 2195
2185 if (my $map = $cf::MAP{$path}) { 2196 if (my $map = $cf::MAP{$path}) {
2186 return $map if !$load || $map->in_memory == cf::MAP_IN_MEMORY; 2197 return $map if !$load || $map->in_memory == cf::MAP_ACTIVE;
2187 } 2198 }
2188 2199
2189 $MAP_PREFETCH{$path} |= $load; 2200 $MAP_PREFETCH{$path} |= $load;
2190 2201
2191 $MAP_PREFETCHER ||= cf::async { 2202 $MAP_PREFETCHER ||= cf::async {
2228 cf::async { 2239 cf::async {
2229 $Coro::current->{desc} = "map player save"; 2240 $Coro::current->{desc} = "map player save";
2230 $_->contr->save for $self->players; 2241 $_->contr->save for $self->players;
2231 }; 2242 };
2232 2243
2244 cf::get_slot 0.02;
2245
2233 if ($uniq) { 2246 if ($uniq) {
2234 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS); 2247 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS);
2235 $self->_save_objects ($uniq, cf::IO_UNIQUES); 2248 $self->_save_objects ($uniq, cf::IO_UNIQUES);
2236 } else { 2249 } else {
2237 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES); 2250 $self->_save_objects ($save, cf::IO_HEADER | cf::IO_OBJECTS | cf::IO_UNIQUES);
2245 $self->save; 2258 $self->save;
2246 2259
2247 my $lock = cf::lock_acquire "map_data:$self->{path}"; 2260 my $lock = cf::lock_acquire "map_data:$self->{path}";
2248 2261
2249 return if $self->players; 2262 return if $self->players;
2250 return if $self->in_memory != cf::MAP_IN_MEMORY; 2263 return if $self->in_memory != cf::MAP_ACTIVE;
2251 return if $self->{deny_save}; 2264 return if $self->{deny_save};
2252 2265
2253 $self->in_memory (cf::MAP_SWAPPED); 2266 $self->in_memory (cf::MAP_SWAPPED);
2254 2267
2255 $self->deactivate; 2268 $self->deactivate;
2451can be C<undef>. Does the right thing when the player is currently in a 2464can be C<undef>. Does the right thing when the player is currently in a
2452dialogue with the given NPC character. 2465dialogue with the given NPC character.
2453 2466
2454=cut 2467=cut
2455 2468
2469our $SAY_CHANNEL = {
2470 id => "say",
2471 title => "Map",
2472 reply => "say ",
2473 tooltip => "Things said to and replied from npcs near you and other players on the same map only.",
2474};
2475
2476our $CHAT_CHANNEL = {
2477 id => "chat",
2478 title => "Chat",
2479 reply => "chat ",
2480 tooltip => "Player chat and shouts, global to the server.",
2481};
2482
2456# rough implementation of a future "reply" method that works 2483# rough implementation of a future "reply" method that works
2457# with dialog boxes. 2484# with dialog boxes.
2458#TODO: the first argument must go, split into a $npc->reply_to ( method 2485#TODO: the first argument must go, split into a $npc->reply_to ( method
2459sub cf::object::player::reply($$$;$) { 2486sub cf::object::player::reply($$$;$) {
2460 my ($self, $npc, $msg, $flags) = @_; 2487 my ($self, $npc, $msg, $flags) = @_;
2471 my $dialog = $pl->{npc_dialog}; 2498 my $dialog = $pl->{npc_dialog};
2472 $dialog->{pl}->ext_msg ($dialog->{id}, update => msg => $dialog->{pl}->expand_cfpod ($msg)); 2499 $dialog->{pl}->ext_msg ($dialog->{id}, update => msg => $dialog->{pl}->expand_cfpod ($msg));
2473 2500
2474 } else { 2501 } else {
2475 $msg = $npc->name . " says: $msg" if $npc; 2502 $msg = $npc->name . " says: $msg" if $npc;
2476 $self->message ($msg, $flags); 2503 $self->send_msg ($SAY_CHANNEL => $msg, $flags);
2477 } 2504 }
2478 } 2505 }
2479} 2506}
2480 2507
2481=item $object->send_msg ($channel, $msg, $color, [extra...]) 2508=item $object->send_msg ($channel, $msg, $color, [extra...])
2676} 2703}
2677 2704
2678sub prepare_random_map { 2705sub prepare_random_map {
2679 my ($exit) = @_; 2706 my ($exit) = @_;
2680 2707
2681 my $guard = cf::lock_acquire "exit_prepare:$exit";
2682
2683 # all this does is basically replace the /! path by 2708 # all this does is basically replace the /! path by
2684 # a new random map path (?random/...) with a seed 2709 # a new random map path (?random/...) with a seed
2685 # that depends on the exit object 2710 # that depends on the exit object
2686 2711
2687 my $rmp = parse_random_map_params $exit->msg; 2712 my $rmp = parse_random_map_params $exit->msg;
2689 if ($exit->map) { 2714 if ($exit->map) {
2690 $rmp->{region} = $exit->region->name; 2715 $rmp->{region} = $exit->region->name;
2691 $rmp->{origin_map} = $exit->map->path; 2716 $rmp->{origin_map} = $exit->map->path;
2692 $rmp->{origin_x} = $exit->x; 2717 $rmp->{origin_x} = $exit->x;
2693 $rmp->{origin_y} = $exit->y; 2718 $rmp->{origin_y} = $exit->y;
2719
2720 $exit->map->touch;
2694 } 2721 }
2695 2722
2696 $rmp->{random_seed} ||= $exit->random_seed; 2723 $rmp->{random_seed} ||= $exit->random_seed;
2697 2724
2698 my $data = cf::encode_json $rmp; 2725 my $data = JSON::XS->new->utf8->pretty->canonical->encode ($rmp);
2699 my $md5 = Digest::MD5::md5_hex $data; 2726 my $md5 = Digest::MD5::md5_hex $data;
2700 my $meta = "$RANDOMDIR/$md5.meta"; 2727 my $meta = "$RANDOMDIR/$md5.meta";
2701 2728
2702 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) { 2729 if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) {
2703 aio_write $fh, 0, (length $data), $data, 0; 2730 aio_write $fh, 0, (length $data), $data, 0;
2704 undef $fh; 2731 undef $fh;
2705 aio_rename "$meta~", $meta; 2732 aio_rename "$meta~", $meta;
2706 2733
2734 my $slaying = "?random/$md5";
2735
2736 if ($exit->valid) {
2707 $exit->slaying ("?random/$md5"); 2737 $exit->slaying ("?random/$md5");
2708 $exit->msg (undef); 2738 $exit->msg (undef);
2739 }
2709 } 2740 }
2710} 2741}
2711 2742
2712sub cf::object::player::enter_exit { 2743sub cf::object::player::enter_exit {
2713 my ($self, $exit) = @_; 2744 my ($self, $exit) = @_;
2714 2745
2715 return unless $self->type == cf::PLAYER; 2746 return unless $self->type == cf::PLAYER;
2716 2747
2717 if ($exit->slaying eq "/!") {
2718 #TODO: this should de-fi-ni-te-ly not be a sync-job
2719 # the problem is that $exit might not survive long enough
2720 # so it needs to be done right now, right here
2721 cf::sync_job { prepare_random_map $exit };
2722 }
2723
2724 my $slaying = cf::map::normalise $exit->slaying, $exit->map && $exit->map->path;
2725 my $hp = $exit->stats->hp;
2726 my $sp = $exit->stats->sp;
2727
2728 $self->enter_link; 2748 $self->enter_link;
2729 2749
2730 # if exit is damned, update players death & WoR home-position
2731 $self->contr->savebed ($slaying, $hp, $sp)
2732 if $exit->flag (FLAG_DAMNED);
2733
2734 (async { 2750 (async {
2735 $Coro::current->{desc} = "enter_exit $slaying $hp $sp"; 2751 $Coro::current->{desc} = "enter_exit";
2736 2752
2737 $self->deactivate_recursive; # just to be sure
2738 unless (eval { 2753 unless (eval {
2754 $self->deactivate_recursive; # just to be sure
2755
2756 # random map handling
2757 {
2758 my $guard = cf::lock_acquire "exit_prepare:$exit";
2759
2760 prepare_random_map $exit
2761 if $exit->slaying eq "/!";
2762 }
2763
2764 my $map = cf::map::normalise $exit->slaying, $exit->map && $exit->map->path;
2765 my $x = $exit->stats->hp;
2766 my $y = $exit->stats->sp;
2767
2739 $self->goto ($slaying, $hp, $sp); 2768 $self->goto ($map, $x, $y);
2740 2769
2770 # if exit is damned, update players death & WoR home-position
2771 $self->contr->savebed ($map, $x, $y)
2772 if $exit->flag (cf::FLAG_DAMNED);
2773
2741 1; 2774 1
2742 }) { 2775 }) {
2743 $self->message ("Something went wrong deep within the crossfire server. " 2776 $self->message ("Something went wrong deep within the crossfire server. "
2744 . "I'll try to bring you back to the map you were before. " 2777 . "I'll try to bring you back to the map you were before. "
2745 . "Please report this to the dungeon master!", 2778 . "Please report this to the dungeon master!",
2746 cf::NDI_UNIQUE | cf::NDI_RED); 2779 cf::NDI_UNIQUE | cf::NDI_RED);
2826 id => "infobox", 2859 id => "infobox",
2827 title => "Map Info", 2860 title => "Map Info",
2828 reply => undef, 2861 reply => undef,
2829 tooltip => "Information related to the maps", 2862 tooltip => "Information related to the maps",
2830 }, 2863 },
2864 "c/party" => {
2865 id => "party",
2866 title => "Party",
2867 reply => "gsay ",
2868 tooltip => "Messages and chat related to your party",
2869 },
2831); 2870);
2832 2871
2833sub cf::client::send_msg { 2872sub cf::client::send_msg {
2834 my ($self, $channel, $msg, $color, @extra) = @_; 2873 my ($self, $channel, $msg, $color, @extra) = @_;
2835 2874
3072 3111
3073The following functions and methods are available within a safe environment: 3112The following functions and methods are available within a safe environment:
3074 3113
3075 cf::object 3114 cf::object
3076 contr pay_amount pay_player map x y force_find force_add destroy 3115 contr pay_amount pay_player map x y force_find force_add destroy
3077 insert remove name archname title slaying race decrease_ob_nr 3116 insert remove name archname title slaying race decrease split
3078 3117
3079 cf::object::player 3118 cf::object::player
3080 player 3119 player
3081 3120
3082 cf::player 3121 cf::player
3087 3126
3088=cut 3127=cut
3089 3128
3090for ( 3129for (
3091 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y 3130 ["cf::object" => qw(contr pay_amount pay_player map force_find force_add x y
3092 insert remove inv name archname title slaying race 3131 insert remove inv nrof name archname title slaying race
3093 decrease_ob_nr destroy)], 3132 decrease split destroy)],
3094 ["cf::object::player" => qw(player)], 3133 ["cf::object::player" => qw(player)],
3095 ["cf::player" => qw(peaceful)], 3134 ["cf::player" => qw(peaceful)],
3096 ["cf::map" => qw(trigger)], 3135 ["cf::map" => qw(trigger)],
3097) { 3136) {
3098 no strict 'refs'; 3137 no strict 'refs';
3306 while (my ($k, $v) = each %$want) { 3345 while (my ($k, $v) = each %$want) {
3307 $ns->fx_want ($k, $v); 3346 $ns->fx_want ($k, $v);
3308 } 3347 }
3309}; 3348};
3310 3349
3350sub load_resource_file($) {
3351 my $guard = lock_acquire "load_resource_file";
3352
3353 my $status = load_resource_file_ $_[0];
3354 get_slot 0.1, 100;
3355 cf::arch::commit_load;
3356
3357 $status
3358}
3359
3311sub reload_regions { 3360sub reload_regions {
3312 # HACK to clear player env face cache, we need some signal framework 3361 # HACK to clear player env face cache, we need some signal framework
3313 # for this (global event?) 3362 # for this (global event?)
3314 %ext::player_env::MUSIC_FACE_CACHE = (); 3363 %ext::player_env::MUSIC_FACE_CACHE = ();
3315 3364
3328} 3377}
3329 3378
3330sub reload_archetypes { 3379sub reload_archetypes {
3331 load_resource_file "$DATADIR/archetypes" 3380 load_resource_file "$DATADIR/archetypes"
3332 or die "unable to load archetypes\n"; 3381 or die "unable to load archetypes\n";
3333 #d# NEED to laod twice to resolve forward references
3334 # this really needs to be done in an extra post-pass
3335 # (which needs to be synchronous, so solve it differently)
3336 load_resource_file "$DATADIR/archetypes"
3337 or die "unable to load archetypes\n";
3338} 3382}
3339 3383
3340sub reload_treasures { 3384sub reload_treasures {
3341 load_resource_file "$DATADIR/treasures" 3385 load_resource_file "$DATADIR/treasures"
3342 or die "unable to load treasurelists\n"; 3386 or die "unable to load treasurelists\n";
3343} 3387}
3344 3388
3345sub reload_resources { 3389sub reload_resources {
3346 warn "reloading resource files...\n"; 3390 warn "reloading resource files...\n";
3347 3391
3392 reload_facedata;
3393 reload_archetypes;
3348 reload_regions; 3394 reload_regions;
3349 reload_facedata;
3350 #reload_archetypes;#d#
3351 reload_archetypes;
3352 reload_treasures; 3395 reload_treasures;
3353 3396
3354 warn "finished reloading resource files\n"; 3397 warn "finished reloading resource files\n";
3355} 3398}
3356 3399
3357sub init { 3400sub init {
3401 my $guard = freeze_mainloop;
3402
3358 reload_resources; 3403 reload_resources;
3359} 3404}
3360 3405
3361sub reload_config { 3406sub reload_config {
3362 open my $fh, "<:utf8", "$CONFDIR/config" 3407 open my $fh, "<:utf8", "$CONFDIR/config"
3387 $Coro::current->{desc} = "IDLE BUG HANDLER"; 3432 $Coro::current->{desc} = "IDLE BUG HANDLER";
3388 EV::loop EV::LOOP_ONESHOT; 3433 EV::loop EV::LOOP_ONESHOT;
3389 })->prio (Coro::PRIO_MAX); 3434 })->prio (Coro::PRIO_MAX);
3390 }; 3435 };
3391 3436
3437 {
3438 my $guard = freeze_mainloop;
3392 reload_config; 3439 reload_config;
3393 db_init; 3440 db_init;
3394 load_extensions; 3441 load_extensions;
3395 3442
3396 $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
3397 evthread_start IO::AIO::poll_fileno; 3444 }
3445
3398 EV::loop; 3446 EV::loop;
3399} 3447}
3400 3448
3401############################################################################# 3449#############################################################################
3402# initialisation and cleanup 3450# initialisation and cleanup
3684 3732
3685our @WAIT_FOR_TICK; 3733our @WAIT_FOR_TICK;
3686our @WAIT_FOR_TICK_BEGIN; 3734our @WAIT_FOR_TICK_BEGIN;
3687 3735
3688sub wait_for_tick { 3736sub wait_for_tick {
3689 return if tick_inhibit;
3690 return if $Coro::current == $Coro::main; 3737 return if tick_inhibit || $Coro::current == $Coro::main;
3691 3738
3692 my $signal = new Coro::Signal; 3739 my $signal = new Coro::Signal;
3693 push @WAIT_FOR_TICK, $signal; 3740 push @WAIT_FOR_TICK, $signal;
3694 $signal->wait; 3741 $signal->wait;
3695} 3742}
3696 3743
3697sub wait_for_tick_begin { 3744sub wait_for_tick_begin {
3698 return if tick_inhibit;
3699 return if $Coro::current == $Coro::main; 3745 return if tick_inhibit || $Coro::current == $Coro::main;
3700 3746
3701 my $signal = new Coro::Signal; 3747 my $signal = new Coro::Signal;
3702 push @WAIT_FOR_TICK_BEGIN, $signal; 3748 push @WAIT_FOR_TICK_BEGIN, $signal;
3703 $signal->wait; 3749 $signal->wait;
3704} 3750}
3743{ 3789{
3744 # configure BDB 3790 # configure BDB
3745 3791
3746 BDB::min_parallel 8; 3792 BDB::min_parallel 8;
3747 BDB::max_poll_reqs $TICK * 0.1; 3793 BDB::max_poll_reqs $TICK * 0.1;
3748 $Coro::BDB::WATCHER->priority (1); 3794 $AnyEvent::BDB::WATCHER->priority (1);
3749 3795
3750 unless ($DB_ENV) { 3796 unless ($DB_ENV) {
3751 $DB_ENV = BDB::db_env_create; 3797 $DB_ENV = BDB::db_env_create;
3752 $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
3753 | BDB::LOG_AUTOREMOVE, 1); 3799 | BDB::LOG_AUTOREMOVE, 1);
3784{ 3830{
3785 # configure IO::AIO 3831 # configure IO::AIO
3786 3832
3787 IO::AIO::min_parallel 8; 3833 IO::AIO::min_parallel 8;
3788 IO::AIO::max_poll_time $TICK * 0.1; 3834 IO::AIO::max_poll_time $TICK * 0.1;
3789 $Coro::AIO::WATCHER->priority (1); 3835 #undef $AnyEvent::AIO::WATCHER;
3790} 3836}
3791 3837
3792my $_log_backtrace; 3838my $_log_backtrace;
3793 3839
3794sub _log_backtrace { 3840sub _log_backtrace {
3832# load additional modules 3878# load additional modules
3833use cf::pod; 3879use cf::pod;
3834 3880
3835END { cf::emergency_save } 3881END { cf::emergency_save }
3836 3882
3883evthread_start IO::AIO::poll_fileno;
3884
38371 38851
3838 3886

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines