--- deliantra/Deliantra/Deliantra.pm 2006/02/23 15:10:08 1.32 +++ deliantra/Deliantra/Deliantra.pm 2006/03/16 01:13:02 1.45 @@ -15,8 +15,7 @@ use Carp (); use File::Spec; use List::Util qw(min max); - -#XXX: The map_* procedures scream for a map-object +use Storable; our @EXPORT = qw(read_pak read_arch %ARCH TILESIZE $TILE %FACE editor_archs arch_extents); @@ -46,24 +45,15 @@ sub MOVE_SWIM (){ 0x8 } sub MOVE_ALL (){ 0xf } -BEGIN { - if ($^O eq "MSWin32") { - eval "use FreezeThaw qw(freeze thaw)"; - } else { - eval "use Storable qw(freeze thaw)"; - } -} - sub load_ref($) { my ($path) = @_; - die if $^O eq "MSWin32"; #d# - open my $fh, "<", $path or die "$path: $!"; binmode $fh; local $/; - thaw <$fh> + + Storable::thaw <$fh> } sub save_ref($$) { @@ -72,7 +62,7 @@ open my $fh, ">", "$path~" or die "$path~: $!"; binmode $fh; - print $fh freeze $ref; + print $fh Storable::freeze $ref; close $fh; rename "$path~", $path or die "$path: $!"; @@ -275,7 +265,7 @@ my $o = $ARCH{$a->{_name}} or return; - my $face = $FACE{$a->{face} || $o->{face}} + my $face = $FACE{$a->{face} || $o->{face} || "blank.111"} or (warn "no face data found for arch '$a->{_name}'"), return; if ($face->{w} > 1 || $face->{h} > 1) { @@ -321,28 +311,72 @@ require Crossfire::Data; - my $attr; + my $root; if ($arch->{type} > 0) { - $attr = $Crossfire::Data::ATTR{$arch->{type}+0}; + $root = $Crossfire::Data::ATTR{$arch->{type}+0}; } else { - $attr = $Crossfire::Data::TYPE{Misc}; + $root = $Crossfire::Data::TYPE{Misc}; type: for (@Crossfire::Data::ATTR0) { my $req = $_->{required} or die "internal error: ATTR0 without 'required'"; + keys %$req; while (my ($k, $v) = each %$req) { next type unless $arch->{$k} == $v; } - $attr = $_; + $root = $_; + } + } + + my $attr = { }; + + my @import = (\%Crossfire::Data::DEFAULT_ATTR, $root); + my (%ignore); + my (@section_order, %section, @attr_order); + + while (my $type = shift @import) { + push @import, @{$type->{import} || []}; + + $attr->{$_} ||= $type->{$_} + for qw(name desc use); + + for (@{$type->{ignore} || []}) { + $ignore{$_}++ for ref $_ ? @$_ : $_; + } + + for ([general => ($type->{attr} || [])], @{$type->{section} || []}) { + my ($name, $attr) = @$_; + push @section_order, $name; + for (@$attr) { + my ($k, $v) = @$_; + push @attr_order, $k; + $section{$name}{$k} ||= $v; + } } } - $attr || \%Crossfire::Data::DEFAULT_ATTR; + $attr->{section} = [ + map !exists $section{$_} ? () : do { + my $attr = delete $section{$_}; + + [ + $_, + map exists $attr->{$_} && !$ignore{$_} + ? [$_ => delete $attr->{$_}] : (), + @attr_order + ] + }, + + exists $section{$_} ? [$_ => delete $section{$_}] : (), + @section_order + ]; + + $attr } sub arch_edit_sections {