#! perl # mandatory # manages the worldmap by directing to other handlers cf::map->register (qr{^/world/world_(-?\d+)_(-?\d+)(?:_(-?\d+))?$}, 100); # universal our $TILE_W = 50; our $TILE_H = 50; # registry our @AREAS; sub register($$$$$$$@) { my $meta = { pkg => shift, x0 => shift, y0 => shift, z0 => shift, x1 => shift, y1 => shift, z1 => shift, @_ }; my $pkg = $meta->{pkg}; @AREAS = sort { $b->{pri} <=> $a->{pri} } $meta, grep $pkg ne $_->{pkg}, @AREAS; my $isa = \@{"$pkg\::ISA"}; @$isa = ( __PACKAGE__, grep __PACKAGE__ ne $_, @$isa ); } sub format_xyz($$;$) { sprintf "/world/world_%03d_%03d%s", $_[0], $_[1], $_[2] ? sprintf "_%03d", $_[2] : ""; } ############################################################################# sub init { my ($self) = @_; my ($x, $y, $z) = @$self{qw(x y z)} = ($1, $2, $3+0); # find handler for this area for my $meta (@AREAS) { if ( $meta->{x0} <= $x && $x <= $meta->{x1} && $meta->{y0} <= $y && $y <= $meta->{y1} && $meta->{z0} <= $z && $z <= $meta->{z1} ) { $self->{ox} = $x - $meta->{x0}; $self->{oy} = $y - $meta->{y0}; $self->{oz} = $z - $meta->{z0}; bless $self, $meta->{pkg}; $self->init_worldmap ($meta); last; } } $self->SUPER::init; } sub init_worldmap { # only for handlers } sub load_header_orig { my ($self) = @_; my ($x, $y, $z) = @$self{qw(x y z)}; $self->width ($TILE_W); $self->height ($TILE_H); $self->name (sprintf "'The World' at %+d%+d%+d", $x, $y, $z); $self->msg ("worldmap dynamically created by map-world extension"); $self->outdoor ($self->{z} >= 0); $self->default_region (cf::region::find "wilderness"); # all possible worldmap tiles also exist $self->tile_path (0, format_xyz $x, $y - 1, $z); $self->tile_path (1, format_xyz $x + 1, $y, $z); $self->tile_path (2, format_xyz $x, $y + 1, $z); $self->tile_path (3, format_xyz $x - 1, $y, $z); $self->tile_path (4, format_xyz $x, $y, $z + 1); $self->tile_path (5, format_xyz $x, $y, $z - 1); # an overlay always wins my $overlay = sprintf "%s/%s.map", $cf::MAPDIR, format_xyz $x, $y, $z; $self->{load_path} = $overlay unless Coro::AIO::aio_stat $overlay; $self->{need_create_treasure} = 1; 1 } # fill map with "default" data - first region and first archetype from palette # used when we have no map data from elsewhere sub fill { my ($self) = @_; if ($self->{z} > 0) { # hmmm... air? :) $self->add_underlay ("\x00" x ($TILE_W * $TILE_H), 0, $TILE_W, ["blocked"]); } elsif ($self->{z} < 0) { $self->add_underlay ("\x00" x ($TILE_W * $TILE_H), 0, $TILE_W, ["blocked"]); } else { $self->add_underlay ("\x00" x ($TILE_W * $TILE_H), 0, $TILE_W, ["deep_sea"]); } } #sub load { # my ($self) = @_; # # if ($self->{load_path}) { # warn "load $self\n";#d# # $self->SUPER::load; # } else { # warn "fill $self\n";#d# # my $guard = cf::lock_acquire "map_data:$self->{path}"; # # $self->alloc; # $self->fill; # $self->state (cf::MAP_ACTIVE); # $self->activate; # $self->post_load; # } #} # MUST be overwritten to call at least ->fill sub post_load { my ($self) = @_; $self->create_region_treasure if delete $self->{need_create_treasure}; }