--- deliantra/server/lib/cf.pm 2007/04/12 14:18:05 1.236 +++ deliantra/server/lib/cf.pm 2007/04/17 10:06:33 1.245 @@ -11,13 +11,14 @@ use Safe; use Safe::Hole; -use Coro 3.52 (); +use Coro 3.61 (); use Coro::State; use Coro::Event; use Coro::Timer; use Coro::Signal; use Coro::Semaphore; use Coro::AIO; +use Coro::Storable; use BDB (); use Data::Dumper; @@ -30,6 +31,7 @@ # configure various modules to our taste # +$Storable::canonical = 1; # reduce rsync transfers Coro::State::cctx_stacksize 256000; # 1-2MB stack, for deep recursions in maze generator Compress::LZF::sfreeze_cr { }; # prime Compress::LZF so it does not use require later @@ -54,7 +56,7 @@ our @EVENT; our $LIBDIR = datadir . "/ext"; -our $TICK = MAX_TIME * 1e-6; +our $TICK = MAX_TIME * 1e-6; # this is a CONSTANT(!) our $TICK_WATCHER; our $AIO_POLL_WATCHER; our $NEXT_RUNTIME_WRITE; # when should the runtime file be written @@ -76,9 +78,6 @@ our $RANDOM_MAPS = cf::localdir . "/random"; our $BDB_ENV_DIR = cf::localdir . "/db"; -our $WAIT_FOR_TICK; $WAIT_FOR_TICK ||= new Coro::Signal; -our $WAIT_FOR_TICK_ONE; $WAIT_FOR_TICK_ONE ||= new Coro::Signal; - # used to convert map paths into valid unix filenames by replacing / by ∕ our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons @@ -136,12 +135,11 @@ Configuration for the server, loaded from C, or from wherever your confdir points to. -=item $cf::WAIT_FOR_TICK, $cf::WAIT_FOR_TICK_ONE +=item cf::wait_for_tick, cf::wait_for_tick_begin -These are Coro::Signal objects that are C<< ->broadcast >> (WAIT_FOR_TICK) -or C<< ->send >> (WAIT_FOR_TICK_ONE) on after normal server tick -processing has been done. Call C<< ->wait >> on them to maximise the -window of cpu time available, or simply to synchronise to the server tick. +These are functions that inhibit the current coroutine one tick. cf::wait_for_tick_begin only +returns directly I the tick processing (and consequently, can only wake one process +per tick), while cf::wait_for_tick wakes up all waiters after tick processing. =back @@ -1159,10 +1157,36 @@ $self->ns->ext_event ($type, %msg); } -package cf; +=head3 cf::region -=back +=over 4 + +=cut + +package cf::region; + +=item cf::region::find_by_path $path + +Tries to decuce the probable region for a map knowing only its path. + +=cut + +sub find_by_path($) { + my ($path) = @_; + my ($match, $specificity); + + for my $region (list) { + if ($region->match && $path =~ $region->match) { + ($match, $specificity) = ($region, $region->specificity) + if $region->specificity > $specificity; + } + } + + $match +} + +=back =head3 cf::map @@ -1403,6 +1427,9 @@ $self->prepare_orig; } + $self->default_region (cf::region::find_by_path $self->{path}) + unless $self->default_region; + 1 } @@ -1454,6 +1481,7 @@ $self->alloc; $self->pre_load; + Coro::cede; $self->_load_objects ($self->{load_path}, 1) or return; @@ -1470,9 +1498,9 @@ } Coro::cede; - # now do the right thing for maps $self->link_multipart_objects; + Coro::cede; unless ($self->{deny_activate}) { $self->decay_objects; @@ -1484,9 +1512,11 @@ unless $self->difficulty; Coro::cede; $self->activate; + Coro::cede; } $self->post_load; + Coro::cede; $self->in_memory (cf::MAP_IN_MEMORY); } @@ -2313,9 +2343,7 @@ 0 < aio_load $path, $facedata or die "$path: $!"; - Coro::cede; - $facedata = Storable::thaw $facedata; - Coro::cede; + $facedata = Coro::Storable::thaw $facedata; $facedata->{version} == 2 or cf::cleanup "$path: version mismatch, cannot proceed."; @@ -2358,11 +2386,28 @@ 1 } +sub load_archetypes { + load_archetype_file sprintf "%s/archetypes", cf::datadir; # remove when stable + load_archetype_file sprintf "%s/archetypes", cf::datadir +} + +sub load_treasures { + load_treasure_file sprintf "%s/treasures", cf::datadir +} + sub reload_resources { + warn "reloading resource files...\n"; + load_resource_file sprintf "%s/%s/regions", cf::datadir, cf::mapdir - or die "unable to load regions file\n";#d# + or die "unable to load regions file\n"; load_facedata - or die "unable to load facedata\n";#d# + or die "unable to load facedata\n"; + load_archetypes + or die "unable to load archetypes\n"; + load_treasures + or die "unable to load treasurelists\n"; + + warn "finished reloading resource files\n"; } sub init { @@ -2616,6 +2661,27 @@ my $bug_warning = 0; +our @WAIT_FOR_TICK; +our @WAIT_FOR_TICK_BEGIN; + +sub wait_for_tick { + return unless $TICK_WATCHER->is_active; + return if $Coro::current == $Coro::main; + + my $signal = new Coro::Signal; + push @WAIT_FOR_TICK, $signal; + $signal->wait; +} + +sub wait_for_tick_begin { + return unless $TICK_WATCHER->is_active; + return if $Coro::current == $Coro::main; + + my $signal = new Coro::Signal; + push @WAIT_FOR_TICK_BEGIN, $signal; + $signal->wait; +} + $TICK_WATCHER = Event->timer ( reentrant => 0, parked => 1, @@ -2632,6 +2698,7 @@ $NOW = Event::time; cf::server_tick; # one server iteration + $RUNTIME += $TICK; $NEXT_TICK += $TICK; @@ -2643,9 +2710,6 @@ }; } - $WAIT_FOR_TICK->broadcast; - $WAIT_FOR_TICK_ONE->send if $WAIT_FOR_TICK_ONE->awaited; - # my $AFTER = Event::time; # warn $AFTER - $NOW;#d# @@ -2654,6 +2718,15 @@ $TICK_WATCHER->at ($NEXT_TICK); $TICK_WATCHER->start; + + if (my $sig = shift @WAIT_FOR_TICK_BEGIN) { + $sig->send; + } + while (my $sig = shift @WAIT_FOR_TICK) { + $sig->send; + } + + _post_tick; }, );