ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/utils/cfutil.in
(Generate patch)

Comparing deliantra/server/utils/cfutil.in (file contents):
Revision 1.27 by root, Wed Apr 18 07:59:03 2007 UTC vs.
Revision 1.40 by root, Mon Jul 16 19:43:33 2007 UTC

6my $exec_prefix = "@exec_prefix@"; 6my $exec_prefix = "@exec_prefix@";
7my $datarootdir = "@datarootdir@"; 7my $datarootdir = "@datarootdir@";
8my $DATADIR = "@datadir@/@PACKAGE@"; 8my $DATADIR = "@datadir@/@PACKAGE@";
9 9
10my $CONVERT = "@CONVERT@"; 10my $CONVERT = "@CONVERT@";
11my $IDENTIFY = "@IDENTIFY@"; 11#my $IDENTIFY = "@IDENTIFY@";
12my $OPTIPNG = "@OPTIPNG@"; 12my $OPTIPNG = "@OPTIPNG@";
13my $RSYNC = "@RSYNC@"; 13my $RSYNC = "@RSYNC@";
14my $PNGNQ = "@PNGNQ@";
14 15
15use Getopt::Long; 16use Getopt::Long;
16use Coro::Event; 17use Coro::Event;
17use AnyEvent; 18use AnyEvent;
18use IO::AIO (); 19use IO::AIO ();
42my $CACHE = 0; 43my $CACHE = 0;
43my $FORCE; 44my $FORCE;
44my $TMPDIR = "/tmp/cfutil$$~"; 45my $TMPDIR = "/tmp/cfutil$$~";
45my $TMPFILE = "aaaa0"; 46my $TMPFILE = "aaaa0";
46 47
48our %COLOR = (
49 black => 0,
50 white => 1,
51 navy => 2,
52 red => 3,
53 orange => 4,
54 blue => 5,
55 darkorange => 6,
56 green => 7,
57 lightgreen => 8,
58 grey => 9,
59 brown => 10,
60 gold => 11,
61 tan => 12,
62);
63
47END { system "rm", "-rf", $TMPDIR } 64END { system "rm", "-rf", $TMPDIR }
48 65
49Event->signal (signal => "INT", cb => sub { exit 1 }); 66Event->signal (signal => "INT", cb => sub { exit 1 });
50Event->signal (signal => "TERM", cb => sub { exit 1 }); 67Event->signal (signal => "TERM", cb => sub { exit 1 });
51 68
68} 85}
69 86
70sub inst_maps($) { 87sub inst_maps($) {
71 my (undef, $path) = @_; 88 my (undef, $path) = @_;
72 89
73 print "installing '$path' to '$DATADIR/maps'\n"; 90 print "\nInstalling '$path' to '$DATADIR/maps'\n\n";
74 91
75 if (!-f "$path/regions") { 92 if (!-f "$path/regions") {
76 warn "'$path' does not look like a maps directory ('regions' file is missing).\n"; 93 warn "'$path' does not look like a maps directory ('regions' file is missing).\n";
77 exit 1 unless $FORCE; 94 exit 1 unless $FORCE;
78 } 95 }
79 96
80 system $RSYNC, "-av", "$path/.", "$DATADIR/maps/.", "--delete", "--exclude", "CVS", "--delete-excluded" 97 system $RSYNC, "-av", "--chmod=u=rwX,go=rX", "$path/.", "$DATADIR/maps/.", "--delete", "--exclude", "CVS", "--delete-excluded"
81 and die "map installation failed.\n"; 98 and die "map installation failed.\n";
82 99
83 print "maps installed successfully.\n"; 100 print "maps installed successfully.\n";
84} 101}
85 102
86{ 103{
87 our %ANIMINFO; 104 our %ANIMINFO;
88 our %FACEINFO; 105 our %FACEINFO;
106 our %RESOURCE;
107 our @ARC;
89 our %ARC; 108 our %ARC;
90 our $TRS; 109 our $TRS;
91 our $NFILE; 110 our $NFILE;
111 our $PATH;
92 112
93 our $QUANTIZE = "+dither -colorspace RGB -colors 256"; 113 our $QUANTIZE = "+dither -colorspace RGB -colors 256";
94 114
95 our (@png, @trs, @arc); # files we are interested in 115 our (@png, @trs, @arc, @res); # files we are interested in
96 116
97 sub commit_png($$$) { 117 sub commit_png($$$) {
98 my ($name, $data, $T) = @_; 118 my ($name, $data, $T) = @_;
99 119
100 $FACEINFO{$name}{"data$T"} = $data; 120 $FACEINFO{$name}{"data$T"} = $data;
153 fork_sub { 173 fork_sub {
154 system "convert png:\Q$path\E -depth 8 rgba:-" 174 system "convert png:\Q$path\E -depth 8 rgba:-"
155 . "| $exec_prefix/bin/cfhq2xa $w $h $wrap" 175 . "| $exec_prefix/bin/cfhq2xa $w $h $wrap"
156 . "| convert -depth 8 -size ".($w * 2)."x".($h * 2)." rgba:- $QUANTIZE -quality 00 png32:\Q$other\E~" 176 . "| convert -depth 8 -size ".($w * 2)."x".($h * 2)." rgba:- $QUANTIZE -quality 00 png32:\Q$other\E~"
157 and die "convert/hq2xa pipeline error: status $? ($!)"; 177 and die "convert/hq2xa pipeline error: status $? ($!)";
158 system $OPTIPNG, "-o5", "-i0", "-q", "$other~"; 178 system $OPTIPNG, "-i0", "-q", "$other~";
159 die "$other~ has zero size, aborting." unless -s "$other~"; 179 die "$other~ has zero size, aborting." unless -s "$other~";
160 rename "$other~", $other; 180 rename "$other~", $other;
161 }; 181 };
162 } 182 }
163 183
169 my $other = "$stem.32x32.png~"; 189 my $other = "$stem.32x32.png~";
170 190
171 if (0 > aio_lstat $other or (-M _) > (-M $path)) { 191 if (0 > aio_lstat $other or (-M _) > (-M $path)) {
172 fork_sub { 192 fork_sub {
173 system "convert png:\Q$path\E -geometry 50% -filter lanczos $QUANTIZE -quality 00 png32:\Q$other\E~"; 193 system "convert png:\Q$path\E -geometry 50% -filter lanczos $QUANTIZE -quality 00 png32:\Q$other\E~";
174 system $OPTIPNG, "-o5", "-i0", "-q", "$other~"; 194 system $OPTIPNG, "-i0", "-q", "$other~";
195
196 # reduce smoothfaces >10000 bytes
197 if ($stem =~ /_S\./ && (-s "$other~") > 10000) {
198 my $ncolor = 256;
199 while () {
200 system "<\Q$other~\E $PNGNQ -s1 -n$ncolor >\Q$other~~\E";
201 system $OPTIPNG, "-i0", "-q", "$other~~";
202 last if 10000 > -s "$other~~";
203 $ncolor = int $ncolor * 0.9;
204 $ncolor > 8 or die "cannot reduce filesize to < 10000 bytes";
205 }
206
207 printf "reduced %s from %d to %d bytes using %d colours.\n",
208 $other, -s "$other~", -s "$other~~", $ncolor
209 if $VERBOSE >= 2;
210 rename "$other~~", "$other~";
211 }
212
175 die "$other~ has zero size, aborting." unless -s "$other~"; 213 die "$other~ has zero size, aborting." unless -s "$other~";
176 rename "$other~", $other; 214 rename "$other~", $other;
177 }; 215 };
178 } 216 }
179 217
255 my $arc; 293 my $arc;
256 aio_load "$dir/$file", $arc; # simply pre-cache, as read_arch wants a file :/ 294 aio_load "$dir/$file", $arc; # simply pre-cache, as read_arch wants a file :/
257 295
258 my $arc = read_arch "$dir/$file"; 296 my $arc = read_arch "$dir/$file";
259 for my $o (values %$arc) { 297 for my $o (values %$arc) {
298 push @ARC, $o;
299 for (my $m = $o; $m; $m = $m->{more}) {
260 $ARC{$o->{_name}} = $o; 300 $ARC{$m->{_name}} = $m;
301 }
261 302
262 $o->{editor_folder} = $dir; 303 $o->{editor_folder} = $dir;
263 304
264 my $visibility = delete $o->{visibility}; 305 my $visibility = delete $o->{visibility};
265 my $magicmap = delete $o->{magicmap}; 306 my $magicmap = delete $o->{magicmap};
278 319
279 my $ext = $x|$y ? "+$x+$y" : ""; 320 my $ext = $x|$y ? "+$x+$y" : "";
280 321
281 $o->{face} .= $ext unless /^blank.x11$|^empty.x11$/ || !$o->{face}; 322 $o->{face} .= $ext unless /^blank.x11$|^empty.x11$/ || !$o->{face};
282 323
283 my $visibility = delete $o->{visibility} if exists $o->{visibility}; 324 $visibility = delete $o->{visibility} if exists $o->{visibility};
284 my $magicmap = delete $o->{magicmap} if exists $o->{magicmap}; 325 $magicmap = delete $o->{magicmap} if exists $o->{magicmap};
285 326
286 my $anim = delete $o->{anim}; 327 my $anim = delete $o->{anim};
287 328
288 if ($anim) { 329 if ($anim) {
289 # possibly add $ext to the animation name to avoid 330 # possibly add $ext to the animation name to avoid
344 385
345 $TRS .= $trs; 386 $TRS .= $trs;
346 } 387 }
347 } 388 }
348 389
390 sub process_res {
391 while (@res) {
392 my ($dir, $file) = @{pop @res};
393
394 my $data;
395 aio_load "$dir/$file", $data;
396
397 my $copyright;
398 aio_load "$dir/copyright", $copyright;
399
400 $file =~ s/\.res$//;
401 $file =~ /\.([^.]+)$/
402 or next;
403
404 my $type = $1;
405
406 substr $dir, 0, 1 + length $PATH, "";
407
408 $RESOURCE{"$dir/$file"} = {
409 type => $1,
410 copyright => $copyright,
411 data => $data,
412 chksum => Digest::MD5::md5 $data,
413 };
414 }
415 }
416
349 sub find_files; 417 sub find_files;
350 sub find_files { 418 sub find_files {
351 my ($path) = @_; 419 my ($path) = @_;
352 420
353 IO::AIO::aioreq_pri 4; 421 IO::AIO::aioreq_pri 4;
362 push @png, ["$path/$file", 0]; 430 push @png, ["$path/$file", 0];
363 } elsif ($file =~ /\.trs$/) { 431 } elsif ($file =~ /\.trs$/) {
364 push @trs, [$path, $file]; 432 push @trs, [$path, $file];
365 } elsif ($file =~ /\.arc$/) { 433 } elsif ($file =~ /\.arc$/) {
366 push @arc, [$path, $file]; 434 push @arc, [$path, $file];
435 } elsif ($file =~ /\.(ogg|jpg|res)$/) {
436 push @res, [$path, $file];
367 } else { 437 } else {
368 warn "ignoring $path/$file\n" if $VERBOSE >= 2; 438 warn "ignoring $path/$file\n" if $VERBOSE >= 3;
369 } 439 }
370 } 440 }
371 }; 441 };
372 } 442 }
373 443
374 sub inst_arch($) { 444 sub inst_arch($) {
375 my (undef, $path) = @_; 445 my (undef, $path) = @_;
376 446
447 $PATH = $path;
448
449 print "\n",
377 print "Installing '$path' to '$DATADIR'\n", 450 "Installing '$path' to '$DATADIR'\n",
451 "\n",
378 "This can take a long time if you run this\n", 452 "This can take a long time if you run this\n",
379 "for the first time or do not use --cache.\n", 453 "for the first time or do not use --cache.\n",
380 "\n", 454 "\n",
381 "Unless you run verbosely, all following warning\n", 455 "Unless you run verbosely, all following warning\n",
382 "or error messages indicate serious problems.\n", 456 "or error messages indicate serious problems.\n",
393 $_->join for ( 467 $_->join for (
394 # four png crunchers work fine for my 2x smp machine 468 # four png crunchers work fine for my 2x smp machine
395 (async \&process_png), (async \&process_png), (async \&process_png), (async \&process_png), 469 (async \&process_png), (async \&process_png), (async \&process_png), (async \&process_png),
396 (async \&process_trs), (async \&process_trs), 470 (async \&process_trs), (async \&process_trs),
397 (async \&process_arc), (async \&process_arc), 471 (async \&process_arc), (async \&process_arc),
472 (async \&process_res), (async \&process_res),
398 ); 473 );
399 474
400 { 475 {
401 # remove path prefix from editor_folder 476 # remove path prefix from editor_folder
402 substr $_->{editor_folder}, 0, 1 + length $path, "" 477 substr $_->{editor_folder}, 0, 1 + length $path, ""
412 if (my $s = $ARC{$other}) { 487 if (my $s = $ARC{$other}) {
413 if ($s->{inherit}) { 488 if ($s->{inherit}) {
414 $loop = $s; 489 $loop = $s;
415 } else { 490 } else {
416 delete $o->{inherit}; 491 delete $o->{inherit};
492 my %s = %$s;
493 delete @s{qw(_name more name name_pl)};
417 %$o = ( %$s, %$o ); 494 %$o = ( %s, %$o );
418 ++$progress; 495 ++$progress;
419 } 496 }
420 } else { 497 } else {
421 warn "'$o->{_name}' tries to inherit from undefined archetype '$other', skipping.\n"; 498 warn "'$o->{_name}' tries to inherit from undefined archetype '$other', skipping.\n";
422 delete $ARC{$o->{_name}}; 499 delete $ARC{$o->{_name}};
430 507
431 last; 508 last;
432 } 509 }
433 } 510 }
434 511
512 # remove base classes (by naming scheme, should use something like "baseclass xxx" to inherit
513 @ARC = grep $_->{_name} !~ /^(?:type|class)_/, @ARC;
514
435 open my $fh, ">:utf8", "$DATADIR/archetypes~" 515 open my $fh, ">:utf8", "$DATADIR/archetypes~"
436 or die "$DATADIR/archetypes~: $!"; 516 or die "$DATADIR/archetypes~: $!";
437 print $fh Crossfire::archlist_to_string [sort { $a->{_name} cmp $b->{_name} } values %ARC]; 517 print $fh Crossfire::archlist_to_string [sort { $a->{_name} cmp $b->{_name} } @ARC];
438 } 518 }
439 519
440 { 520 {
441 open my $fh, ">:utf8", "$DATADIR/treasures~" 521 open my $fh, ">:utf8", "$DATADIR/treasures~"
442 or die "$DATADIR/treasures~: $!"; 522 or die "$DATADIR/treasures~: $!";
451 length $v->{data32} <= 10000 or warn "$k: face32 larger than 10000 bytes, will not work with crossfire client.\n"; 531 length $v->{data32} <= 10000 or warn "$k: face32 larger than 10000 bytes, will not work with crossfire client.\n";
452 #length $v->{data64} <= 10000 or warn "$k: face64 larger than 10000 bytes.\n"; 532 #length $v->{data64} <= 10000 or warn "$k: face64 larger than 10000 bytes.\n";
453 533
454 $v->{chksum32} = Digest::MD5::md5 $v->{data32}; 534 $v->{chksum32} = Digest::MD5::md5 $v->{data32};
455 $v->{chksum64} = Digest::MD5::md5 $v->{data64}; 535 $v->{chksum64} = Digest::MD5::md5 $v->{data64};
536
537 if (my $magicmap = $v->{magicmap}) {
538 $magicmap =~ y/A-Z_\-/a-z/d;
539 $v->{magicmap} = $COLOR{$magicmap};
540 }
456 } 541 }
457 542
458 open my $fh, ">:perlio", "$DATADIR/facedata~" 543 open my $fh, ">:perlio", "$DATADIR/facedata~"
459 or die "$DATADIR/facedata~: $!"; 544 or die "$DATADIR/facedata~: $!";
460 545
461 print $fh freeze { 546 print $fh freeze {
462 version => 2, 547 version => 2,
463 faceinfo => \%FACEINFO, 548 faceinfo => \%FACEINFO,
464 animinfo => \%ANIMINFO, 549 animinfo => \%ANIMINFO,
550 resource => \%RESOURCE,
465 }; 551 };
466 } 552 }
467 553
468 for (qw(archetypes facedata treasures)) { 554 for (qw(archetypes facedata treasures)) {
469 chmod 0644, "$DATADIR/$_~"; 555 chmod 0644, "$DATADIR/$_~";

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines