22declare(strict_types=1);
24namespace pocketmine\data\bedrock\block\convert;
26use pocketmine\block\utils\BellAttachmentType;
27use pocketmine\block\utils\CoralType;
28use pocketmine\block\utils\SlabType;
29use pocketmine\block\utils\WallConnectionType;
41use
function array_keys;
43use
function get_class;
52 private array $unusedStates;
54 public function __construct(
57 $this->unusedStates = $this->data->getStates();
66 "Property \"$name\" has unexpected value \"$stringifiedValue\"" . (
67 $reason !==
null ?
" ($reason)" :
""
73 unset($this->unusedStates[$name]);
74 $tag = $this->data->getState($name);
79 default:
throw $this->badValueException($name, (
string) $tag->
getValue());
82 throw $this->missingOrWrongTypeException($name, $tag);
86 public function readInt(
string $name) : int{
87 unset($this->unusedStates[$name]);
88 $tag = $this->data->getState($name);
89 if($tag instanceof
IntTag){
92 throw $this->missingOrWrongTypeException($name, $tag);
97 $result = $this->readInt($name);
98 if($result < $min || $result > $max){
99 throw $this->badValueException($name, (
string) $result,
"Must be inside the range $min ... $max");
106 unset($this->unusedStates[$name]);
108 $tag = $this->data->getState($name);
112 throw $this->missingOrWrongTypeException($name, $tag);
121 private function parseFacingValue(
int $value, array $mapping) : int{
122 $result = $mapping[$value] ?? null;
123 if($result ===
null){
131 return $this->parseFacingValue($this->readInt(
BlockStateNames::FACING_DIRECTION), [
143 return match($raw = $this->readString(
BlockStateNames::MC_BLOCK_FACE)){
144 StringValues::MC_BLOCK_FACE_DOWN => Facing::DOWN,
145 StringValues::MC_BLOCK_FACE_UP => Facing::UP,
146 StringValues::MC_BLOCK_FACE_NORTH => Facing::NORTH,
147 StringValues::MC_BLOCK_FACE_SOUTH => Facing::SOUTH,
148 StringValues::MC_BLOCK_FACE_WEST => Facing::WEST,
149 StringValues::MC_BLOCK_FACE_EAST => Facing::EAST,
150 default =>
throw $this->badValueException(BlockStateNames::MC_BLOCK_FACE, $raw)
160 $flags = $this->readBoundedInt(BlockStateNames::MULTI_FACE_DIRECTION_BITS, 0, 63);
162 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_DOWN => Facing::DOWN,
163 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_UP => Facing::UP,
164 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_NORTH => Facing::NORTH,
165 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_SOUTH => Facing::SOUTH,
166 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_WEST => Facing::WEST,
167 BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_EAST => Facing::EAST
168 ] as $flag => $facing){
169 if(($flags & $flag) !== 0){
170 $result[$facing] = $facing;
179 $result = $this->readFacingDirection();
180 return Facing::axis($result) !== Axis::Y ? Facing::opposite($result) : $result;
185 return $this->parseFacingValue($this->readInt(
BlockStateNames::FACING_DIRECTION), [
197 return $this->parseFacingValue($this->readInt(
BlockStateNames::WEIRDO_DIRECTION), [
207 return $this->parseFacingValue($this->readInt(
BlockStateNames::DIRECTION), [
220 return $this->parseFacingValue($this->readInt(
BlockStateNames::DIRECTION), [
233 return match($raw = $this->readString(
BlockStateNames::MC_CARDINAL_DIRECTION)){
234 StringValues::MC_CARDINAL_DIRECTION_NORTH => Facing::NORTH,
235 StringValues::MC_CARDINAL_DIRECTION_SOUTH => Facing::SOUTH,
236 StringValues::MC_CARDINAL_DIRECTION_WEST => Facing::WEST,
237 StringValues::MC_CARDINAL_DIRECTION_EAST => Facing::EAST,
238 default =>
throw $this->badValueException(BlockStateNames::MC_CARDINAL_DIRECTION, $raw)
244 return $this->parseFacingValue($this->readInt(
BlockStateNames::CORAL_DIRECTION), [
254 $result = $this->readFacingDirection();
255 if($result === Facing::DOWN){
256 $result = Facing::UP;
261 public function readFacingWithoutUp() : int{
262 $result = $this->readFacingDirection();
263 if($result === Facing::UP){
264 $result = Facing::DOWN;
276 StringValues::PILLAR_AXIS_X => Axis::X,
277 StringValues::PILLAR_AXIS_Y => Axis::Y,
278 StringValues::PILLAR_AXIS_Z => Axis::Z
279 ][$rawValue] ??
null;
281 throw $this->badValueException(BlockStateNames::PILLAR_AXIS, $rawValue,
"Invalid axis value");
288 return match($rawValue = $this->readString(
BlockStateNames::MC_VERTICAL_HALF)){
289 StringValues::MC_VERTICAL_HALF_BOTTOM => SlabType::BOTTOM,
290 StringValues::MC_VERTICAL_HALF_TOP => SlabType::TOP,
291 default =>
throw $this->badValueException(BlockStateNames::MC_VERTICAL_HALF, $rawValue,
"Invalid slab position"),
301 return match($rawValue = $this->readString(
BlockStateNames::TORCH_FACING_DIRECTION)){
302 StringValues::TORCH_FACING_DIRECTION_EAST => Facing::WEST,
303 StringValues::TORCH_FACING_DIRECTION_NORTH => Facing::SOUTH,
304 StringValues::TORCH_FACING_DIRECTION_SOUTH => Facing::NORTH,
305 StringValues::TORCH_FACING_DIRECTION_TOP => Facing::UP,
306 StringValues::TORCH_FACING_DIRECTION_UNKNOWN => Facing::UP,
307 StringValues::TORCH_FACING_DIRECTION_WEST => Facing::EAST,
308 default =>
throw $this->badValueException(BlockStateNames::TORCH_FACING_DIRECTION, $rawValue,
"Invalid torch facing"),
315 StringValues::CORAL_COLOR_BLUE => CoralType::TUBE,
316 StringValues::CORAL_COLOR_PINK => CoralType::BRAIN,
317 StringValues::CORAL_COLOR_PURPLE => CoralType::BUBBLE,
318 StringValues::CORAL_COLOR_RED => CoralType::FIRE,
319 StringValues::CORAL_COLOR_YELLOW => CoralType::HORN,
320 default =>
throw $this->badValueException(BlockStateNames::CORAL_COLOR, $type),
327 StringValues::ATTACHMENT_HANGING => BellAttachmentType::CEILING,
328 StringValues::ATTACHMENT_STANDING => BellAttachmentType::FLOOR,
329 StringValues::ATTACHMENT_SIDE => BellAttachmentType::ONE_WALL,
330 StringValues::ATTACHMENT_MULTIPLE => BellAttachmentType::TWO_WALLS,
331 default =>
throw $this->badValueException(BlockStateNames::ATTACHMENT, $type),
337 return match($type = $this->readString($name)){
341 StringValues::WALL_CONNECTION_TYPE_EAST_NONE =>
null,
342 StringValues::WALL_CONNECTION_TYPE_EAST_SHORT => WallConnectionType::SHORT,
343 StringValues::WALL_CONNECTION_TYPE_EAST_TALL => WallConnectionType::TALL,
344 default =>
throw $this->badValueException($name, $type),
352 if($this->data->getState($name) !== null){
353 unset($this->unusedStates[$name]);
355 throw $this->missingOrWrongTypeException($name,
null);
362 public function todo(
string $name) : void{
363 $this->ignored($name);
370 if(count($this->unusedStates) > 0){
readWeirdoHorizontalFacing()
readBoundedInt(string $name, int $min, int $max)
readCardinalHorizontalFacing()
read5MinusHorizontalFacing()
readLegacyHorizontalFacing()
readWallConnectionType(string $name)
readEndRodFacingDirection()