… | |
… | |
130 | and return; |
130 | and return; |
131 | |
131 | |
132 | 1 |
132 | 1 |
133 | } |
133 | } |
134 | |
134 | |
135 | (Coro::unblock_sub { |
135 | (Coro::async { |
136 | unless (write_runtime) { |
136 | unless (write_runtime) { |
137 | warn "unable to write runtime file: $!"; |
137 | warn "unable to write runtime file: $!"; |
138 | exit 1; |
138 | exit 1; |
139 | } |
139 | } |
140 | })->(); |
140 | })->prio (Coro::PRIO_MAX); |
141 | |
141 | |
142 | our $SCHEDULER = cf::coro { |
142 | our $SCHEDULER = cf::coro { |
143 | while () { |
143 | while () { |
144 | Coro::Timer::sleep $SCHEDULE_INTERVAL; |
144 | Coro::Timer::sleep $SCHEDULE_INTERVAL; |
145 | |
145 | |
… | |
… | |
181 | |
181 | |
182 | Carp::confess "nested sync_job" if $cf::FREEZE; |
182 | Carp::confess "nested sync_job" if $cf::FREEZE; |
183 | |
183 | |
184 | local $cf::FREEZE = 1; |
184 | local $cf::FREEZE = 1; |
185 | |
185 | |
186 | (async { |
186 | (Coro::async { |
187 | @res = eval { $job->() }; |
187 | @res = eval { $job->() }; |
188 | warn $@ if $@; |
188 | warn $@ if $@; |
189 | $done = 1; |
189 | $done = 1; |
190 | })->prio (Coro::PRIO_MAX); |
190 | })->prio (Coro::PRIO_MAX); |
191 | |
191 | |
192 | while (!$done) { |
192 | while (!$done) { |
193 | Coro::cede_notself; |
193 | Coro::cede_notself; |
194 | Event::one_event unless Coro::nready; |
194 | Event::one_event unless Coro::nready; |
195 | } |
195 | } |
196 | |
196 | |
197 | warn "job done<@res>\n";#d# |
|
|
198 | |
|
|
199 | wantarray ? @res : $res[0] |
197 | wantarray ? @res : $res[0] |
200 | } |
198 | } |
201 | |
199 | |
202 | # and all this just because we cannot iterate over |
200 | # and all this just because we cannot iterate over |
203 | # all maps in C++... |
201 | # all maps in C++... |
… | |
… | |
222 | |
220 | |
223 | $map->reset_time (0) if $map->reset_time > $cf::RUNTIME; |
221 | $map->reset_time (0) if $map->reset_time > $cf::RUNTIME; |
224 | $map->reset_timeout (10);#d# |
222 | $map->reset_timeout (10);#d# |
225 | |
223 | |
226 | $map->{load_path} = $path; |
224 | $map->{load_path} = $path; |
227 | warn "load header from $path\n";#d# |
|
|
228 | |
225 | |
229 | $map |
226 | $map |
230 | } |
227 | } |
231 | |
228 | |
232 | sub cf::map::find_map_nb { |
229 | sub cf::map::find_map_nb { |
233 | my ($path, $origin) = @_; |
230 | my ($path, $origin) = @_; |
234 | |
231 | |
|
|
232 | warn "find_map_nb<$path,$origin>\n";#d# |
|
|
233 | |
235 | $path = ref $path ? $path : new cf::path $path, $origin && $origin->path; |
234 | $path = ref $path ? $path : new cf::path $path, $origin && $origin->path; |
236 | my $key = $path->as_string; |
235 | my $key = $path->as_string; |
237 | |
|
|
238 | warn "find_map_nb<$path,$origin>\n";#d# |
|
|
239 | |
236 | |
240 | $cf::MAP{$key} || do { |
237 | $cf::MAP{$key} || do { |
241 | # do it the slow way |
238 | # do it the slow way |
242 | my $map = try_load_header $path->save_path; |
239 | my $map = try_load_header $path->save_path; |
243 | |
240 | |
… | |
… | |
249 | $map or return; |
246 | $map or return; |
250 | |
247 | |
251 | $map->instantiate; |
248 | $map->instantiate; |
252 | $map->path ($key); |
249 | $map->path ($key); |
253 | $map->{path} = $path; |
250 | $map->{path} = $path; |
|
|
251 | |
|
|
252 | $map->per_player (0) if $path->{user_rel}; |
254 | |
253 | |
255 | $map->reset if $map->should_reset; |
254 | $map->reset if $map->should_reset; |
256 | |
255 | |
257 | $cf::MAP{$key} = $map |
256 | $cf::MAP{$key} = $map |
258 | } |
257 | } |
… | |
… | |
334 | } |
333 | } |
335 | |
334 | |
336 | sub cf::map::swap_out { |
335 | sub cf::map::swap_out { |
337 | my ($self) = @_; |
336 | my ($self) = @_; |
338 | |
337 | |
339 | $self->save; |
338 | $self->save if $self->in_memory == cf::MAP_IN_MEMORY; |
340 | $self->clear; |
339 | $self->clear; |
341 | $self->in_memory (cf::MAP_SWAPPED); |
340 | $self->in_memory (cf::MAP_SWAPPED); |
342 | } |
341 | } |
343 | |
342 | |
344 | sub cf::map::should_reset { |
343 | sub cf::map::should_reset { |
… | |
… | |
356 | |
355 | |
357 | sub cf::map::reset { |
356 | sub cf::map::reset { |
358 | my ($self) = @_; |
357 | my ($self) = @_; |
359 | |
358 | |
360 | return if $self->players; |
359 | return if $self->players; |
|
|
360 | return if $self->{path}{user_rel};#d# |
361 | |
361 | |
362 | warn "resetting map ", $self->path;#d# |
362 | warn "resetting map ", $self->path;#d# |
363 | return;#d# |
363 | |
|
|
364 | utf8::encode (my $save = $self->{path}->save_path); |
|
|
365 | aioreq_pri 3; IO::AIO::aio_unlink $save; |
|
|
366 | aioreq_pri 3; IO::AIO::aio_unlink "$save.pst"; |
364 | |
367 | |
365 | $self->clear; |
368 | $self->clear; |
366 | $self->in_memory (cf::MAP_SWAPPED); |
369 | $self->in_memory (cf::MAP_SWAPPED); |
367 | $self->{load_path} = $self->{path}->load_path; |
370 | utf8::encode ($self->{load_path} = $self->{path}->load_path); |
368 | utf8::encode $self->{load_path}; |
|
|
369 | } |
371 | } |
370 | |
372 | |
371 | sub cf::object::player::enter_exit { |
373 | sub cf::object::player::enter_exit { |
372 | my ($ob, $exit) = @_; |
374 | my ($ob, $exit) = @_; |
373 | |
375 | |
374 | warn "enter_exit\n";#d# |
376 | # if at login, move to interim map immediately |
|
|
377 | unless ($exit) { |
|
|
378 | # used on login only |
|
|
379 | $ob->enter_map ($LINK_MAP, 0, 0); |
|
|
380 | } |
|
|
381 | |
|
|
382 | #TODO: do this in the background, freeze the player if required |
375 | sync_job { |
383 | sync_job { |
376 | warn "enter_exit<$ob,$exit>\n";#d# |
384 | my ($map, $x, $y); |
377 | |
385 | |
378 | if ($exit) { |
386 | unless ($exit) { |
|
|
387 | # used on login only(?) |
|
|
388 | $map = cf::map::find_map_nb $ob->contr->maplevel; |
|
|
389 | ($x, $y) = ($ob->x, $ob->y); |
|
|
390 | } else { |
379 | my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path; |
391 | my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path; |
380 | |
392 | |
381 | my $map = cf::map::find_map_nb $path->as_string; |
393 | $map = cf::map::find_map_nb $path->as_string; |
382 | $map = $map->customise_for ($ob) if $map; |
394 | $map = $map->customise_for ($ob) if $map; |
383 | |
|
|
384 | if ($map) { |
|
|
385 | $map->do_load_nb; |
|
|
386 | $ob->enter_map ($map, $exit->stats->hp, $exit->stats->sp); |
395 | ($x, $y) = ($exit->stats->hp, $exit->stats->sp); |
387 | } else { |
|
|
388 | $ob->message ("The exit is closed", cf::NDI_UNIQUE | cf::NDI_RED); |
|
|
389 | } |
396 | } |
390 | } else { |
|
|
391 | # used on login only(?) |
|
|
392 | my $map = cf::map::find_map_nb $ob->contr->maplevel; |
|
|
393 | my ($x, $y) = ($ob->x, $ob->y); |
|
|
394 | |
397 | |
395 | unless ($map) { |
398 | unless ($map) { |
396 | $map = cf::map::find_map_nb $emergency_position->[0] |
399 | $map = cf::map::find_map_nb $emergency_position->[0] |
397 | or die "FATAL: cannot load emergency map\n"; |
400 | or die "FATAL: cannot load emergency map\n"; |
398 | $x = $emergency_position->[1]; |
401 | $x = $emergency_position->[1]; |
399 | $y = $emergency_position->[2]; |
402 | $y = $emergency_position->[2]; |
400 | } |
403 | } |
401 | |
404 | |
|
|
405 | if ($map) { |
|
|
406 | warn "entering ", $map->path, " at ($x, $y)\n";#d# |
402 | $map->do_load_nb; |
407 | $map->do_load_nb; |
403 | $ob->enter_map ($map, $x, $y); |
408 | $ob->enter_map ($map, $x, $y); |
|
|
409 | } else { |
|
|
410 | $ob->message ("The exit is closed", cf::NDI_UNIQUE | cf::NDI_RED); |
404 | } |
411 | } |
405 | } |
412 | } |
406 | } |
413 | } |
407 | |
414 | |
408 | sub cf::map::customise_for { |
415 | sub cf::map::customise_for { |
409 | my ($map, $ob) = @_; |
416 | my ($map, $ob) = @_; |
410 | |
417 | |
411 | warn "customise_for<$map,$ob>\n";#d# |
|
|
412 | |
|
|
413 | if ($map->per_player) { |
418 | if ($map->per_player) { |
414 | return cf::map::find_map_nb "~" . $ob->name . "/" . $map->{path}{path}; |
419 | return cf::map::find_map_nb "~" . $ob->name . "/" . $map->{path}{path}; |
415 | } |
420 | } |
416 | |
421 | |
417 | $map |
422 | $map |
418 | } |
423 | } |
419 | |
424 | |
420 | sub cf::map::emergency_save { |
425 | sub cf::map::emergency_save { |
421 | local $cf::FREEZE = 1; |
426 | local $cf::FREEZE = 1; |
422 | |
427 | |
|
|
428 | warn "enter emergency map save\n"; |
|
|
429 | |
|
|
430 | my $saver = async { |
423 | warn "begin emergency map save\n"; |
431 | warn "begin emergency map save\n"; |
424 | $_->save for values %cf::MAP; |
432 | $_->save for values %cf::MAP; |
|
|
433 | }; |
|
|
434 | $saver->prio (Coro::PRIO_MAX); |
|
|
435 | $saver->join; |
|
|
436 | |
425 | warn "emergency map save drain\n"; |
437 | warn "emergency map save drain\n"; |
426 | |
|
|
427 | Event::one_event while IO::AIO::nreqs; |
438 | Event::one_event while IO::AIO::nreqs; |
428 | warn "end emergency map save\n"; |
439 | warn "end emergency map save\n"; |
429 | } |
440 | } |
430 | |
441 | |