1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00

Sort NBT when writing

This should fix the worst cases of #1196.
This commit is contained in:
Jonathan Coates 2022-10-30 16:47:26 +00:00
parent 1490ca8624
commit 14cb97cba1
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06

View File

@ -18,6 +18,7 @@
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -181,7 +182,7 @@ public static String getNBTHash( @Nullable CompoundNBT tag )
{
MessageDigest digest = MessageDigest.getInstance( "MD5" );
DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) );
CompressedStreamTools.write( tag, output );
writeTag( output, "", tag );
byte[] hash = digest.digest();
return ENCODING.encode( hash );
}
@ -192,6 +193,38 @@ public static String getNBTHash( @Nullable CompoundNBT tag )
}
}
/**
* An alternative version of {@link CompressedStreamTools#write(CompoundNBT, DataOutput)}, which sorts keys. This
* should make the output slightly more deterministic.
*
* @param output The output to write to.
* @param name The name of the key we're writing. Should be {@code ""} for the root node.
* @param tag The tag to write.
* @throws IOException If the underlying stream throws.
* @see CompressedStreamTools#write(CompoundNBT, DataOutput)
* @see CompoundNBT#write(DataOutput)
*/
private static void writeTag( DataOutput output, String name, INBT tag ) throws IOException
{
output.writeByte( tag.getId() );
if( tag.getId() == 0 ) return;
output.writeUTF( name );
if( tag instanceof CompoundNBT )
{
CompoundNBT compound = (CompoundNBT) tag;
String[] keys = compound.getAllKeys().toArray( new String[0] );
Arrays.sort( keys );
for( String key : keys ) writeTag( output, key, compound.get( key ) );
output.writeByte( 0 );
}
else
{
tag.write( output );
}
}
private static final class DigestOutputStream extends OutputStream
{
private final MessageDigest digest;