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.37 by root, Tue Jul 10 16:24:00 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 }
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 $file =~ s/\.res$//;
398 $file =~ /\.([^.]+)$/
399 or next;
400
401 my $type = $1;
402
403 substr $dir, 0, 1 + length $PATH, "";
404
405 $RESOURCE{"$dir/$file"} = {
406 type => $1,
407 copyright => "", # TODO
408 data => $data,
409 chksum => Digest::MD5::md5 $data,
410 };
411 }
412 }
413
349 sub find_files; 414 sub find_files;
350 sub find_files { 415 sub find_files {
351 my ($path) = @_; 416 my ($path) = @_;
352 417
353 IO::AIO::aioreq_pri 4; 418 IO::AIO::aioreq_pri 4;
362 push @png, ["$path/$file", 0]; 427 push @png, ["$path/$file", 0];
363 } elsif ($file =~ /\.trs$/) { 428 } elsif ($file =~ /\.trs$/) {
364 push @trs, [$path, $file]; 429 push @trs, [$path, $file];
365 } elsif ($file =~ /\.arc$/) { 430 } elsif ($file =~ /\.arc$/) {
366 push @arc, [$path, $file]; 431 push @arc, [$path, $file];
432 } elsif ($file =~ /\.(ogg|res)$/) {
433 push @res, [$path, $file];
367 } else { 434 } else {
368 warn "ignoring $path/$file\n" if $VERBOSE >= 2; 435 warn "ignoring $path/$file\n" if $VERBOSE >= 3;
369 } 436 }
370 } 437 }
371 }; 438 };
372 } 439 }
373 440
374 sub inst_arch($) { 441 sub inst_arch($) {
375 my (undef, $path) = @_; 442 my (undef, $path) = @_;
376 443
444 $PATH = $path;
445
446 print "\n",
377 print "Installing '$path' to '$DATADIR'\n", 447 "Installing '$path' to '$DATADIR'\n",
448 "\n",
378 "This can take a long time if you run this\n", 449 "This can take a long time if you run this\n",
379 "for the first time or do not use --cache.\n", 450 "for the first time or do not use --cache.\n",
380 "\n", 451 "\n",
381 "Unless you run verbosely, all following warning\n", 452 "Unless you run verbosely, all following warning\n",
382 "or error messages indicate serious problems.\n", 453 "or error messages indicate serious problems.\n",
393 $_->join for ( 464 $_->join for (
394 # four png crunchers work fine for my 2x smp machine 465 # four png crunchers work fine for my 2x smp machine
395 (async \&process_png), (async \&process_png), (async \&process_png), (async \&process_png), 466 (async \&process_png), (async \&process_png), (async \&process_png), (async \&process_png),
396 (async \&process_trs), (async \&process_trs), 467 (async \&process_trs), (async \&process_trs),
397 (async \&process_arc), (async \&process_arc), 468 (async \&process_arc), (async \&process_arc),
469 (async \&process_res), (async \&process_res),
398 ); 470 );
399 471
400 { 472 {
401 # remove path prefix from editor_folder 473 # remove path prefix from editor_folder
402 substr $_->{editor_folder}, 0, 1 + length $path, "" 474 substr $_->{editor_folder}, 0, 1 + length $path, ""
412 if (my $s = $ARC{$other}) { 484 if (my $s = $ARC{$other}) {
413 if ($s->{inherit}) { 485 if ($s->{inherit}) {
414 $loop = $s; 486 $loop = $s;
415 } else { 487 } else {
416 delete $o->{inherit}; 488 delete $o->{inherit};
489 my %s = %$s;
490 delete @s{qw(_name more name name_pl)};
417 %$o = ( %$s, %$o ); 491 %$o = ( %s, %$o );
418 ++$progress; 492 ++$progress;
419 } 493 }
420 } else { 494 } else {
421 warn "'$o->{_name}' tries to inherit from undefined archetype '$other', skipping.\n"; 495 warn "'$o->{_name}' tries to inherit from undefined archetype '$other', skipping.\n";
422 delete $ARC{$o->{_name}}; 496 delete $ARC{$o->{_name}};
430 504
431 last; 505 last;
432 } 506 }
433 } 507 }
434 508
509 # remove base classes (by naming scheme, should use something like "baseclass xxx" to inherit
510 @ARC = grep $_->{_name} !~ /^(?:type|class)_/, @ARC;
511
435 open my $fh, ">:utf8", "$DATADIR/archetypes~" 512 open my $fh, ">:utf8", "$DATADIR/archetypes~"
436 or die "$DATADIR/archetypes~: $!"; 513 or die "$DATADIR/archetypes~: $!";
437 print $fh Crossfire::archlist_to_string [sort { $a->{_name} cmp $b->{_name} } values %ARC]; 514 print $fh Crossfire::archlist_to_string [sort { $a->{_name} cmp $b->{_name} } @ARC];
438 } 515 }
439 516
440 { 517 {
441 open my $fh, ">:utf8", "$DATADIR/treasures~" 518 open my $fh, ">:utf8", "$DATADIR/treasures~"
442 or die "$DATADIR/treasures~: $!"; 519 or die "$DATADIR/treasures~: $!";
451 length $v->{data32} <= 10000 or warn "$k: face32 larger than 10000 bytes, will not work with crossfire client.\n"; 528 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"; 529 #length $v->{data64} <= 10000 or warn "$k: face64 larger than 10000 bytes.\n";
453 530
454 $v->{chksum32} = Digest::MD5::md5 $v->{data32}; 531 $v->{chksum32} = Digest::MD5::md5 $v->{data32};
455 $v->{chksum64} = Digest::MD5::md5 $v->{data64}; 532 $v->{chksum64} = Digest::MD5::md5 $v->{data64};
533
534 if (my $magicmap = $v->{magicmap}) {
535 $magicmap =~ y/A-Z_\-/a-z/d;
536 $v->{magicmap} = $COLOR{$magicmap};
537 }
456 } 538 }
457 539
458 open my $fh, ">:perlio", "$DATADIR/facedata~" 540 open my $fh, ">:perlio", "$DATADIR/facedata~"
459 or die "$DATADIR/facedata~: $!"; 541 or die "$DATADIR/facedata~: $!";
460 542
461 print $fh freeze { 543 print $fh freeze {
462 version => 2, 544 version => 2,
463 faceinfo => \%FACEINFO, 545 faceinfo => \%FACEINFO,
464 animinfo => \%ANIMINFO, 546 animinfo => \%ANIMINFO,
547 resource => \%RESOURCE,
465 }; 548 };
466 } 549 }
467 550
468 for (qw(archetypes facedata treasures)) { 551 for (qw(archetypes facedata treasures)) {
469 chmod 0644, "$DATADIR/$_~"; 552 chmod 0644, "$DATADIR/$_~";

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines