--- deliantra/Deliantra/Deliantra.pm 2006/02/22 22:36:45 1.17 +++ deliantra/Deliantra/Deliantra.pm 2006/02/23 15:10:08 1.32 @@ -13,7 +13,7 @@ use base 'Exporter'; use Carp (); -use Storable; +use File::Spec; use List::Util qw(min max); #XXX: The map_* procedures scream for a map-object @@ -26,7 +26,7 @@ sub TILESIZE (){ 32 } -our $CACHEDIR; +our $VARDIR; our %ARCH; our %FACE; our $TILE; @@ -46,6 +46,38 @@ 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> +} + +sub save_ref($$) { + my ($ref, $path) = @_; + + open my $fh, ">", "$path~" + or die "$path~: $!"; + binmode $fh; + print $fh freeze $ref; + close $fh; + rename "$path~", $path + or die "$path: $!"; +} + sub normalize_arch($) { my ($ob) = @_; @@ -115,19 +147,20 @@ eval { defined $cache && -M $cache < -M $path - && Storable::retrieve $cache + && load_ref $cache } or do { my %pak; - open my $fh, "<:raw", $path + open my $fh, "<", $path or Carp::croak "$_[0]: $!"; + binmode $fh; while (<$fh>) { my ($type, $id, $len, $path) = split; $path =~ s/.*\///; read $fh, $pak{$path}, $len; } - Storable::nstore \%pak, $cache + save_ref \%pak, $cache if defined $cache; \%pak @@ -140,14 +173,16 @@ eval { defined $cache && -M $cache < -M $path - && Storable::retrieve $cache + && load_ref $cache } or do { my %arc; my ($more, $prev); - open my $fh, "<:raw", $path + open my $fh, "<", $path or Carp::croak "$path: $!"; + binmode $fh; + my $parse_block; $parse_block = sub { my %arc = @_; @@ -205,7 +240,7 @@ undef $parse_block; # work around bug in perl not freeing $fh etc. - Storable::nstore \%arc, $cache + save_ref \%arc, $cache if defined $cache; \%arc @@ -266,15 +301,7 @@ } } -sub init($) { - my ($cachedir) = @_; - - return if %ARCH; - - *ARCH = read_arch "$LIB/archetypes", "$cachedir/archetypes.pst"; -} - -=item $data = arch_attr $arch +=item $type = arch_attr $arch Returns a hashref describing the object and its attributes. It can contain the following keys: @@ -285,6 +312,7 @@ desc use section => [name => \%attr, name => \%attr] + import =cut @@ -293,16 +321,28 @@ require Crossfire::Data; - my %attr; + my $attr; if ($arch->{type} > 0) { - %attr = %{ $Crossfire::Data::ATTR{$arch->{type}+0} || {} }; + $attr = $Crossfire::Data::ATTR{$arch->{type}+0}; } else { - die; + $attr = $Crossfire::Data::TYPE{Misc}; + + type: + for (@Crossfire::Data::ATTR0) { + my $req = $_->{required} + or die "internal error: ATTR0 without 'required'"; + + while (my ($k, $v) = each %$req) { + next type + unless $arch->{$k} == $v; + } + + $attr = $_; + } } - use PApp::Util; - warn PApp::Util::dumpval \%attr; + $attr || \%Crossfire::Data::DEFAULT_ATTR; } sub arch_edit_sections { @@ -366,9 +406,18 @@ # } -$CACHEDIR ||= "$ENV{HOME}/.crossfire"; +sub init($) { + my ($cachedir) = @_; + + return if %ARCH; + + mkdir $cachedir, 0777; + *ARCH = read_arch "$LIB/archetypes", "$cachedir/archetypes.pst"; +} + +$VARDIR ||= $ENV{HOME} ? "$ENV{HOME}/.crossfire" : File::Spec->tmpdir . "/crossfire"; -init $CACHEDIR; +init $VARDIR; =head1 AUTHOR