22declare(strict_types=1);
24namespace pocketmine\data\bedrock\block\convert;
26use pocketmine\block\utils\BellAttachmentType;
27use pocketmine\block\utils\SlabType;
28use pocketmine\block\utils\WallConnectionType;
40use
function array_keys;
42use
function get_class;
51 private array $unusedStates;
53 public function __construct(
56 $this->unusedStates = $this->data->getStates();
65 "Property \"$name\" has unexpected value \"$stringifiedValue\"" . (
66 $reason !==
null ?
" ($reason)" :
""
72 unset($this->unusedStates[$name]);
73 $tag = $this->data->getState($name);
78 default:
throw $this->badValueException($name, (
string) $tag->
getValue());
81 throw $this->missingOrWrongTypeException($name, $tag);
85 public function readInt(
string $name) : int{
86 unset($this->unusedStates[$name]);
87 $tag = $this->data->getState($name);
88 if($tag instanceof
IntTag){
91 throw $this->missingOrWrongTypeException($name, $tag);
96 $result = $this->readInt($name);
97 if($result < $min || $result > $max){
98 throw $this->badValueException($name, (
string) $result,
"Must be inside the range $min ... $max");
105 unset($this->unusedStates[$name]);
107 $tag = $this->data->getState($name);
111 throw $this->missingOrWrongTypeException($name, $tag);
120 private function parseFacingValue(
int $value, array $mapping) : int{
121 $result = $mapping[$value] ?? null;
122 if($result ===
null){
130 return $this->parseFacingValue($this->readInt(
BlockStateNames::FACING_DIRECTION), [
142 return match($raw = $this->readString(
BlockStateNames::MC_BLOCK_FACE)){
143 StringValues::MC_BLOCK_FACE_DOWN => Facing::DOWN,
144 StringValues::MC_BLOCK_FACE_UP => Facing::UP,
145 StringValues::MC_BLOCK_FACE_NORTH => Facing::NORTH,
146 StringValues::MC_BLOCK_FACE_SOUTH => Facing::SOUTH,
147 StringValues::MC_BLOCK_FACE_WEST => Facing::WEST,
148 StringValues::MC_BLOCK_FACE_EAST => Facing::EAST,
149 default =>
throw $this->badValueException(BlockStateNames::MC_BLOCK_FACE, $raw)
159 $flags = $this->readBoundedInt(BlockStateNames::MULTI_FACE_DIRECTION_BITS, 0, 63);
161 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_DOWN => Facing::DOWN,
162 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_UP => Facing::UP,
163 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_NORTH => Facing::NORTH,
164 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_SOUTH => Facing::SOUTH,
165 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_WEST => Facing::WEST,
166 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_EAST => Facing::EAST
167 ] as $flag => $facing){
168 if(($flags & $flag) !== 0){
169 $result[$facing] = $facing;
178 $result = $this->readFacingDirection();
179 return Facing::axis($result) !== Axis::Y ? Facing::opposite($result) : $result;
184 return $this->parseFacingValue($this->readInt(
BlockStateNames::FACING_DIRECTION), [
196 return $this->parseFacingValue($this->readInt(
BlockStateNames::WEIRDO_DIRECTION), [
206 return $this->parseFacingValue($this->readInt(
BlockStateNames::DIRECTION), [
219 return $this->parseFacingValue($this->readInt(
BlockStateNames::DIRECTION), [
232 return match($raw = $this->readString(
BlockStateNames::MC_CARDINAL_DIRECTION)){
233 StringValues::MC_CARDINAL_DIRECTION_NORTH => Facing::NORTH,
234 StringValues::MC_CARDINAL_DIRECTION_SOUTH => Facing::SOUTH,
235 StringValues::MC_CARDINAL_DIRECTION_WEST => Facing::WEST,
236 StringValues::MC_CARDINAL_DIRECTION_EAST => Facing::EAST,
237 default =>
throw $this->badValueException(BlockStateNames::MC_CARDINAL_DIRECTION, $raw)
243 return $this->parseFacingValue($this->readInt(
BlockStateNames::CORAL_DIRECTION), [
253 $result = $this->readFacingDirection();
254 if($result === Facing::DOWN){
255 $result = Facing::UP;
260 public function readFacingWithoutUp() : int{
261 $result = $this->readFacingDirection();
262 if($result === Facing::UP){
263 $result = Facing::DOWN;
275 StringValues::PILLAR_AXIS_X => Axis::X,
276 StringValues::PILLAR_AXIS_Y => Axis::Y,
277 StringValues::PILLAR_AXIS_Z => Axis::Z
278 ][$rawValue] ??
null;
280 throw $this->badValueException(BlockStateNames::PILLAR_AXIS, $rawValue,
"Invalid axis value");
287 return match($rawValue = $this->readString(
BlockStateNames::MC_VERTICAL_HALF)){
288 StringValues::MC_VERTICAL_HALF_BOTTOM => SlabType::BOTTOM,
289 StringValues::MC_VERTICAL_HALF_TOP => SlabType::TOP,
290 default =>
throw $this->badValueException(BlockStateNames::MC_VERTICAL_HALF, $rawValue,
"Invalid slab position"),
300 return match($rawValue = $this->readString(
BlockStateNames::TORCH_FACING_DIRECTION)){
301 StringValues::TORCH_FACING_DIRECTION_EAST => Facing::WEST,
302 StringValues::TORCH_FACING_DIRECTION_NORTH => Facing::SOUTH,
303 StringValues::TORCH_FACING_DIRECTION_SOUTH => Facing::NORTH,
304 StringValues::TORCH_FACING_DIRECTION_TOP => Facing::UP,
305 StringValues::TORCH_FACING_DIRECTION_UNKNOWN => Facing::UP,
306 StringValues::TORCH_FACING_DIRECTION_WEST => Facing::EAST,
307 default =>
throw $this->badValueException(BlockStateNames::TORCH_FACING_DIRECTION, $rawValue,
"Invalid torch facing"),
314 StringValues::ATTACHMENT_HANGING => BellAttachmentType::CEILING,
315 StringValues::ATTACHMENT_STANDING => BellAttachmentType::FLOOR,
316 StringValues::ATTACHMENT_SIDE => BellAttachmentType::ONE_WALL,
317 StringValues::ATTACHMENT_MULTIPLE => BellAttachmentType::TWO_WALLS,
318 default =>
throw $this->badValueException(BlockStateNames::ATTACHMENT, $type),
324 return match($type = $this->readString($name)){
328 StringValues::WALL_CONNECTION_TYPE_EAST_NONE =>
null,
329 StringValues::WALL_CONNECTION_TYPE_EAST_SHORT => WallConnectionType::SHORT,
330 StringValues::WALL_CONNECTION_TYPE_EAST_TALL => WallConnectionType::TALL,
331 default =>
throw $this->badValueException($name, $type),
339 if($this->data->getState($name) !== null){
340 unset($this->unusedStates[$name]);
342 throw $this->missingOrWrongTypeException($name,
null);
349 public function todo(
string $name) : void{
350 $this->ignored($name);
357 if(count($this->unusedStates) > 0){
readWeirdoHorizontalFacing()
readBoundedInt(string $name, int $min, int $max)
readCardinalHorizontalFacing()
read5MinusHorizontalFacing()
readLegacyHorizontalFacing()
readWallConnectionType(string $name)
readEndRodFacingDirection()