def fetch_chunk(cls, world_path: str, chunk_x: int, chunk_z: int) -> Chunk: chunk_data, timestamp = chunkio.fetchChunk( world_path, chunk_x, chunk_z) chunk_nbt = nbt.TAG_Compound.unpack( Buffer( zlib.decompress(b"".join( [ord(c).to_bytes(1, "big") for c in chunk_data])))) return Chunk(chunk_nbt, int(timestamp))
async def fetch_chunk(self, chunk_x: int, chunk_z: int) -> Chunk: key = (chunk_x, chunk_z) try: # try to fetch chunk from cache return self._chunk_cache[key] except KeyError: pass try: # try to fetch from disk return self.cache_chunk( await self.server.chunkio.fetch_chunk_async(self.path, *key), key) except FileNotFoundError: # fall back to generate chunk sections = self.server.generator.generate_chunk( self.data["RandomSeed"], self.dimension, chunk_x, chunk_z) chunk = Chunk.new(chunk_x, chunk_z, sections, int(time.time())) return self.cache_chunk(chunk)
def fetch_chunk(cls, world_path: str, chunk_x: int, chunk_z: int) -> Chunk: rx, ry = chunk_x // 32, chunk_z // 32 region_path = os.path.join(world_path, "region", f"r.{rx}.{ry}.mca") if not os.path.isfile(region_path): raise FileNotFoundError(region_path) loc_table_loc = cls.calc_offset(chunk_x, chunk_z) with open(region_path, "rb") as region_file: region_file.seek(loc_table_loc) offset, length = cls.find_chunk(region_file.read(4)) region_file.seek(loc_table_loc + 4096) timestamp = struct.unpack(">i", region_file.read(4)) region_file.seek(offset + 5) return Chunk( nbt.TAG_Compound.unpack( Buffer(zlib.decompress(region_file.read(length - 5)))), timestamp)
def generate_chunk(seed: int, dimension: str, chunk_x: int, chunk_z: int) -> Chunk: chunk = Chunk.new(chunk_x, chunk_z, int(time.time())) chunk.sections[0] = ChunkSection.new(0, DirectPalette) palette = chunk.sections[0].palette if dimension == "minecraft:overworld": chunk.sections[0].block_states[0] = palette.encode( "minecraft:bedrock") chunk.sections[0].block_states[1:3] = palette.encode( "minecraft:dirt") chunk.sections[0].block_states[3] = palette.encode( "minecraft:grass_block", {"snowy": "false"}) chunk.sections[0].block_light[0:4] = 0 chunk.sections[0].sky_light[0:3] = 0 chunk.sections[0].sky_light[3:] = 15 elif dimension == "minecraft:nether": chunk.sections[0].block_states[0] = palette.encode( "minecraft:bedrock") chunk.sections[0].block_states[1:4] = palette.encode( "minecraft:netherrack") chunk.sections[0].block_light[0:4] = 0 chunk.sections[0].sky_light[4:] = 7 elif dimension == "minecraft:the_end": chunk.sections[0].block_states[0:4] = palette.encode( "minecraft:end_stone") chunk.sections[0].block_light[0:4] = 0 chunk.sections[0].sky_light[4:] = 0 else: raise ValueError(f"Unsupported dimension: {dimension}") return chunk
def pack_chunk_light(cls, chunk: Chunk) -> bytes: out = cls.pack_varint(chunk.x) + cls.pack_varint(chunk.z) + cls.pack("?", True) sky_light_mask = 0 block_light_mask = 0 empty_sky_light_mask = 0 empty_block_light_mask = 0 sky_light_arrays = [] block_light_arrays = [] for section_y in range(-1, 17, 1): section = chunk.get(section_y) if section is None: continue print("Section y/index:", section_y) if section.sky_light is not None and len(section.sky_light.nonzero()) > 0: sky_light_mask |= 1 << section_y sky_light_array = b"" for y in range(16): for z in range(16): for x in range(0, 16, 2): sky_light_array += cls.pack( "B", (section.sky_light[y][z][x] << 4) | (section.sky_light[y][z][x + 1]), ) print("Sky light array length:", len(sky_light_array)) sky_light_arrays.append(cls.pack_varint(len(sky_light_array)) + sky_light_array) if section.block_light is not None and len(section.block_light.nonzero()) > 0: block_light_mask |= 1 << section_y block_light_array = b"" for y in range(16): for z in range(16): for x in range(0, 16, 2): block_light_array += cls.pack( "B", (section.block_light[y][z][x] << 4) | (section.block_light[y][z][x + 1]), ) print("Block light array length:", len(block_light_array)) block_light_arrays.append( cls.pack_varint(len(block_light_array)) + block_light_array ) print("Sky light mask:", sky_light_mask) print("Block light mask:", block_light_mask) out = ( cls.pack_varint(sky_light_mask) + cls.pack_varint(block_light_mask) + cls.pack_varint(empty_sky_light_mask) + cls.pack_varint(empty_block_light_mask) + b"".join(sky_light_arrays) + b"".join(block_light_arrays) ) return out # [:len(out) - 4095]