--- deliantra/server/lib/cf.pm 2007/01/10 22:54:06 1.160 +++ deliantra/server/lib/cf.pm 2007/01/11 00:16:58 1.161 @@ -39,6 +39,7 @@ our @EXTS = (); # list of extension package names our %EXTCMD = (); our %EXT_CORO = (); # coroutines bound to extensions +our %EXT_MAP = (); # pluggable maps our @EVENT; our $LIBDIR = datadir . "/ext"; @@ -373,14 +374,20 @@ # used to convert map paths into valid unix filenames by repalcing / by ∕ our $PATH_SEP = "∕"; # U+2215, chosen purely for visual reasons +sub register { + my ($pkg, $prefix) = @_; + + $EXT_MAP{$prefix} = $pkg; +} + sub new { my ($class, $path, $base) = @_; - $path = $path->as_string if ref $path; + return $path if ref $path; - my $self = bless { }, $class; + my $self = {}; - # {... are special paths that are not touched + # {... are special paths that are not being touched # ?xxx/... are special absolute paths # ?random/... random maps # /! non-realised random map exit @@ -392,11 +399,9 @@ 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 { if ($path =~ s{^~([^/]+)?}{}) { + # ~user $self->{user_rel} = 1; if (defined $1) { @@ -406,9 +411,17 @@ } else { warn "cannot resolve user-relative path without user <$path,$base>\n"; } + } elsif ($path =~ s{^\?([^/]+)/}{}) { + # ?... + $self->{ext} = $1; + if (my $ext = $EXT_MAP{$1}) { + bless $self, $ext; + } } elsif ($path =~ /^\//) { + # /... # already absolute } else { + # relative $base =~ s{[^/]+/?$}{}; return $class->new ("$base/$path"); } @@ -421,28 +434,41 @@ $self->{path} = $path; + if ("HASH" eq ref $self) { + bless $self, $class; + } else { + $self->init; + } + + for my $ext (values %EXT_MAP) { + if (my $subst = $ext->substitute ($self)) { + return $subst; + } + } + $self } +sub init { + # nop +} + +sub substitute { + () +} + # the name / primary key / in-game path sub as_string { my ($self) = @_; $self->{user_rel} ? "~$self->{user}$self->{path}" - : $self->{random} ? "?random/$self->{path}" + : $self->{ext} ? "?$self->{ext}/$self->{path}" : $self->{path} } # the displayed name, this is a one way mapping sub visible_name { - my ($self) = @_; - -# if (my $rmp = $self->{random}) { -# # todo: be more intelligent about this -# "?random/$rmp->{origin_map}+$rmp->{origin_x}+$rmp->{origin_y}/$rmp->{dungeon_level}" -# } else { - $self->as_string -# } + &as_string } # escape the /'s in the path @@ -467,25 +493,28 @@ : sprintf "%s/%s/%s", cf::localdir, cf::tmpdir, $self->_escaped_path } -# the unique path, might be eq to save_path +# the unique path, undef == no special unique path sub uniq_path { my ($self) = @_; - $self->{user_rel} || $self->{random} - ? undef - : sprintf "%s/%s/%s", cf::localdir, cf::uniquedir, $self->_escaped_path + sprintf "%s/%s/%s", cf::localdir, cf::uniquedir, $self->_escaped_path +} + +# this is somewhat ugly, but style maps do need special treatment +sub is_style_map { + $_[0]{path} =~ m{^/styles/} } -# return random map parameters, or undef -sub random_map_params { +sub load_orig { my ($self) = @_; - $self->{random} + &cf::map::load_map_header ($self->load_path) } -# this is somewhat ugly, but style maps do need special treatment -sub is_style_map { - $_[0]{path} =~ m{^/styles/} +sub load_temp { + my ($self) = @_; + + &cf::map::load_map_header ($self->save_path) } package cf; @@ -1262,7 +1291,7 @@ for grep $_->outdoor, values %cf::MAP; } -sub try_load_header($) { +sub load_map_header($) { my ($path) = @_; utf8::encode $path; @@ -1272,7 +1301,7 @@ my $map = cf::map::new or return; - # for better error messages only, will be overwritten + # for better error messages only, will be overwritten later $map->path ($path); $map->load_header ($path) @@ -1298,7 +1327,7 @@ my $guard = cf::lock_acquire "map_find:$key"; # do it the slow way - my $map = try_load_header $path->save_path; + my $map = $path->load_temp; Coro::cede; @@ -1309,13 +1338,8 @@ $map->{instantiate_time} = $cf::RUNTIME if $map->{instantiate_time} > $cf::RUNTIME; } else { - if (my $rmp = $path->random_map_params) { - $map = generate_random_map $key, $rmp; - } else { - $map = try_load_header $path->load_path; - } - - $map or return; + $map = $path->load_orig + or return; $map->{load_original} = 1; $map->{instantiate_time} = $cf::RUNTIME;