#!/opt/bin/perl use strict; no utf8; use Crossfire::Map; use Storable; use POSIX; use File::Compare; use Gtk2 -init; my %type = ( deep_sea => "#006", sea => "#008", shallow_sea => "#00a", beach => "#aa0", dunes => "#bb0", desert => "#cc0", steppe => "#880", steppelight => "#dd7", small_stones => "#eeb", marsh => "#0f8", grass => "#0f0", grassmedium => "#0e0", grassbrown => "#851", grassdark => "#274", desert => "#cc0", darkforest => "#040", evergreens => "#0a0", woods => "#080", swamp => "#660", deep_swamp => "#440", jungle_1 => "#084", flagstone => "#bbb", istone => "#bbc", hills_rocky => "#aa8", treed_hills => "#6a4", hills => "#aa4", mountain => "#ccc", mountain2 => "#cdd", mountain3 => "#ddc", mountain4 => "#ddb", mountain5 => "#ddd", s_mountain => "#dff", wasteland => "#ddf", drifts => "#eef", snow => "#eff", cobblestones => "#ea2", ); my ($part_x, $part_y); if ($ARGV[0] eq 'palette') { mkdir "/tmp/$$.palette" or die "Couldn't make /tmp/$$.palette"; for (keys %type) { my $color = $type{$_}; $color =~ s/^#//; system ("convert -size 300x30 xc:\\#$color -pointsize 32 -fill \"red\" -gravity east -draw \"text 0,0 \\\"$_\\\"\" /tmp/$$.palette/$color.png"); } system ("convert -append " . join (' ', map { my $c = $_; $c =~ s/^#//; "/tmp/$$.palette/$c.png" } sort values %type ) . " palette.png" ); system ("rm -r /tmp/$$.palette"); exit } elsif ($ARGV[0] eq 'pixel2map') { my ($x, $y) = ($ARGV[1], $ARGV[2]); $x = int ($x / 50); $y = int ($y / 50); $x += 100; $y += 100; print "gce $ENV{CROSSFIRE_LIBDIR}/maps/world/world_${x}_${y}\n"; exit } elsif ($ARGV[0] eq 'partial') { ($part_x, $part_y) = ($ARGV[1], $ARGV[2]); } elsif ($ARGV[0] =~ m/-*?:he?l?p?/) { print <] possible modes are: - palette generates the palette.png for drawing world.png - pixel2map takes 2 further arguments representing coordinates in world.png and returns the world map file where the coordinate points to. - partial takes 2 further arguments that should be X and Y coordinates of the worldmap (starting at 100/100 and ending at 129/129). it will only generate that particular worldmap. (no overlay png is generated in this mode) without any mode the complete world is regenerated from the world.png and the overlay png is written. USAGE } Crossfire::load_archetypes; open my $png, "convert world.png -depth 8 rgb:- |" or die "convert :$!"; 1500*1500*3 == read $png, my $world, 1500*1500*3 or die; my $mask; my $maskfh; unless (defined $part_x) { open my $mmaskfh, "| convert -depth 8 -size 1500x1500 rgba:- mask.png" or die "convert2: $!"; $maskfh = $mmaskfh; $mask = "\x00\x00\x00\x00" x (1500*1500); } chdir ".." unless -d "maps/."; -d "maps/world/." and -d "maps/world-overlay/." or die "need maps/world and maps/world-overlay in ."; my %color; my @pids; for my $k (keys %type) { my $v = join "", map chr, (map $_*255/15, map hex, split //, substr $type{$k}, 1); $color{$v} = $k; } for my $Y (100..129) { next if defined $part_y and $Y != $part_y; print "$Y\n";#d# for my $X (100..129) { next if defined $part_x and $X != $part_x; my $mapname = sprintf "world_%03d_%03d", $X, $Y; my $map = new_from_file Crossfire::Map "maps/world-overlay/$mapname" or die "maps/world-overlay/$mapname: $!"; { my $X = ($X - 100) * 50; my $Y = ($Y - 100) * 50; for my $y (0..49) { for my $x (0..49) { my $ofs = (($Y + $y)* 1500 + $X + $x); if (defined $mask) { substr $mask, $ofs * 4, 4, $map->{map}[$x][$y] ? "\xff\x00\x00\xff" : "\xff\xff\xff\x00"; } unless (grep $Crossfire::ARCH{$_->{_name}}{is_floor}, @{ $map->{map}[$x][$y] }) { my $type = substr $world, $ofs * 3, 3; if (my $k = $color{$type}) { unshift @{ $map->{map}[$x][$y] }, { _name => "$k", }; } else { die sprintf "colour '%s' not defined at %s+%s+%s", (unpack "H*", $type), $mapname, $x, $y, } } } } } if ((my $pid = fork)) { push @pids, $pid; waitpid shift @pids, 0 if @pids >= 3; } else { $map->write_file ("maps/world/$mapname~"); if (File::Compare::cmp "maps/world/$mapname", "maps/world/$mapname~") { print "replacing maps/world/$mapname\n"; rename "maps/world/$mapname~", "maps/world/$mapname"; } else { unlink "maps/world/$mapname~"; } warn $@ if $@; POSIX::_exit 0; } } } print $maskfh $mask if defined $mask; waitpid shift @pids, 0 if @pids >= 1;