isLightPopulated() === true; $stream = new BinaryStream(); $stream->putByte( ($includeLight ? self::FLAG_HAS_LIGHT : 0) | ($chunk->isPopulated() ? self::FLAG_POPULATED : 0) ); //subchunks $subChunks = $chunk->getSubChunks(); $count = $subChunks->count(); $stream->putByte($count); foreach($subChunks as $y => $subChunk){ $stream->putByte($y); $stream->putInt($subChunk->getEmptyBlockId()); $layers = $subChunk->getBlockLayers(); $stream->putByte(count($layers)); foreach($layers as $blocks){ $wordArray = $blocks->getWordArray(); $palette = $blocks->getPalette(); $stream->putByte($blocks->getBitsPerBlock()); $stream->put($wordArray); $serialPalette = pack("L*", ...$palette); $stream->putInt(strlen($serialPalette)); $stream->put($serialPalette); } if($includeLight){ $stream->put($subChunk->getBlockSkyLightArray()->getData()); $stream->put($subChunk->getBlockLightArray()->getData()); } } //biomes $stream->put($chunk->getBiomeIdArray()); if($includeLight){ $stream->put(pack("S*", ...$chunk->getHeightMapArray())); } return $stream->getBuffer(); } /** * Deserializes a fast-serialized chunk */ public static function deserialize(string $data) : Chunk{ $stream = new BinaryStream($data); $flags = $stream->getByte(); $lightPopulated = (bool) ($flags & self::FLAG_HAS_LIGHT); $terrainPopulated = (bool) ($flags & self::FLAG_POPULATED); $subChunks = []; $heightMap = null; $count = $stream->getByte(); for($subCount = 0; $subCount < $count; ++$subCount){ $y = $stream->getByte(); $airBlockId = $stream->getInt(); /** @var PalettedBlockArray[] $layers */ $layers = []; for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){ $bitsPerBlock = $stream->getByte(); $words = $stream->get(PalettedBlockArray::getExpectedWordArraySize($bitsPerBlock)); /** @var int[] $unpackedPalette */ $unpackedPalette = unpack("L*", $stream->get($stream->getInt())); //unpack() will never fail here $palette = array_values($unpackedPalette); $layers[] = PalettedBlockArray::fromData($bitsPerBlock, $words, $palette); } $subChunks[$y] = new SubChunk( $airBlockId, $layers, $lightPopulated ? new LightArray($stream->get(2048)) : null, $lightPopulated ? new LightArray($stream->get(2048)) : null ); } $biomeIds = new BiomeArray($stream->get(256)); if($lightPopulated){ /** @var int[] $unpackedHeightMap */ $unpackedHeightMap = unpack("S*", $stream->get(512)); //unpack() will never fail here $heightMap = new HeightArray(array_values($unpackedHeightMap)); } $chunk = new Chunk($subChunks, $biomeIds, $heightMap); $chunk->setPopulated($terrainPopulated); $chunk->setLightPopulated($lightPopulated); $chunk->clearTerrainDirtyFlags(); return $chunk; } }