… | |
… | |
1816 | for (@$files) { |
1816 | for (@$files) { |
1817 | utf8::decode $_; |
1817 | utf8::decode $_; |
1818 | next if /\.(?:pl|pst)$/; |
1818 | next if /\.(?:pl|pst)$/; |
1819 | next unless /^$PATH_SEP/o; |
1819 | next unless /^$PATH_SEP/o; |
1820 | |
1820 | |
1821 | push @paths, cf::map::normalise "~$pl/$_", $pl->map; |
1821 | push @paths, cf::map::normalise "~$pl/$_"; |
1822 | } |
1822 | } |
1823 | |
1823 | |
1824 | \@paths |
1824 | \@paths |
1825 | } |
1825 | } |
1826 | |
1826 | |
… | |
… | |
1954 | # {... are special paths that are not being touched |
1954 | # {... are special paths that are not being touched |
1955 | # ?xxx/... are special absolute paths |
1955 | # ?xxx/... are special absolute paths |
1956 | # ?random/... random maps |
1956 | # ?random/... random maps |
1957 | # /... normal maps |
1957 | # /... normal maps |
1958 | # ~user/... per-player map of a specific user |
1958 | # ~user/... per-player map of a specific user |
1959 | # !up !down for quad maps, or other maps with up/down layers |
|
|
1960 | |
1959 | |
1961 | $path =~ s/$PATH_SEP/\//go; |
1960 | $path =~ s/$PATH_SEP/\//go; |
1962 | |
1961 | |
1963 | # treat it as relative path if it starts with |
1962 | # treat it as relative path if it starts with |
1964 | # something that looks reasonable |
1963 | # something that looks reasonable |
1965 | if ($path =~ m{^(?:\./|\.\./|\w)}) { |
1964 | if ($path =~ m{^(?:\./|\.\./|\w)}) { |
1966 | $base or Carp::carp "normalise called with relative path and no base: '$path'"; |
1965 | $base or Carp::carp "normalise called with relative path and no base: '$path'"; |
1967 | |
1966 | |
1968 | $base =~ s{[^/]+/?$}{}; |
1967 | $base =~ s{[^/]+/?$}{}; |
1969 | $path = "$base/$path"; |
1968 | $path = "$base/$path"; |
1970 | |
|
|
1971 | } elsif ($path eq '!up') { |
|
|
1972 | $base && ref $base |
|
|
1973 | or Carp::carp "normalise called with relative tile path and no base: '$path'"; |
|
|
1974 | |
|
|
1975 | my $uppth = $base->tile_path (cf::TILE_UP); |
|
|
1976 | $path = $uppth if $uppth; |
|
|
1977 | |
|
|
1978 | } elsif ($path eq '!down') { |
|
|
1979 | $base && ref $base |
|
|
1980 | or Carp::carp "normalise called with relative tile path and no base: '$path'"; |
|
|
1981 | |
|
|
1982 | my $dpth = $base->tile_path (cf::TILE_DOWN); |
|
|
1983 | $path = $dpth if $dpth; |
|
|
1984 | } |
1969 | } |
1985 | |
1970 | |
1986 | for ($path) { |
1971 | for ($path) { |
1987 | redo if s{/\.?/}{/}; |
1972 | redo if s{/\.?/}{/}; |
1988 | redo if s{/[^/]+/\.\./}{/}; |
1973 | redo if s{/[^/]+/\.\./}{/}; |
… | |
… | |
2084 | $self->{load_path} = $path; |
2069 | $self->{load_path} = $path; |
2085 | |
2070 | |
2086 | 1 |
2071 | 1 |
2087 | } |
2072 | } |
2088 | |
2073 | |
|
|
2074 | # used to laod the header of an original map |
2089 | sub load_header_orig { |
2075 | sub load_header_orig { |
2090 | my ($self) = @_; |
2076 | my ($self) = @_; |
2091 | |
2077 | |
2092 | $self->load_header_from ($self->load_path) |
2078 | $self->load_header_from ($self->load_path) |
2093 | } |
2079 | } |
2094 | |
2080 | |
|
|
2081 | # used to laod the header of an instantiated map |
2095 | sub load_header_temp { |
2082 | sub load_header_temp { |
2096 | my ($self) = @_; |
2083 | my ($self) = @_; |
2097 | |
2084 | |
2098 | $self->load_header_from ($self->save_path) |
2085 | $self->load_header_from ($self->save_path) |
2099 | } |
2086 | } |
2100 | |
2087 | |
|
|
2088 | # called after loading the header from an instantiated map |
2101 | sub prepare_temp { |
2089 | sub prepare_temp { |
2102 | my ($self) = @_; |
2090 | my ($self) = @_; |
2103 | |
2091 | |
2104 | $self->last_access ((delete $self->{last_access}) |
2092 | $self->last_access ((delete $self->{last_access}) |
2105 | || $cf::RUNTIME); #d# |
2093 | || $cf::RUNTIME); #d# |
2106 | # safety |
2094 | # safety |
2107 | $self->{instantiate_time} = $cf::RUNTIME |
2095 | $self->{instantiate_time} = $cf::RUNTIME |
2108 | if $self->{instantiate_time} > $cf::RUNTIME; |
2096 | if $self->{instantiate_time} > $cf::RUNTIME; |
2109 | } |
2097 | } |
2110 | |
2098 | |
|
|
2099 | # called after loading the header from an original map |
2111 | sub prepare_orig { |
2100 | sub prepare_orig { |
2112 | my ($self) = @_; |
2101 | my ($self) = @_; |
2113 | |
2102 | |
2114 | $self->{load_original} = 1; |
2103 | $self->{load_original} = 1; |
2115 | $self->{instantiate_time} = $cf::RUNTIME; |
2104 | $self->{instantiate_time} = $cf::RUNTIME; |
… | |
… | |
2182 | |
2171 | |
2183 | { |
2172 | { |
2184 | my $guard = cf::lock_acquire "map_data:$path"; |
2173 | my $guard = cf::lock_acquire "map_data:$path"; |
2185 | |
2174 | |
2186 | return unless $self->valid; |
2175 | return unless $self->valid; |
2187 | return unless $self->in_memory == cf::MAP_SWAPPED; |
2176 | return unless $self->state == cf::MAP_SWAPPED; |
2188 | |
|
|
2189 | $self->in_memory (cf::MAP_LOADING); |
|
|
2190 | |
2177 | |
2191 | $self->alloc; |
2178 | $self->alloc; |
2192 | |
2179 | |
2193 | $self->pre_load; |
2180 | $self->pre_load; |
2194 | cf::cede_to_tick; |
2181 | cf::cede_to_tick; |
… | |
… | |
2212 | } |
2199 | } |
2213 | } |
2200 | } |
2214 | } |
2201 | } |
2215 | |
2202 | |
2216 | $f->resolve_delayed_derefs; |
2203 | $f->resolve_delayed_derefs; |
|
|
2204 | } else { |
|
|
2205 | $self->post_load_original |
|
|
2206 | if delete $self->{load_original}; |
2217 | } |
2207 | } |
|
|
2208 | |
|
|
2209 | $self->state (cf::MAP_INACTIVE); |
2218 | |
2210 | |
2219 | cf::cede_to_tick; |
2211 | cf::cede_to_tick; |
2220 | # now do the right thing for maps |
2212 | # now do the right thing for maps |
2221 | $self->link_multipart_objects; |
2213 | $self->link_multipart_objects; |
2222 | $self->difficulty ($self->estimate_difficulty) |
2214 | $self->difficulty ($self->estimate_difficulty) |
… | |
… | |
2226 | unless ($self->{deny_activate}) { |
2218 | unless ($self->{deny_activate}) { |
2227 | $self->decay_objects; |
2219 | $self->decay_objects; |
2228 | $self->fix_auto_apply; |
2220 | $self->fix_auto_apply; |
2229 | $self->update_buttons; |
2221 | $self->update_buttons; |
2230 | cf::cede_to_tick; |
2222 | cf::cede_to_tick; |
2231 | $self->activate; |
2223 | #$self->activate; # no longer activate maps automatically |
2232 | } |
2224 | } |
2233 | |
2225 | |
2234 | $self->{last_save} = $cf::RUNTIME; |
2226 | $self->{last_save} = $cf::RUNTIME; |
2235 | $self->last_access ($cf::RUNTIME); |
2227 | $self->last_access ($cf::RUNTIME); |
2236 | |
|
|
2237 | $self->in_memory (cf::MAP_ACTIVE); |
|
|
2238 | } |
2228 | } |
2239 | |
2229 | |
2240 | $self->post_load; |
2230 | $self->post_load; |
2241 | |
2231 | |
2242 | 1 |
2232 | 1 |
… | |
… | |
2285 | } |
2275 | } |
2286 | |
2276 | |
2287 | sub find_sync { |
2277 | sub find_sync { |
2288 | my ($path, $origin) = @_; |
2278 | my ($path, $origin) = @_; |
2289 | |
2279 | |
|
|
2280 | # it's a bug to call this from the main context |
2290 | return cf::LOG cf::llevError | cf::logBacktrace, "do_find_sync" |
2281 | return cf::LOG cf::llevError | cf::logBacktrace, "do_find_sync" |
2291 | if $Coro::current == $Coro::main; |
2282 | if $Coro::current == $Coro::main; |
2292 | |
2283 | |
2293 | find $path, $origin |
2284 | find $path, $origin |
2294 | } |
2285 | } |
2295 | |
2286 | |
2296 | sub do_load_sync { |
2287 | sub do_load_sync { |
2297 | my ($map) = @_; |
2288 | my ($map) = @_; |
2298 | |
2289 | |
|
|
2290 | # it's a bug to call this from the main context |
2299 | return cf::LOG cf::llevError | cf::logBacktrace, "do_load_sync" |
2291 | return cf::LOG cf::llevError | cf::logBacktrace, "do_load_sync" |
2300 | if $Coro::current == $Coro::main; |
2292 | if $Coro::current == $Coro::main; |
2301 | |
2293 | |
2302 | $map->load; |
2294 | $map->load; |
2303 | } |
2295 | } |
… | |
… | |
2307 | |
2299 | |
2308 | sub find_async { |
2300 | sub find_async { |
2309 | my ($path, $origin, $load) = @_; |
2301 | my ($path, $origin, $load) = @_; |
2310 | |
2302 | |
2311 | $path = normalise $path, $origin; |
2303 | $path = normalise $path, $origin; |
2312 | |
2304 | |
2313 | if (my $map = $cf::MAP{$path}) { |
2305 | if (my $map = $cf::MAP{$path}) { |
2314 | return $map if !$load || $map->in_memory == cf::MAP_ACTIVE; |
2306 | return $map if !$load || $map->linkable; |
2315 | } |
2307 | } |
2316 | |
2308 | |
2317 | $MAP_PREFETCH{$path} |= $load; |
2309 | $MAP_PREFETCH{$path} |= $load; |
2318 | |
2310 | |
2319 | $MAP_PREFETCHER ||= cf::async { |
2311 | $MAP_PREFETCHER ||= cf::async { |
… | |
… | |
2378 | sub swap_out { |
2370 | sub swap_out { |
2379 | my ($self) = @_; |
2371 | my ($self) = @_; |
2380 | |
2372 | |
2381 | my $lock = cf::lock_acquire "map_data:$self->{path}"; |
2373 | my $lock = cf::lock_acquire "map_data:$self->{path}"; |
2382 | |
2374 | |
2383 | return if $self->in_memory != cf::MAP_ACTIVE; |
2375 | return if !$self->linkable; |
2384 | return if $self->{deny_save}; |
2376 | return if $self->{deny_save}; |
2385 | return if $self->players; |
2377 | return if $self->players; |
2386 | |
2378 | |
2387 | # first deactivate the map and "unlink" it from the core |
2379 | # first deactivate the map and "unlink" it from the core |
2388 | $self->deactivate; |
2380 | $self->deactivate; |
2389 | $_->clear_links_to ($self) for values %cf::MAP; |
2381 | $_->clear_links_to ($self) for values %cf::MAP; |
2390 | $self->in_memory (cf::MAP_SWAPPED); |
2382 | $self->state (cf::MAP_SWAPPED); |
2391 | |
2383 | |
2392 | # then atomically save |
2384 | # then atomically save |
2393 | $self->_save; |
2385 | $self->_save; |
2394 | |
2386 | |
2395 | # then free the map |
2387 | # then free the map |
… | |
… | |
2421 | |
2413 | |
2422 | return if $self->players; |
2414 | return if $self->players; |
2423 | |
2415 | |
2424 | cf::trace "resetting map ", $self->path, "\n"; |
2416 | cf::trace "resetting map ", $self->path, "\n"; |
2425 | |
2417 | |
2426 | $self->in_memory (cf::MAP_SWAPPED); |
2418 | $self->state (cf::MAP_SWAPPED); |
2427 | |
2419 | |
2428 | # need to save uniques path |
2420 | # need to save uniques path |
2429 | unless ($self->{deny_save}) { |
2421 | unless ($self->{deny_save}) { |
2430 | my $uniq = $self->uniq_path; utf8::encode $uniq; |
2422 | my $uniq = $self->uniq_path; utf8::encode $uniq; |
2431 | |
2423 | |
… | |
… | |
2927 | $Coro::current->{desc} = "enter_exit"; |
2919 | $Coro::current->{desc} = "enter_exit"; |
2928 | |
2920 | |
2929 | unless (eval { |
2921 | unless (eval { |
2930 | $self->deactivate_recursive; # just to be sure |
2922 | $self->deactivate_recursive; # just to be sure |
2931 | |
2923 | |
2932 | # random map handling |
|
|
2933 | { |
|
|
2934 | my $guard = cf::lock_acquire "exit_prepare:$exit"; |
|
|
2935 | |
|
|
2936 | prepare_random_map $exit |
|
|
2937 | if $exit->slaying eq "/!"; |
|
|
2938 | } |
|
|
2939 | |
|
|
2940 | my $map = cf::map::normalise $exit->slaying, $exit->map; |
2924 | my $map = cf::map::normalise $exit->slaying, $exit->map; |
2941 | my $x = $exit->stats->hp; |
2925 | my $x = $exit->stats->hp; |
2942 | my $y = $exit->stats->sp; |
2926 | my $y = $exit->stats->sp; |
|
|
2927 | |
|
|
2928 | # special map handling |
|
|
2929 | my $slaying = $exit->slaying; |
|
|
2930 | |
|
|
2931 | # special map handling |
|
|
2932 | if ($slaying eq "/!") { |
|
|
2933 | my $guard = cf::lock_acquire "exit_prepare:$exit"; |
|
|
2934 | |
|
|
2935 | prepare_random_map $exit |
|
|
2936 | if $exit->slaying eq "/!"; # need to re-check after getting the lock |
|
|
2937 | |
|
|
2938 | $map = $exit->slaying; |
|
|
2939 | |
|
|
2940 | } elsif ($slaying eq '!up') { |
|
|
2941 | $map = $exit->map->tile_path (cf::TILE_UP); |
|
|
2942 | $x = $exit->x; |
|
|
2943 | $y = $exit->y; |
|
|
2944 | |
|
|
2945 | } elsif ($slaying eq '!down') { |
|
|
2946 | $map = $exit->map->tile_path (cf::TILE_DOWN); |
|
|
2947 | $x = $exit->x; |
|
|
2948 | $y = $exit->y; |
|
|
2949 | } |
2943 | |
2950 | |
2944 | $self->goto ($map, $x, $y); |
2951 | $self->goto ($map, $x, $y); |
2945 | |
2952 | |
2946 | # if exit is damned, update players death & WoR home-position |
2953 | # if exit is damned, update players death & WoR home-position |
2947 | $self->contr->savebed ($map, $x, $y) |
2954 | $self->contr->savebed ($map, $x, $y) |