def __init__(self, db, x, z, y): self.dirty = False self.x = x self.z = z self.y = y if db is not None: # For creating subchunks, there will be no DB. # Subchunks are stored as base key + subchunk key `/` + subchunk id (y level // 16) key = struct.pack("<iicB", x, z, b'/', y) try: data = ldb.get(db, key) except KeyError: raise NotFoundError("Subchunk at {} {}/{} not found.".format(x, z, y)) self.version, data = data[0], data[1:] if self.version != 8: raise NotImplementedError("Unsupported subchunk version {} at {} {}/{}".format(self.version, x, z, y)) numStorages, data = data[0], data[1:] self.blocks = [] for i in range(numStorages): blocks, data = self._loadBlocks(data) palette, data = self._loadPalette(data) self.blocks.append(np.empty(4096, dtype=Block)) # Prepare with correct dtype for j, block in enumerate(blocks): block = palette[block] try: # 1.13 format #if block["version"].payload != 17629200: # raise NotImplementedError("Unexpected block version {}".format(block["version"].payload)) self.blocks[i][j] = Block(block["name"].payload, block["states"].payload) # .payload to get actual val except KeyError: # 1.12 format self.blocks[i][j] = Block(block["name"].payload, block["val"].payload) # .payload to get actual val self.blocks[i] = self.blocks[i].reshape(16, 16, 16).swapaxes(1, 2) # Y and Z saved in an inverted order
def _loadVersion(self, db): try: version = ldb.get(db, self.keyBase + b"v") version = struct.unpack("<B", version)[0] if version not in [10, 13, 14, 15]: raise NotImplementedError("Unexpected chunk version {} at chunk {} {}.".format(version, self.x, self.z)) except KeyError: raise KeyError("Chunk at {}, {} does not exist.".format(self.x, self.z)) return version
def _loadEntities(self, db): try: data = ldb.get(db, self.keyBase + b"2") except KeyError: return [] data = nbt.DataReader(data) entities = [] while not data.finished(): entities.append(nbt.decode(data)) return entities
def _loadTileEntities(self, db): try: data = ldb.get(db, self.keyBase + b"1") except KeyError: return data = nbt.DataReader(data) while not data.finished(): nbtData = nbt.decode(data) x = nbtData.pop("x").payload # We add back theses with the correct value on save, they are important. y = nbtData.pop("y").payload z = nbtData.pop("z").payload block = self.getBlock(x % 16, y, z % 16) if not block: print("Warning: Cannot apply nbt to block at {} {} {} since it does not exist.".format(x, y, z)) continue block.nbt = nbtData
def _load2D(self, db): data = ldb.get(db, self.keyBase + b'-') heightMap = struct.unpack("<" + "H" * 16 * 16, data[:2 * 16 * 16]) biomes = struct.unpack("B" * 16 * 16, data[2 * 16 * 16:]) return heightMap, biomes
def get(self, key): """""" return leveldb.get(self._handle, key)