ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra/Deliantra.pm
Revision: 1.4
Committed: Sun Feb 5 00:18:26 2006 UTC (18 years, 3 months ago) by root
Branch: MAIN
Changes since 1.3: +80 -134 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Crossfire - Crossfire maphandling
4
5 =cut
6
7 package Crossfire;
8
9 our $VERSION = '0.1';
10
11 use strict;
12
13 use Storable;
14 use List::Util qw(max);
15
16 our $LIB = $ENV{CROSSFIRE_LIBDIR}
17 or die "\$CROSSFIRE_LIBDIR must be set\n";
18
19 sub T (){ 32 }
20
21 our $ARCH;
22 our $TILE;
23
24 sub read_pak($;$) {
25 my ($path, $cache) = @_;
26
27 eval {
28 defined $cache
29 && -M $cache < -M $path
30 && Storable::retrieve $cache
31 } or do {
32 my %pak;
33
34 open my $fh, "<:raw", $path
35 or die "$_[0]: $!";
36 while (<$fh>) {
37 my ($type, $id, $len, $path) = split;
38 $path =~ s/.*\///;
39 read $fh, $pak{$path}, $len;
40 }
41
42 Storable::nstore \%pak, $cache
43 if defined $cache;
44
45 \%pak
46 }
47 }
48
49 sub read_arch($;$) {
50 my ($path, $cache) = @_;
51
52 eval {
53 defined $cache
54 && -M $cache < -M $path
55 && Storable::retrieve $cache
56 } or do {
57 my %arc;
58 my ($more, $prev);
59
60 open my $fh, "<:raw", $path
61 or die "$path: $!";
62
63 my $parse_block; $parse_block = sub {
64 my %arc = @_;
65
66 while (<$fh>) {
67 s/\s+$//;
68 if (/^end$/i) {
69 last;
70 } elsif (/^arch (\S+)$/) {
71 push @{ $arc{inventory} }, $parse_block->(_name => $1);
72 } elsif (/^lore$/) {
73 while (<$fh>) {
74 last if /^endlore\s*$/i;
75 $arc{lore} .= $_;
76 }
77 } elsif (/^msg$/) {
78 while (<$fh>) {
79 last if /^endmsg\s*$/i;
80 $arc{msg} .= $_;
81 }
82 } elsif (/^(\S+)\s*(.*)$/) {
83 $arc{lc $1} = $2;
84 } elsif (/^\s*($|#)/) {
85 #
86 } else {
87 warn "$path: unparsable line '$_' in arch $arc{_name}";
88 }
89 }
90
91 \%arc
92 };
93
94 while (<$fh>) {
95 s/\s+$//;
96 if (/^more$/i) {
97 $more = $prev;
98 } elsif (/^object (\S+)$/i) {
99 my $name = $1;
100 my $arc = $parse_block->(_name => $name);
101
102 if ($more) {
103 $more->{more} = $arc;
104 } else {
105 $arc{$name} = $arc;
106 }
107 $prev = $arc;
108 $more = undef;
109 } elsif (/^arch (\S+)$/i) {
110 push @{ $arc{arch} }, $parse_block->(_name => $1);
111 } elsif (/^\s*($|#)/) {
112 #
113 } else {
114 warn "$path: unparseable top-level line '$_'";
115 }
116 }
117
118 undef $parse_block; # work around bug in perl not freeing $fh etc.
119
120 Storable::nstore \%arc, $cache
121 if defined $cache;
122
123 \%arc
124 }
125 }
126
127 sub arch2map($;$) {
128 my ($mapa) = @_;
129
130 my %meta;
131
132 my ($mapx, $mapy);
133
134 my $map;
135
136 for (@{ $mapa->{arch} }) {
137 my ($x, $y) = ($_->{x}, $_->{y});
138
139 if ($_->{_name} eq "map") {
140 $meta{info} = $_;
141
142 $mapx = $_->{width} || $x;
143 $mapy = $_->{height} || $y;
144 } else {
145 push @{ $map->[$x][$y] }, $_;
146
147 # arch map is unreliable w.r.t. width and height
148 $mapx = $x + 1 if $mapx <= $x;
149 $mapy = $y + 1 if $mapy <= $y;
150 #$mapx = $a->{x} + 1, warn "$mapname: arch '$a->{_name}' outside map width at ($a->{x}|$a->{y})\n" if $mapx <= $a->{x};
151 #$mapy = $a->{y} + 1, warn "$mapname: arch '$a->{_name}' outside map height at ($a->{x}|$a->{y})\n" if $mapy <= $a->{y};
152 }
153 }
154
155 $meta{width} = $mapx;
156 $meta{height} = $mapy;
157
158 \%meta
159 }
160
161 sub init($) {
162 my ($cachedir) = @_;
163
164 $ARCH = read_arch "$LIB/archetypes", "$cachedir/archetypes.pst";
165 $TILE = read_pak "$LIB/crossfire.0", "$cachedir/crossfire.0.pst";
166 }
167
168 =head1 AUTHOR
169
170 Marc Lehmann <schmorp@schmorp.de>
171 http://home.schmorp.de/
172
173 Robin Redeker <elmex@ta-sa.org>
174 http://www.ta-sa.org/
175
176 =cut
177
178 1