ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra/bin/cf-slotutil
Revision: 1.2
Committed: Sun Sep 28 07:34:51 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
Changes since 1.1: +17 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/opt/bin/perl
2    
3     use utf8;
4     use strict qw(vars subs);
5    
6     use Deliantra;
7     use IO::AIO;
8     use List::Util;
9    
10     Deliantra::load_archetypes;
11    
12     sub scan_files($$) {
13     my ($path, $cb) = @_;
14    
15     aio_scandir $path, 3, sub {
16     my ($dirs, $nondirs) = @_;
17    
18     scan_files("$path/$_", $cb) for @$dirs;
19    
20     for my $file (@$nondirs) {
21     next unless $file =~ /\.arc$/;
22    
23     my $data;
24     aio_load "$path/$file", $data, sub {
25     $cb->("$path/$file", read_arch \$data);
26     };
27     }
28     };
29     }
30    
31     sub for_all_arc($) {
32     scan_files $ENV{DELIANTRA_ARCHDIR} || ".", $_[0];
33    
34     IO::AIO::flush;
35     }
36    
37     sub extract {
38     my (undef, $filter, @slots) = @ARGV;
39    
40     $filter =~ s/%(\w+)/\$_{$1}/g;
41     $filter = eval "sub { $filter }"
42     or die $@;
43    
44     my @res;
45    
46     unshift @slots, "_name";
47    
48     my @widths = map s/\=(\d+)// && $1, @slots;
49     my @big;
50    
51     local *_;
52     for (sort keys %ARCH) {
53     *_ = $ARCH{$_};
54     next unless &$filter;
55     push @res, [@_{@slots}];
56     };
57    
58     for my $row (@res) {
59     for (0 .. $#$row) {
60     $big[$_] =1 if $row->[$_] =~ /\n/;
61     }
62     }
63     for my $i (0 .. $#widths) {
64     $widths[$i] ||= List::Util::max map length $_->[$i], \@slots, @res;
65     }
66    
67     for (0 .. $#big) {
68     $widths[$_] = length $slots[$_] if $big[$_];
69     }
70    
71     my $format = join " ", map "%-${_}s", @widths;
72     printf "$format\n", map "A$_", map $_ + 1, @widths;
73     printf "$format\n", @slots;
74     for my $row (@res) {
75     print "\n" if @big;
76    
77     printf "$format\n", map $big[$_] ? "\x{fffc}" : $row->[$_], 0 .. $#$row;
78    
79     for (grep $big[$_], 0 .. $#big) {
80     print "$row->[$_]%%\n";
81     }
82     }
83     }
84    
85     sub insert {
86 root 1.2 my ($apply) = @_;
87    
88 root 1.1 shift @ARGV;
89     my $format = <STDIN>;
90     my @slots = unpack $format, <STDIN>;
91    
92     my %res;
93    
94     while (<STDIN>) {
95     next unless /\S/;
96    
97     my @row = unpack $format, $_;
98    
99     for (0 .. $#row) {
100     next unless $row[$_] eq "\x{fffc}";
101    
102     local $/ = "%%\n";
103     chomp ($row[$_] = <STDIN>);
104     }
105    
106     $res{$row[0]} = \@row;
107     }
108    
109     for_all_arc sub {
110     my ($path, $arch) = @_;
111    
112     my $chg;
113    
114     for (keys %$arch) {
115     my $data = $res{$_}
116     or next;
117    
118     my $arch = $arch->{$_};
119    
120     for (0 .. $#$data) {
121     next if $data->[$_] eq $arch->{$slots[$_]};
122     $chg = 1;
123     $arch->{$slots[$_]} = $data->[$_];
124     }
125     }
126    
127     if ($chg) {
128     open my $fh, ">:raw:utf8", "$path~"
129     or die "$path~: $!";
130     print $fh Deliantra::archlist_to_string [
131     map $arch->{$_},
132     sort keys %$arch
133     ];
134     close $fh;
135 root 1.2
136     if ($apply) {
137     rename "$path~", $path;
138     } else {
139     system "diff", "-u", $path, "$path~";
140     unlink "$path~";
141     }
142 root 1.1 }
143     };
144     }
145    
146     binmode STDIN, ":utf8";
147     binmode STDOUT, ":utf8";
148    
149     if ($ARGV[0] eq "extract") {
150     extract;
151     } elsif ($ARGV[0] eq "diff") {
152 root 1.2 insert 0;
153     } elsif ($ARGV[0] eq "apply") {
154     insert 1;
155 root 1.1 } else {
156     die <<EOF;
157     Usage:
158    
159     $0 extract 'filter' slot...
160    
161     extract slots from server archetypes file (NOT the .arc files!)
162     Example: $0 extract '%type == 101' level
163    
164 root 1.2 $0 diff
165 root 1.1
166     generates a diff against the .arc files found
167     in \$DELIANTRA_ARCHDIR or ".".
168    
169     Example: $0 diff <file
170    
171 root 1.2 $0 apply
172    
173     like diff, but applies it in-place
174    
175 root 1.1 EOF
176     }
177    
178    
179