--- deliantra/server/utils/cfutil.in 2009/11/04 13:46:37 1.78 +++ deliantra/server/utils/cfutil.in 2009/11/15 18:04:00 1.79 @@ -45,6 +45,7 @@ use YAML::XS (); use JSON::XS (); use IO::AIO (); +use Digest::MD5 (); use Coro 5.12; use Coro::AIO; @@ -97,6 +98,28 @@ my $s_INT = EV::signal INT => sub { exit 1 }; my $s_TERM = EV::signal TERM => sub { exit 1 }; +our %hash; + +# here we could try to avoid collisions and reduce chksum size further +sub make_hash($\$\$;$) { + my ($id, $dataref, $hashref, $clen) = @_; + + my $hash = substr +(Digest::MD5::md5 $$dataref), 0, $clen || 4; + + if (exists $hash{$hash}) { + # hahs collinion, but some files are simply identical + if (${$hash{$hash}[1]} ne $$dataref) { + warn "hash collision $hash{$hash}[0] vs. $id\n"; + exit 1; + } else { + print "$hash{$hash}[0] and $id are identical (which is fine).\n" if $VERBOSE >= 3; + } + } + $hash{$hash} = [$id, $dataref, $hashref]; + + $$hashref = $hash; +} + mkdir $TMPDIR, 0700 or die "$TMPDIR: $!"; @@ -763,6 +786,9 @@ length $v->{data32} or warn "$k: face has no png32. this will not work (shoddy gcfclient will crash of course).\n"; length $v->{data64} or warn "$k: face has no png64. this will not work very well.\n"; + make_hash $k, $v->{data32}, $v->{hash32}; + make_hash $k, $v->{data64}, $v->{hash64}; + #length $v->{data32} <= 10000 or warn "$k: face32 larger than 10000 bytes, will not work with crossfire client.\n"; #length $v->{data64} <= 10000 or warn "$k: face64 larger than 10000 bytes.\n"; @@ -774,6 +800,24 @@ delete $v->{arc}; } + print "processing resources...\n" if $VERBOSE; + my $enc = JSON::XS->new->utf8->canonical->relaxed; + while (my ($k, $v) = each %RESOURCE) { + + if ($v->{type} & 1) { + # prepend meta info + + my $meta = $enc->encode ({ + name => $k, + %{ $v->{meta} || {} }, + }); + + $v->{data} = pack "(w/a*)*", $meta, $v->{data}; + } + + make_hash $k, $v->{data}, $v->{hash}, 6; # 6 for the benefit of existing clients + } + printf "writing facedata (%d faces, %d anims, %d resources)...\n", scalar keys %FACEINFO, scalar keys %ANIMINFO,