--- deliantra/server/lib/cf.pm 2007/01/14 18:00:34 1.173 +++ deliantra/server/lib/cf.pm 2007/01/19 15:38:01 1.182 @@ -10,7 +10,7 @@ use Safe; use Safe::Hole; -use Coro 3.3 (); +use Coro 3.4 (); use Coro::Event; use Coro::Timer; use Coro::Signal; @@ -959,7 +959,7 @@ my ($login) = @_; $cf::PLAYER{$login} - or cf::sync_job { !aio_stat $login } + or cf::sync_job { !aio_stat path $login } } sub find($) { @@ -1123,7 +1123,6 @@ sub generate_random_map { my ($self, $rmp) = @_; - # mit "rum" bekleckern, nicht $self->_create_random_map ( $rmp->{wallstyle}, $rmp->{wall_name}, $rmp->{floorstyle}, $rmp->{monsterstyle}, @@ -1537,20 +1536,6 @@ $self->reset_at <= $cf::RUNTIME } -sub rename { - my ($self, $new_path) = @_; - - normalise $new_path; - - $self->unlink_save; - - delete $cf::MAP{$self->path}; - $self->{path} = $new_path; $self->path ($self->{path}); - $cf::MAP{$self->path} = $self; - - $self->save; -} - sub reset { my ($self) = @_; @@ -1577,9 +1562,18 @@ sub nuke { my ($self) = @_; + delete $cf::MAP{$self->path}; + + $self->unlink_save; + + bless $self, "cf::map"; + delete $self->{deny_reset}; $self->{deny_save} = 1; $self->reset_timeout (1); - $self->rename ("{nuke}/" . ($nuke_counter++)); + $self->path ($self->{path} = "{nuke}/" . ($nuke_counter++)); + + $cf::MAP{$self->path} = $self; + $self->reset; # polite request, might not happen } @@ -1820,8 +1814,10 @@ my ($spec) = @_; my $rmp = { # defaults - xsize => 10, - ysize => 10, + xsize => (cf::rndm 15, 40), + ysize => (cf::rndm 15, 40), + symmetry => (cf::rndm 1, cf::SYMMETRY_XY), + #layout => string, }; for (split /\n/, $spec) { @@ -1836,6 +1832,8 @@ sub prepare_random_map { my ($exit) = @_; + my $guard = cf::lock_acquire "exit_prepare:$exit"; + # all this does is basically replace the /! path by # a new random map path (?random/...) with a seed # that depends on the exit object @@ -1853,9 +1851,12 @@ my $data = cf::to_json $rmp; my $md5 = Digest::MD5::md5_hex $data; + my $meta = "$cf::RANDOM_MAPS/$md5.meta"; - if (my $fh = aio_open "$cf::RANDOM_MAPS/$md5.meta", O_WRONLY | O_CREAT, 0666) { + if (my $fh = aio_open "$meta~", O_WRONLY | O_CREAT, 0666) { aio_write $fh, 0, (length $data), $data, 0; + undef $fh; + aio_rename "$meta~", $meta; $exit->slaying ("?random/$md5"); $exit->msg (undef); @@ -2235,7 +2236,9 @@ # we must not ever block the main coroutine local $Coro::idle = sub { Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# - async { Event::one_event }; + (async { + Event::one_event; + })->prio (Coro::PRIO_MAX); }; cfg_load; @@ -2393,13 +2396,21 @@ warn "reloaded"; }; +our $RELOAD_WATCHER; # used only during reload + register_command "reload" => sub { my ($who, $arg) = @_; if ($who->flag (FLAG_WIZ)) { - $who->message ("start of reload."); - reload; - $who->message ("end of reload."); + $who->message ("reloading server."); + + # doing reload synchronously and two reloads happen back-to-back, + # coro crashes during coro_state_free->destroy here. + + $RELOAD_WATCHER ||= Event->timer (after => 0, data => WF_AUTOCANCEL, cb => sub { + reload; + undef $RELOAD_WATCHER; + }); } };