getWordArray(); $palette = $array->getPalette(); $stream->putByte($array->getBitsPerBlock()); $stream->put($wordArray); $serialPalette = pack("L*", ...$palette); $stream->putInt(strlen($serialPalette)); $stream->put($serialPalette); } /** * Fast-serializes the chunk for passing between threads * TODO: tiles and entities */ public static function serializeTerrain(Chunk $chunk) : string{ $stream = new BinaryStream(); $stream->putByte( ($chunk->isPopulated() ? self::FLAG_POPULATED : 0) ); //subchunks $subChunks = $chunk->getSubChunks(); $count = count($subChunks); $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){ self::serializePalettedArray($stream, $blocks); } self::serializePalettedArray($stream, $subChunk->getBiomeArray()); } return $stream->getBuffer(); } private static function deserializePalettedArray(BinaryStream $stream) : PalettedBlockArray{ $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); return PalettedBlockArray::fromData($bitsPerBlock, $words, $palette); } /** * Deserializes a fast-serialized chunk */ public static function deserializeTerrain(string $data) : Chunk{ $stream = new BinaryStream($data); $flags = $stream->getByte(); $terrainPopulated = (bool) ($flags & self::FLAG_POPULATED); $subChunks = []; $count = $stream->getByte(); for($subCount = 0; $subCount < $count; ++$subCount){ $y = Binary::signByte($stream->getByte()); $airBlockId = $stream->getInt(); $layers = []; for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){ $layers[] = self::deserializePalettedArray($stream); } $biomeArray = self::deserializePalettedArray($stream); $subChunks[$y] = new SubChunk($airBlockId, $layers, $biomeArray); } return new Chunk($subChunks, $terrainPopulated); } }