ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.160 by root, Wed Jan 10 22:54:06 2007 UTC vs.
Revision 1.161 by root, Thu Jan 11 00:16:58 2007 UTC

37our %COMMAND_TIME = (); 37our %COMMAND_TIME = ();
38 38
39our @EXTS = (); # list of extension package names 39our @EXTS = (); # list of extension package names
40our %EXTCMD = (); 40our %EXTCMD = ();
41our %EXT_CORO = (); # coroutines bound to extensions 41our %EXT_CORO = (); # coroutines bound to extensions
42our %EXT_MAP = (); # pluggable maps
42 43
43our @EVENT; 44our @EVENT;
44our $LIBDIR = datadir . "/ext"; 45our $LIBDIR = datadir . "/ext";
45 46
46our $TICK = MAX_TIME * 1e-6; 47our $TICK = MAX_TIME * 1e-6;
371 '""' => \&as_string; 372 '""' => \&as_string;
372 373
373# used to convert map paths into valid unix filenames by repalcing / by ∕ 374# used to convert map paths into valid unix filenames by repalcing / by ∕
374our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons 375our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons
375 376
377sub register {
378 my ($pkg, $prefix) = @_;
379
380 $EXT_MAP{$prefix} = $pkg;
381}
382
376sub new { 383sub new {
377 my ($class, $path, $base) = @_; 384 my ($class, $path, $base) = @_;
378 385
379 $path = $path->as_string if ref $path; 386 return $path if ref $path;
380 387
381 my $self = bless { }, $class; 388 my $self = {};
382 389
383 # {... are special paths that are not touched 390 # {... are special paths that are not being touched
384 # ?xxx/... are special absolute paths 391 # ?xxx/... are special absolute paths
385 # ?random/... random maps 392 # ?random/... random maps
386 # /! non-realised random map exit 393 # /! non-realised random map exit
387 # /... normal maps 394 # /... normal maps
388 # ~/... per-player maps without a specific player (DO NOT USE) 395 # ~/... per-player maps without a specific player (DO NOT USE)
390 397
391 $path =~ s/$PATH_SEP/\//go; 398 $path =~ s/$PATH_SEP/\//go;
392 399
393 if ($path =~ /^{/) { 400 if ($path =~ /^{/) {
394 # fine as it is 401 # fine as it is
395 } elsif ($path =~ s{^\?random/}{}) {
396 Coro::AIO::aio_load "$cf::RANDOM_MAPS/$path.meta", my $data;
397 $self->{random} = cf::from_json $data;
398 } else { 402 } else {
399 if ($path =~ s{^~([^/]+)?}{}) { 403 if ($path =~ s{^~([^/]+)?}{}) {
404 # ~user
400 $self->{user_rel} = 1; 405 $self->{user_rel} = 1;
401 406
402 if (defined $1) { 407 if (defined $1) {
403 $self->{user} = $1; 408 $self->{user} = $1;
404 } elsif ($base =~ m{^~([^/]+)/}) { 409 } elsif ($base =~ m{^~([^/]+)/}) {
405 $self->{user} = $1; 410 $self->{user} = $1;
406 } else { 411 } else {
407 warn "cannot resolve user-relative path without user <$path,$base>\n"; 412 warn "cannot resolve user-relative path without user <$path,$base>\n";
408 } 413 }
414 } elsif ($path =~ s{^\?([^/]+)/}{}) {
415 # ?...
416 $self->{ext} = $1;
417 if (my $ext = $EXT_MAP{$1}) {
418 bless $self, $ext;
419 }
409 } elsif ($path =~ /^\//) { 420 } elsif ($path =~ /^\//) {
421 # /...
410 # already absolute 422 # already absolute
411 } else { 423 } else {
424 # relative
412 $base =~ s{[^/]+/?$}{}; 425 $base =~ s{[^/]+/?$}{};
413 return $class->new ("$base/$path"); 426 return $class->new ("$base/$path");
414 } 427 }
415 428
416 for ($path) { 429 for ($path) {
419 } 432 }
420 } 433 }
421 434
422 $self->{path} = $path; 435 $self->{path} = $path;
423 436
437 if ("HASH" eq ref $self) {
438 bless $self, $class;
439 } else {
440 $self->init;
441 }
442
443 for my $ext (values %EXT_MAP) {
444 if (my $subst = $ext->substitute ($self)) {
445 return $subst;
446 }
447 }
448
424 $self 449 $self
450}
451
452sub init {
453 # nop
454}
455
456sub substitute {
457 ()
425} 458}
426 459
427# the name / primary key / in-game path 460# the name / primary key / in-game path
428sub as_string { 461sub as_string {
429 my ($self) = @_; 462 my ($self) = @_;
430 463
431 $self->{user_rel} ? "~$self->{user}$self->{path}" 464 $self->{user_rel} ? "~$self->{user}$self->{path}"
432 : $self->{random} ? "?random/$self->{path}" 465 : $self->{ext} ? "?$self->{ext}/$self->{path}"
433 : $self->{path} 466 : $self->{path}
434} 467}
435 468
436# the displayed name, this is a one way mapping 469# the displayed name, this is a one way mapping
437sub visible_name { 470sub visible_name {
438 my ($self) = @_; 471 &as_string
439
440# if (my $rmp = $self->{random}) {
441# # todo: be more intelligent about this
442# "?random/$rmp->{origin_map}+$rmp->{origin_x}+$rmp->{origin_y}/$rmp->{dungeon_level}"
443# } else {
444 $self->as_string
445# }
446} 472}
447 473
448# escape the /'s in the path 474# escape the /'s in the path
449sub _escaped_path { 475sub _escaped_path {
450 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/g; 476 (my $path = $_[0]{path}) =~ s/\//$PATH_SEP/g;
465 $self->{user_rel} ? sprintf "%s/%s/%s/%s", cf::localdir, cf::playerdir, $self->{user}, $self->_escaped_path 491 $self->{user_rel} ? sprintf "%s/%s/%s/%s", cf::localdir, cf::playerdir, $self->{user}, $self->_escaped_path
466 : $self->{random} ? sprintf "%s/%s", $RANDOM_MAPS, $self->{path} 492 : $self->{random} ? sprintf "%s/%s", $RANDOM_MAPS, $self->{path}
467 : sprintf "%s/%s/%s", cf::localdir, cf::tmpdir, $self->_escaped_path 493 : sprintf "%s/%s/%s", cf::localdir, cf::tmpdir, $self->_escaped_path
468} 494}
469 495
470# the unique path, might be eq to save_path 496# the unique path, undef == no special unique path
471sub uniq_path { 497sub uniq_path {
472 my ($self) = @_; 498 my ($self) = @_;
473 499
474 $self->{user_rel} || $self->{random}
475 ? undef
476 : sprintf "%s/%s/%s", cf::localdir, cf::uniquedir, $self->_escaped_path 500 sprintf "%s/%s/%s", cf::localdir, cf::uniquedir, $self->_escaped_path
477}
478
479# return random map parameters, or undef
480sub random_map_params {
481 my ($self) = @_;
482
483 $self->{random}
484} 501}
485 502
486# this is somewhat ugly, but style maps do need special treatment 503# this is somewhat ugly, but style maps do need special treatment
487sub is_style_map { 504sub is_style_map {
488 $_[0]{path} =~ m{^/styles/} 505 $_[0]{path} =~ m{^/styles/}
506}
507
508sub load_orig {
509 my ($self) = @_;
510
511 &cf::map::load_map_header ($self->load_path)
512}
513
514sub load_temp {
515 my ($self) = @_;
516
517 &cf::map::load_map_header ($self->save_path)
489} 518}
490 519
491package cf; 520package cf;
492 521
493############################################################################# 522#############################################################################
1260 1289
1261 $_->change_map_light ($change) 1290 $_->change_map_light ($change)
1262 for grep $_->outdoor, values %cf::MAP; 1291 for grep $_->outdoor, values %cf::MAP;
1263} 1292}
1264 1293
1265sub try_load_header($) { 1294sub load_map_header($) {
1266 my ($path) = @_; 1295 my ($path) = @_;
1267 1296
1268 utf8::encode $path; 1297 utf8::encode $path;
1269 aio_open $path, O_RDONLY, 0 1298 aio_open $path, O_RDONLY, 0
1270 or return; 1299 or return;
1271 1300
1272 my $map = cf::map::new 1301 my $map = cf::map::new
1273 or return; 1302 or return;
1274 1303
1275 # for better error messages only, will be overwritten 1304 # for better error messages only, will be overwritten later
1276 $map->path ($path); 1305 $map->path ($path);
1277 1306
1278 $map->load_header ($path) 1307 $map->load_header ($path)
1279 or return; 1308 or return;
1280 1309
1296 1325
1297 $cf::MAP{$key} || do { 1326 $cf::MAP{$key} || do {
1298 my $guard = cf::lock_acquire "map_find:$key"; 1327 my $guard = cf::lock_acquire "map_find:$key";
1299 1328
1300 # do it the slow way 1329 # do it the slow way
1301 my $map = try_load_header $path->save_path; 1330 my $map = $path->load_temp;
1302 1331
1303 Coro::cede; 1332 Coro::cede;
1304 1333
1305 if ($map) { 1334 if ($map) {
1306 $map->last_access ((delete $map->{last_access}) 1335 $map->last_access ((delete $map->{last_access})
1307 || $cf::RUNTIME); #d# 1336 || $cf::RUNTIME); #d#
1308 # safety 1337 # safety
1309 $map->{instantiate_time} = $cf::RUNTIME 1338 $map->{instantiate_time} = $cf::RUNTIME
1310 if $map->{instantiate_time} > $cf::RUNTIME; 1339 if $map->{instantiate_time} > $cf::RUNTIME;
1311 } else { 1340 } else {
1312 if (my $rmp = $path->random_map_params) { 1341 $map = $path->load_orig
1313 $map = generate_random_map $key, $rmp;
1314 } else {
1315 $map = try_load_header $path->load_path;
1316 }
1317
1318 $map or return; 1342 or return;
1319 1343
1320 $map->{load_original} = 1; 1344 $map->{load_original} = 1;
1321 $map->{instantiate_time} = $cf::RUNTIME; 1345 $map->{instantiate_time} = $cf::RUNTIME;
1322 $map->last_access ($cf::RUNTIME); 1346 $map->last_access ($cf::RUNTIME);
1323 $map->instantiate; 1347 $map->instantiate;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines