--- deliantra/server/lib/cf.pm 2007/01/01 13:31:47 1.112 +++ deliantra/server/lib/cf.pm 2007/01/01 17:30:34 1.116 @@ -291,7 +291,17 @@ my $self = bless { }, $class; - if ($path =~ s{^\?random/}{}) { + # {... are special paths that are not touched + # ?xxx/... are special absolute paths + # ?random/... random maps + # /! non-realised random map exit + # /... normal maps + # ~/... per-player maps without a specific player (DO NOT USE) + # ~user/... per-player map of a specific user + + if ($path =~ /^{/) { + # fine as it is + } elsif ($path =~ s{^\?random/}{}) { Coro::AIO::aio_load "$cf::RANDOM_MAPS/$path.meta", my $data; $self->{random} = cf::from_json $data; } else { @@ -806,7 +816,7 @@ unless (aio_stat "$filename.pst") { (aio_load "$filename.pst", $av) >= 0 or return; - $av = eval { (Storable::thaw <$av>)->{objs} }; + $av = eval { (Storable::thaw $av)->{objs} }; } return ($data, $av); @@ -1135,6 +1145,7 @@ $map->path ($key); $map->{path} = $path; + $map->{last_save} = $cf::RUNTIME; $map->last_access ($cf::RUNTIME); if ($map->should_reset) { @@ -1240,12 +1251,11 @@ my ($self) = @_; # TODO: safety, remove and allow resettable per-player maps - return 1e100 if $self->{path}{user_rel}; - return 1e100 if $self->{deny_reset}; + return 1e99 if $self->{path}{user_rel}; + return 1e99 if $self->{deny_reset}; my $time = $self->fixed_resettime ? $self->{instantiate_time} : $self->last_access; - my $to = $self->reset_timeout || $DEFAULT_RESET; - $to = $MAX_RESET if $to > $MAX_RESET; + my $to = List::Util::min $MAX_RESET, $self->reset_timeout || $DEFAULT_RESET; $time + $to } @@ -1264,6 +1274,19 @@ aioreq_pri 3; IO::AIO::aio_unlink "$save.pst"; } +sub rename { + my ($self, $new_path) = @_; + + $self->unlink_save; + + delete $cf::MAP{$self->path}; + $self->{path} = new cf::path $new_path; + $self->path ($self->{path}->as_string); + $cf::MAP{$self->path} = $self; + + $self->save; +} + sub reset { my ($self) = @_; @@ -1280,6 +1303,17 @@ $self->destroy; } +my $nuke_counter = "aaaa"; + +sub nuke { + my ($self) = @_; + + $self->{deny_save} = 1; + $self->reset_timeout (1); + $self->rename ("{nuke}/" . ($nuke_counter++)); + $self->reset; # polite request, might not happen +} + sub customise_for { my ($map, $ob) = @_; @@ -1352,6 +1386,24 @@ : $cf::CFG{"may_$access"}) } +=item $player_object->enter_link + +Freezes the player and moves him/her to a special map (C<{link}>). + +The player should be reaosnably safe there for short amounts of time. You +I call C as soon as possible, though. + +=item $player_object->leave_link ($map, $x, $y) + +Moves the player out of the specila link map onto the given map. If the +map is not valid (or omitted), the player will be moved back to the +location he/she was before the call to C, or, if that fails, +to the emergency map position. + +Might block. + +=cut + sub cf::object::player::enter_link { my ($self) = @_; @@ -1370,8 +1422,6 @@ my $link_pos = delete $self->{_link_pos}; unless ($map) { - $self->message ("The exit is closed", cf::NDI_UNIQUE | cf::NDI_RED); - # restore original map position ($map, $x, $y) = @{ $link_pos || [] }; $map = cf::map::find_map $map; @@ -1414,6 +1464,8 @@ warn "entering ", $map->path, " at ($x, $y)\n" if $map; + $map or $self->message ("The exit is closed", cf::NDI_UNIQUE | cf::NDI_RED); + $self->leave_link ($map, $x, $y); })->prio (1); } @@ -1833,7 +1885,7 @@ sub main { # we must not ever block the main coroutine local $Coro::idle = sub { - Carp::cluck "FATAL: Coro::idle was called, major BUG\n";#d# + Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# (Coro::unblock_sub { Event::one_event; })->();