Simplify the load and save interfaces. Replace the (data, data_cursor) tuples with a load_ctx object. Add an option to skip decoding tag names to unicode, improving speed and memory use if tag names are assumed to be ASCII. Make nbt.py and _nbt.pyx more consistent with each other. Use a similar method to import from _nbt.pyx as is seen in the standard library. Move pretty-print code to its own file and share it between implementations.
MCServerChunkGenerator.copyChunkAtPosition copies the compressed chunk data instead of the uncompressed tag. This is because AnvilChunk removes parts of the tag when emulating the older chunk format.
When compressing a chunk, the uncompressed tag structure in
self.root_tag is thrown away, but an AnvilChunk stores uncompressed
data in four other member variables (_Blocks, _Data, _BlockLight and
_SkyLight) too.
This fix factors out the discarding of self.root_tag into a new method
_discardUncompressed(), and overrides this method in AnvilChunk to
also throw away the Anvil-specific members.
In a number of places, all exceptions were caught and a ChunkMalformed
exception raised in their place. Some code, such as dumpSigns,
continues after a ChunkMalformed exception. In the case where the
ChunkMalformed exception was a result of a MemoryError, this will most
likely result in a flood of error messages because the MemoryError is
not likely to go away by itself.
This fix causes MemoryError exceptions to not be transformed into
ChunkMalformed exceptions, and hopefully covers all cases where this
was done. Now, when memory is exhausted, the only detail that is
output is "Exception during command: MemoryError()", rather than the
previous, more detailed output, such as:
"""
ERROR:Malformed NBT data in file: r.4.0.mca index 3776 sector 552 length 1 format deflate ()
ERROR:Incorrect chunk format in file: r.4.0.mca index 3776 sector 552 length 1 format deflate (((MemoryError(),), <traceback object at 0x1C927B98>))
"""
but the particular data that was being processed at the time of the
MemoryError is not likely to be useful information anyway.
The exception handlers in the dumpSigns and dumpChests commands
referenced ChunkMalformed in the wrong package.
This fix corrects the references, but note that this by itself is not
desirable, as ChunkMalformed is raised when a MemoryError occurs, and
the exception handlers ignore the exception. As a MemoryError is not
likely to go away by itself, this can result in a flood of error
messages being printed, instead of the existing behaviour where
execution of the command terminates due to the incorrect reference to
ChunkMalformed.
When using the dumpSigns command, if non-ASCII characters were present
in the sign text, a UnicodeDecodeError exception would occur when
concatenating the text from the sign with 'u"\n"'.
This fix decodes the sign text as UTF-8, which appears to be
consistent with the behaviour of Minecraft 1.2.5 for the following
sign text as dumped in Python using repr():
'\xc2\xa3$\xc2\xa3$\xc2\xa3$\xc2\xa3$\xc2\xa3$\xc2\xa3$\xc2\xa3$\xc2\xa3'
Additionally, this fix ensures the output file includes a signature
which makes it easier for tools to work out that the file contains
UTF-8.