PocketMine-MP 5.18.1 git-9381fc4172e5dce4cada1cb356050c8a2ab57b94
BlockStateWriter.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\data\bedrock\block\convert;
25
26use pocketmine\block\utils\BellAttachmentType;
27use pocketmine\block\utils\SlabType;
28use pocketmine\block\utils\WallConnectionType;
41
42final class BlockStateWriter{
43
48 private array $states = [];
49
50 public function __construct(
51 private string $id
52 ){}
53
54 public static function create(string $id) : self{
55 return new self($id);
56 }
57
59 public function writeBool(string $name, bool $value) : self{
60 $this->states[$name] = new ByteTag($value ? 1 : 0);
61 return $this;
62 }
63
65 public function writeInt(string $name, int $value) : self{
66 $this->states[$name] = new IntTag($value);
67 return $this;
68 }
69
71 public function writeString(string $name, string $value) : self{
72 $this->states[$name] = new StringTag($value);
73 return $this;
74 }
75
77 public function writeFacingDirection(int $value) : self{
78 $this->writeInt(BlockStateNames::FACING_DIRECTION, match($value){
79 Facing::DOWN => 0,
80 Facing::UP => 1,
81 Facing::NORTH => 2,
82 Facing::SOUTH => 3,
83 Facing::WEST => 4,
84 Facing::EAST => 5,
85 default => throw new BlockStateSerializeException("Invalid Facing $value")
86 });
87 return $this;
88 }
89
91 public function writeBlockFace(int $value) : self{
92 $this->writeString(BlockStateNames::MC_BLOCK_FACE, match($value){
93 Facing::DOWN => StringValues::MC_BLOCK_FACE_DOWN,
94 Facing::UP => StringValues::MC_BLOCK_FACE_UP,
95 Facing::NORTH => StringValues::MC_BLOCK_FACE_NORTH,
96 Facing::SOUTH => StringValues::MC_BLOCK_FACE_SOUTH,
97 Facing::WEST => StringValues::MC_BLOCK_FACE_WEST,
98 Facing::EAST => StringValues::MC_BLOCK_FACE_EAST,
99 default => throw new BlockStateSerializeException("Invalid Facing $value")
100 });
101 return $this;
102 }
103
109 public function writeFacingFlags(array $faces) : self{
110 $result = 0;
111 foreach($faces as $face){
112 $result |= match($face){
113 Facing::DOWN => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_DOWN,
114 Facing::UP => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_UP,
115 Facing::NORTH => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_NORTH,
116 Facing::SOUTH => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_SOUTH,
117 Facing::WEST => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_WEST,
118 Facing::EAST => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_EAST,
119 default => throw new AssumptionFailedError("Unhandled face $face")
120 };
121 }
122
123 return $this->writeInt(BlockStateNames::MULTI_FACE_DIRECTION_BITS, $result);
124 }
125
127 public function writeEndRodFacingDirection(int $value) : self{
128 //end rods are stupid in bedrock and have everything except up/down the wrong way round
129 return $this->writeFacingDirection(Facing::axis($value) !== Axis::Y ? Facing::opposite($value) : $value);
130 }
131
133 public function writeHorizontalFacing(int $value) : self{
134 if($value === Facing::UP || $value === Facing::DOWN){
135 throw new BlockStateSerializeException("Y-axis facing is not allowed");
136 }
137
138 return $this->writeFacingDirection($value);
139 }
140
142 public function writeWeirdoHorizontalFacing(int $value) : self{
143 $this->writeInt(BlockStateNames::WEIRDO_DIRECTION, match($value){
144 Facing::EAST => 0,
145 Facing::WEST => 1,
146 Facing::SOUTH => 2,
147 Facing::NORTH => 3,
148 default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
149 });
150 return $this;
151 }
152
154 public function writeLegacyHorizontalFacing(int $value) : self{
155 $this->writeInt(BlockStateNames::DIRECTION, match($value){
156 Facing::SOUTH => 0,
157 Facing::WEST => 1,
158 Facing::NORTH => 2,
159 Facing::EAST => 3,
160 default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
161 });
162 return $this;
163 }
164
169 public function write5MinusHorizontalFacing(int $value) : self{
170 return $this->writeInt(BlockStateNames::DIRECTION, match($value){
171 Facing::EAST => 0,
172 Facing::WEST => 1,
173 Facing::SOUTH => 2,
174 Facing::NORTH => 3,
175 default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
176 });
177 }
178
183 public function writeCardinalHorizontalFacing(int $value) : self{
184 return $this->writeString(BlockStateNames::MC_CARDINAL_DIRECTION, match($value){
185 Facing::SOUTH => StringValues::MC_CARDINAL_DIRECTION_SOUTH,
186 Facing::WEST => StringValues::MC_CARDINAL_DIRECTION_WEST,
187 Facing::NORTH => StringValues::MC_CARDINAL_DIRECTION_NORTH,
188 Facing::EAST => StringValues::MC_CARDINAL_DIRECTION_EAST,
189 default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
190 });
191 }
192
194 public function writeCoralFacing(int $value) : self{
195 $this->writeInt(BlockStateNames::CORAL_DIRECTION, match($value){
196 Facing::WEST => 0,
197 Facing::EAST => 1,
198 Facing::NORTH => 2,
199 Facing::SOUTH => 3,
200 default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
201 });
202 return $this;
203 }
204
206 public function writeFacingWithoutDown(int $value) : self{
207 if($value === Facing::DOWN){
208 throw new BlockStateSerializeException("Invalid facing DOWN");
209 }
210 $this->writeFacingDirection($value);
211 return $this;
212 }
213
215 public function writeFacingWithoutUp(int $value) : self{
216 if($value === Facing::UP){
217 throw new BlockStateSerializeException("Invalid facing UP");
218 }
219 $this->writeFacingDirection($value);
220 return $this;
221 }
222
224 public function writePillarAxis(int $axis) : self{
225 $this->writeString(BlockStateNames::PILLAR_AXIS, match($axis){
226 Axis::X => StringValues::PILLAR_AXIS_X,
227 Axis::Y => StringValues::PILLAR_AXIS_Y,
228 Axis::Z => StringValues::PILLAR_AXIS_Z,
229 default => throw new BlockStateSerializeException("Invalid axis $axis")
230 });
231 return $this;
232 }
233
235 public function writeSlabPosition(SlabType $slabType) : self{
236 $this->writeString(BlockStateNames::MC_VERTICAL_HALF, match($slabType){
237 SlabType::TOP => StringValues::MC_VERTICAL_HALF_TOP,
238 SlabType::BOTTOM => StringValues::MC_VERTICAL_HALF_BOTTOM,
239 default => throw new BlockStateSerializeException("Invalid slab type " . $slabType->name)
240 });
241 return $this;
242 }
243
245 public function writeTorchFacing(int $facing) : self{
246 //TODO: horizontal directions are flipped (MCPE bug: https://bugs.mojang.com/browse/MCPE-152036)
247 $this->writeString(BlockStateNames::TORCH_FACING_DIRECTION, match($facing){
248 Facing::UP => StringValues::TORCH_FACING_DIRECTION_TOP,
249 Facing::SOUTH => StringValues::TORCH_FACING_DIRECTION_NORTH,
250 Facing::NORTH => StringValues::TORCH_FACING_DIRECTION_SOUTH,
251 Facing::EAST => StringValues::TORCH_FACING_DIRECTION_WEST,
252 Facing::WEST => StringValues::TORCH_FACING_DIRECTION_EAST,
253 default => throw new BlockStateSerializeException("Invalid Torch facing $facing")
254 });
255 return $this;
256 }
257
259 public function writeBellAttachmentType(BellAttachmentType $attachmentType) : self{
260 $this->writeString(BlockStateNames::ATTACHMENT, match($attachmentType){
261 BellAttachmentType::FLOOR => StringValues::ATTACHMENT_STANDING,
262 BellAttachmentType::CEILING => StringValues::ATTACHMENT_HANGING,
263 BellAttachmentType::ONE_WALL => StringValues::ATTACHMENT_SIDE,
264 BellAttachmentType::TWO_WALLS => StringValues::ATTACHMENT_MULTIPLE,
265 });
266 return $this;
267 }
268
270 public function writeWallConnectionType(string $name, ?WallConnectionType $wallConnectionType) : self{
271 $this->writeString($name, match($wallConnectionType){
272 null => StringValues::WALL_CONNECTION_TYPE_EAST_NONE,
273 WallConnectionType::SHORT => StringValues::WALL_CONNECTION_TYPE_EAST_SHORT,
274 WallConnectionType::TALL => StringValues::WALL_CONNECTION_TYPE_EAST_TALL,
275 });
276 return $this;
277 }
278
279 public function getBlockStateData() : BlockStateData{
280 return BlockStateData::current($this->id, $this->states);
281 }
282}
writeBellAttachmentType(BellAttachmentType $attachmentType)
writeWallConnectionType(string $name, ?WallConnectionType $wallConnectionType)