PocketMine-MP 5.21.1 git-2ff647079265e7c600203af4fd902b15e99d49a4
LevelChunkPacket.php
1<?php
2
3/*
4 * This file is part of BedrockProtocol.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/BedrockProtocol>
6 *
7 * BedrockProtocol is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13declare(strict_types=1);
14
15namespace pocketmine\network\mcpe\protocol;
16
21use function count;
22use const PHP_INT_MAX;
23
25 public const NETWORK_ID = ProtocolInfo::LEVEL_CHUNK_PACKET;
26
30 private const CLIENT_REQUEST_FULL_COLUMN_FAKE_COUNT = Limits::UINT32_MAX;
35 private const CLIENT_REQUEST_TRUNCATED_COLUMN_FAKE_COUNT = Limits::UINT32_MAX - 1;
36
37 //this appears large enough for a world height of 1024 blocks - it may need to be increased in the future
38 private const MAX_BLOB_HASHES = 64;
39
40 private ChunkPosition $chunkPosition;
42 private int $dimensionId;
43 private int $subChunkCount;
44 private bool $clientSubChunkRequestsEnabled;
46 private ?array $usedBlobHashes = null;
47 private string $extraPayload;
48
54 public static function create(ChunkPosition $chunkPosition, int $dimensionId, int $subChunkCount, bool $clientSubChunkRequestsEnabled, ?array $usedBlobHashes, string $extraPayload) : self{
55 $result = new self;
56 $result->chunkPosition = $chunkPosition;
57 $result->dimensionId = $dimensionId;
58 $result->subChunkCount = $subChunkCount;
59 $result->clientSubChunkRequestsEnabled = $clientSubChunkRequestsEnabled;
60 $result->usedBlobHashes = $usedBlobHashes;
61 $result->extraPayload = $extraPayload;
62 return $result;
63 }
64
65 public function getChunkPosition() : ChunkPosition{ return $this->chunkPosition; }
66
67 public function getDimensionId() : int{ return $this->dimensionId; }
68
69 public function getSubChunkCount() : int{
70 return $this->subChunkCount;
71 }
72
73 public function isClientSubChunkRequestEnabled() : bool{
74 return $this->clientSubChunkRequestsEnabled;
75 }
76
77 public function isCacheEnabled() : bool{
78 return $this->usedBlobHashes !== null;
79 }
80
84 public function getUsedBlobHashes() : ?array{
85 return $this->usedBlobHashes;
86 }
87
88 public function getExtraPayload() : string{
89 return $this->extraPayload;
90 }
91
92 protected function decodePayload(PacketSerializer $in) : void{
93 $this->chunkPosition = ChunkPosition::read($in);
94 $this->dimensionId = $in->getVarInt();
95
96 $subChunkCountButNotReally = $in->getUnsignedVarInt();
97 if($subChunkCountButNotReally === self::CLIENT_REQUEST_FULL_COLUMN_FAKE_COUNT){
98 $this->clientSubChunkRequestsEnabled = true;
99 $this->subChunkCount = PHP_INT_MAX;
100 }elseif($subChunkCountButNotReally === self::CLIENT_REQUEST_TRUNCATED_COLUMN_FAKE_COUNT){
101 $this->clientSubChunkRequestsEnabled = true;
102 $this->subChunkCount = $in->getLShort();
103 }else{
104 $this->clientSubChunkRequestsEnabled = false;
105 $this->subChunkCount = $subChunkCountButNotReally;
106 }
107
108 $cacheEnabled = $in->getBool();
109 if($cacheEnabled){
110 $this->usedBlobHashes = [];
111 $count = $in->getUnsignedVarInt();
112 if($count > self::MAX_BLOB_HASHES){
113 throw new PacketDecodeException("Expected at most " . self::MAX_BLOB_HASHES . " blob hashes, got " . $count);
114 }
115 for($i = 0; $i < $count; ++$i){
116 $this->usedBlobHashes[] = $in->getLLong();
117 }
118 }
119 $this->extraPayload = $in->getString();
120 }
121
122 protected function encodePayload(PacketSerializer $out) : void{
123 $this->chunkPosition->write($out);
124 $out->putVarInt($this->dimensionId);
125
126 if($this->clientSubChunkRequestsEnabled){
127 if($this->subChunkCount === PHP_INT_MAX){
128 $out->putUnsignedVarInt(self::CLIENT_REQUEST_FULL_COLUMN_FAKE_COUNT);
129 }else{
130 $out->putUnsignedVarInt(self::CLIENT_REQUEST_TRUNCATED_COLUMN_FAKE_COUNT);
131 $out->putLShort($this->subChunkCount);
132 }
133 }else{
134 $out->putUnsignedVarInt($this->subChunkCount);
135 }
136
137 $out->putBool($this->usedBlobHashes !== null);
138 if($this->usedBlobHashes !== null){
139 $out->putUnsignedVarInt(count($this->usedBlobHashes));
140 foreach($this->usedBlobHashes as $hash){
141 $out->putLLong($hash);
142 }
143 }
144 $out->putString($this->extraPayload);
145 }
146
147 public function handle(PacketHandlerInterface $handler) : bool{
148 return $handler->handleLevelChunk($this);
149 }
150}
static create(ChunkPosition $chunkPosition, int $dimensionId, int $subChunkCount, bool $clientSubChunkRequestsEnabled, ?array $usedBlobHashes, string $extraPayload)