PocketMine-MP 5.17.1 git-df4ada81e5d74a14046f27cf44a37dcee69d657e
BlockObjectToStateSerializer.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
147use pocketmine\block\utils\BrewingStandSlot;
148use pocketmine\block\utils\CoralType;
149use pocketmine\block\utils\DirtType;
150use pocketmine\block\utils\DripleafState;
151use pocketmine\block\utils\DyeColor;
152use pocketmine\block\utils\FroglightType;
153use pocketmine\block\utils\LeverFacing;
182use function get_class;
183
192 private array $serializers = [];
193
198 private array $cache = [];
199
200 public function __construct(){
201 $this->registerCandleSerializers();
202 $this->registerFlatColorBlockSerializers();
203 $this->registerFlatCoralSerializers();
204 $this->registerCauldronSerializers();
205 $this->registerFlatWoodBlockSerializers();
206 $this->registerLeavesSerializers();
207 $this->registerSaplingSerializers();
208 $this->registerSimpleSerializers();
209 $this->registerSerializers();
210 }
211
212 public function serialize(int $stateId) : BlockStateData{
213 //TODO: singleton usage not ideal
214 //TODO: we may want to deduplicate cache entries to avoid wasting memory
215 return $this->cache[$stateId] ??= $this->serializeBlock(RuntimeBlockStateRegistry::getInstance()->fromStateId($stateId));
216 }
217
223 public function map(Block $block, \Closure $serializer) : void{
224 if(isset($this->serializers[$block->getTypeId()])){
225 throw new \InvalidArgumentException("Block type ID " . $block->getTypeId() . " already has a serializer registered");
226 }
227 $this->serializers[$block->getTypeId()] = $serializer;
228 }
229
230 public function mapSimple(Block $block, string $id) : void{
231 $this->map($block, fn() => Writer::create($id));
232 }
233
234 public function mapSlab(Slab $block, string $singleId, string $doubleId) : void{
235 $this->map($block, fn(Slab $block) => Helper::encodeSlab($block, $singleId, $doubleId));
236 }
237
238 public function mapStairs(Stair $block, string $id) : void{
239 $this->map($block, fn(Stair $block) => Helper::encodeStairs($block, Writer::create($id)));
240 }
241
242 public function mapLog(Wood $block, string $unstrippedId, string $strippedId) : void{
243 $this->map($block, fn(Wood $block) => Helper::encodeLog($block, $unstrippedId, $strippedId));
244 }
245
252 public function serializeBlock(Block $blockState) : BlockStateData{
253 $typeId = $blockState->getTypeId();
254
255 $locatedSerializer = $this->serializers[$typeId] ?? null;
256 if($locatedSerializer === null){
257 throw new BlockStateSerializeException("No serializer registered for " . get_class($blockState) . " with type ID $typeId");
258 }
259
268 $serializer = $locatedSerializer;
269
271 $writer = $serializer($blockState);
272 return $writer->getBlockStateData();
273 }
274
275 private function registerCandleSerializers() : void{
276 $this->map(Blocks::CANDLE(), fn(Candle $block) => Helper::encodeCandle($block, new Writer(Ids::CANDLE)));
277 $this->map(Blocks::DYED_CANDLE(), fn(DyedCandle $block) => Helper::encodeCandle($block, new Writer(match($block->getColor()){
278 DyeColor::BLACK => Ids::BLACK_CANDLE,
279 DyeColor::BLUE => Ids::BLUE_CANDLE,
280 DyeColor::BROWN => Ids::BROWN_CANDLE,
281 DyeColor::CYAN => Ids::CYAN_CANDLE,
282 DyeColor::GRAY => Ids::GRAY_CANDLE,
283 DyeColor::GREEN => Ids::GREEN_CANDLE,
284 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CANDLE,
285 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CANDLE,
286 DyeColor::LIME => Ids::LIME_CANDLE,
287 DyeColor::MAGENTA => Ids::MAGENTA_CANDLE,
288 DyeColor::ORANGE => Ids::ORANGE_CANDLE,
289 DyeColor::PINK => Ids::PINK_CANDLE,
290 DyeColor::PURPLE => Ids::PURPLE_CANDLE,
291 DyeColor::RED => Ids::RED_CANDLE,
292 DyeColor::WHITE => Ids::WHITE_CANDLE,
293 DyeColor::YELLOW => Ids::YELLOW_CANDLE,
294 })));
295 $this->map(Blocks::CAKE_WITH_CANDLE(), fn(CakeWithCandle $block) => Writer::create(Ids::CANDLE_CAKE)
296 ->writeBool(StateNames::LIT, $block->isLit()));
297 $this->map(Blocks::CAKE_WITH_DYED_CANDLE(), fn(CakeWithDyedCandle $block) => Writer::create(match($block->getColor()){
298 DyeColor::BLACK => Ids::BLACK_CANDLE_CAKE,
299 DyeColor::BLUE => Ids::BLUE_CANDLE_CAKE,
300 DyeColor::BROWN => Ids::BROWN_CANDLE_CAKE,
301 DyeColor::CYAN => Ids::CYAN_CANDLE_CAKE,
302 DyeColor::GRAY => Ids::GRAY_CANDLE_CAKE,
303 DyeColor::GREEN => Ids::GREEN_CANDLE_CAKE,
304 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CANDLE_CAKE,
305 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CANDLE_CAKE,
306 DyeColor::LIME => Ids::LIME_CANDLE_CAKE,
307 DyeColor::MAGENTA => Ids::MAGENTA_CANDLE_CAKE,
308 DyeColor::ORANGE => Ids::ORANGE_CANDLE_CAKE,
309 DyeColor::PINK => Ids::PINK_CANDLE_CAKE,
310 DyeColor::PURPLE => Ids::PURPLE_CANDLE_CAKE,
311 DyeColor::RED => Ids::RED_CANDLE_CAKE,
312 DyeColor::WHITE => Ids::WHITE_CANDLE_CAKE,
313 DyeColor::YELLOW => Ids::YELLOW_CANDLE_CAKE,
314 })->writeBool(StateNames::LIT, $block->isLit()));
315 }
316
317 public function registerFlatColorBlockSerializers() : void{
318 $this->map(Blocks::STAINED_HARDENED_GLASS(), fn(StainedHardenedGlass $block) => Writer::create(match($block->getColor()){
319 DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS,
320 DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS,
321 DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS,
322 DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS,
323 DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS,
324 DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS,
325 DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS,
326 DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS,
327 DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS,
328 DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS,
329 DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS,
330 DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS,
331 DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS,
332 DyeColor::RED => Ids::HARD_RED_STAINED_GLASS,
333 DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS,
334 DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS,
335 }));
336
337 $this->map(Blocks::STAINED_HARDENED_GLASS_PANE(), fn(StainedHardenedGlassPane $block) => Writer::create(match($block->getColor()){
338 DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS_PANE,
339 DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS_PANE,
340 DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS_PANE,
341 DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS_PANE,
342 DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS_PANE,
343 DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS_PANE,
344 DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS_PANE,
345 DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS_PANE,
346 DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS_PANE,
347 DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS_PANE,
348 DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS_PANE,
349 DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS_PANE,
350 DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS_PANE,
351 DyeColor::RED => Ids::HARD_RED_STAINED_GLASS_PANE,
352 DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS_PANE,
353 DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS_PANE,
354 }));
355
356 $this->map(Blocks::GLAZED_TERRACOTTA(), function(GlazedTerracotta $block) : Writer{
357 return Writer::create(match($block->getColor()){
358 DyeColor::BLACK => Ids::BLACK_GLAZED_TERRACOTTA,
359 DyeColor::BLUE => Ids::BLUE_GLAZED_TERRACOTTA,
360 DyeColor::BROWN => Ids::BROWN_GLAZED_TERRACOTTA,
361 DyeColor::CYAN => Ids::CYAN_GLAZED_TERRACOTTA,
362 DyeColor::GRAY => Ids::GRAY_GLAZED_TERRACOTTA,
363 DyeColor::GREEN => Ids::GREEN_GLAZED_TERRACOTTA,
364 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_GLAZED_TERRACOTTA,
365 DyeColor::LIGHT_GRAY => Ids::SILVER_GLAZED_TERRACOTTA,
366 DyeColor::LIME => Ids::LIME_GLAZED_TERRACOTTA,
367 DyeColor::MAGENTA => Ids::MAGENTA_GLAZED_TERRACOTTA,
368 DyeColor::ORANGE => Ids::ORANGE_GLAZED_TERRACOTTA,
369 DyeColor::PINK => Ids::PINK_GLAZED_TERRACOTTA,
370 DyeColor::PURPLE => Ids::PURPLE_GLAZED_TERRACOTTA,
371 DyeColor::RED => Ids::RED_GLAZED_TERRACOTTA,
372 DyeColor::WHITE => Ids::WHITE_GLAZED_TERRACOTTA,
373 DyeColor::YELLOW => Ids::YELLOW_GLAZED_TERRACOTTA,
374 })
375 ->writeHorizontalFacing($block->getFacing());
376 });
377
378 $this->map(Blocks::WOOL(), fn(Wool $block) => Writer::create(match($block->getColor()){
379 DyeColor::BLACK => Ids::BLACK_WOOL,
380 DyeColor::BLUE => Ids::BLUE_WOOL,
381 DyeColor::BROWN => Ids::BROWN_WOOL,
382 DyeColor::CYAN => Ids::CYAN_WOOL,
383 DyeColor::GRAY => Ids::GRAY_WOOL,
384 DyeColor::GREEN => Ids::GREEN_WOOL,
385 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_WOOL,
386 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_WOOL,
387 DyeColor::LIME => Ids::LIME_WOOL,
388 DyeColor::MAGENTA => Ids::MAGENTA_WOOL,
389 DyeColor::ORANGE => Ids::ORANGE_WOOL,
390 DyeColor::PINK => Ids::PINK_WOOL,
391 DyeColor::PURPLE => Ids::PURPLE_WOOL,
392 DyeColor::RED => Ids::RED_WOOL,
393 DyeColor::WHITE => Ids::WHITE_WOOL,
394 DyeColor::YELLOW => Ids::YELLOW_WOOL,
395 }));
396
397 $this->map(Blocks::CARPET(), fn(Carpet $block) => Writer::create(match($block->getColor()){
398 DyeColor::BLACK => Ids::BLACK_CARPET,
399 DyeColor::BLUE => Ids::BLUE_CARPET,
400 DyeColor::BROWN => Ids::BROWN_CARPET,
401 DyeColor::CYAN => Ids::CYAN_CARPET,
402 DyeColor::GRAY => Ids::GRAY_CARPET,
403 DyeColor::GREEN => Ids::GREEN_CARPET,
404 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CARPET,
405 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CARPET,
406 DyeColor::LIME => Ids::LIME_CARPET,
407 DyeColor::MAGENTA => Ids::MAGENTA_CARPET,
408 DyeColor::ORANGE => Ids::ORANGE_CARPET,
409 DyeColor::PINK => Ids::PINK_CARPET,
410 DyeColor::PURPLE => Ids::PURPLE_CARPET,
411 DyeColor::RED => Ids::RED_CARPET,
412 DyeColor::WHITE => Ids::WHITE_CARPET,
413 DyeColor::YELLOW => Ids::YELLOW_CARPET,
414 }));
415
416 $this->map(Blocks::DYED_SHULKER_BOX(), fn(DyedShulkerBox $block) => Writer::create(match($block->getColor()){
417 DyeColor::BLACK => Ids::BLACK_SHULKER_BOX,
418 DyeColor::BLUE => Ids::BLUE_SHULKER_BOX,
419 DyeColor::BROWN => Ids::BROWN_SHULKER_BOX,
420 DyeColor::CYAN => Ids::CYAN_SHULKER_BOX,
421 DyeColor::GRAY => Ids::GRAY_SHULKER_BOX,
422 DyeColor::GREEN => Ids::GREEN_SHULKER_BOX,
423 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_SHULKER_BOX,
424 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_SHULKER_BOX,
425 DyeColor::LIME => Ids::LIME_SHULKER_BOX,
426 DyeColor::MAGENTA => Ids::MAGENTA_SHULKER_BOX,
427 DyeColor::ORANGE => Ids::ORANGE_SHULKER_BOX,
428 DyeColor::PINK => Ids::PINK_SHULKER_BOX,
429 DyeColor::PURPLE => Ids::PURPLE_SHULKER_BOX,
430 DyeColor::RED => Ids::RED_SHULKER_BOX,
431 DyeColor::WHITE => Ids::WHITE_SHULKER_BOX,
432 DyeColor::YELLOW => Ids::YELLOW_SHULKER_BOX,
433 }));
434
435 $this->map(Blocks::CONCRETE(), fn(Concrete $block) => Writer::create(match($block->getColor()){
436 DyeColor::BLACK => Ids::BLACK_CONCRETE,
437 DyeColor::BLUE => Ids::BLUE_CONCRETE,
438 DyeColor::BROWN => Ids::BROWN_CONCRETE,
439 DyeColor::CYAN => Ids::CYAN_CONCRETE,
440 DyeColor::GRAY => Ids::GRAY_CONCRETE,
441 DyeColor::GREEN => Ids::GREEN_CONCRETE,
442 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CONCRETE,
443 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CONCRETE,
444 DyeColor::LIME => Ids::LIME_CONCRETE,
445 DyeColor::MAGENTA => Ids::MAGENTA_CONCRETE,
446 DyeColor::ORANGE => Ids::ORANGE_CONCRETE,
447 DyeColor::PINK => Ids::PINK_CONCRETE,
448 DyeColor::PURPLE => Ids::PURPLE_CONCRETE,
449 DyeColor::RED => Ids::RED_CONCRETE,
450 DyeColor::WHITE => Ids::WHITE_CONCRETE,
451 DyeColor::YELLOW => Ids::YELLOW_CONCRETE,
452 }));
453
454 $this->map(Blocks::CONCRETE_POWDER(), fn(ConcretePowder $block) => Writer::create(match($block->getColor()){
455 DyeColor::BLACK => Ids::BLACK_CONCRETE_POWDER,
456 DyeColor::BLUE => Ids::BLUE_CONCRETE_POWDER,
457 DyeColor::BROWN => Ids::BROWN_CONCRETE_POWDER,
458 DyeColor::CYAN => Ids::CYAN_CONCRETE_POWDER,
459 DyeColor::GRAY => Ids::GRAY_CONCRETE_POWDER,
460 DyeColor::GREEN => Ids::GREEN_CONCRETE_POWDER,
461 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CONCRETE_POWDER,
462 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CONCRETE_POWDER,
463 DyeColor::LIME => Ids::LIME_CONCRETE_POWDER,
464 DyeColor::MAGENTA => Ids::MAGENTA_CONCRETE_POWDER,
465 DyeColor::ORANGE => Ids::ORANGE_CONCRETE_POWDER,
466 DyeColor::PINK => Ids::PINK_CONCRETE_POWDER,
467 DyeColor::PURPLE => Ids::PURPLE_CONCRETE_POWDER,
468 DyeColor::RED => Ids::RED_CONCRETE_POWDER,
469 DyeColor::WHITE => Ids::WHITE_CONCRETE_POWDER,
470 DyeColor::YELLOW => Ids::YELLOW_CONCRETE_POWDER,
471 }));
472
473 $this->map(Blocks::STAINED_CLAY(), fn(StainedHardenedClay $block) => Writer::create(match($block->getColor()){
474 DyeColor::BLACK => Ids::BLACK_TERRACOTTA,
475 DyeColor::BLUE => Ids::BLUE_TERRACOTTA,
476 DyeColor::BROWN => Ids::BROWN_TERRACOTTA,
477 DyeColor::CYAN => Ids::CYAN_TERRACOTTA,
478 DyeColor::GRAY => Ids::GRAY_TERRACOTTA,
479 DyeColor::GREEN => Ids::GREEN_TERRACOTTA,
480 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_TERRACOTTA,
481 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_TERRACOTTA,
482 DyeColor::LIME => Ids::LIME_TERRACOTTA,
483 DyeColor::MAGENTA => Ids::MAGENTA_TERRACOTTA,
484 DyeColor::ORANGE => Ids::ORANGE_TERRACOTTA,
485 DyeColor::PINK => Ids::PINK_TERRACOTTA,
486 DyeColor::PURPLE => Ids::PURPLE_TERRACOTTA,
487 DyeColor::RED => Ids::RED_TERRACOTTA,
488 DyeColor::WHITE => Ids::WHITE_TERRACOTTA,
489 DyeColor::YELLOW => Ids::YELLOW_TERRACOTTA,
490 }));
491
492 $this->map(Blocks::STAINED_GLASS(), fn(StainedGlass $block) => Writer::create(match($block->getColor()){
493 DyeColor::BLACK => Ids::BLACK_STAINED_GLASS,
494 DyeColor::BLUE => Ids::BLUE_STAINED_GLASS,
495 DyeColor::BROWN => Ids::BROWN_STAINED_GLASS,
496 DyeColor::CYAN => Ids::CYAN_STAINED_GLASS,
497 DyeColor::GRAY => Ids::GRAY_STAINED_GLASS,
498 DyeColor::GREEN => Ids::GREEN_STAINED_GLASS,
499 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_STAINED_GLASS,
500 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_STAINED_GLASS,
501 DyeColor::LIME => Ids::LIME_STAINED_GLASS,
502 DyeColor::MAGENTA => Ids::MAGENTA_STAINED_GLASS,
503 DyeColor::ORANGE => Ids::ORANGE_STAINED_GLASS,
504 DyeColor::PINK => Ids::PINK_STAINED_GLASS,
505 DyeColor::PURPLE => Ids::PURPLE_STAINED_GLASS,
506 DyeColor::RED => Ids::RED_STAINED_GLASS,
507 DyeColor::WHITE => Ids::WHITE_STAINED_GLASS,
508 DyeColor::YELLOW => Ids::YELLOW_STAINED_GLASS,
509 }));
510
511 $this->map(Blocks::STAINED_GLASS_PANE(), fn(StainedGlassPane $block) => Writer::create(match($block->getColor()){
512 DyeColor::BLACK => Ids::BLACK_STAINED_GLASS_PANE,
513 DyeColor::BLUE => Ids::BLUE_STAINED_GLASS_PANE,
514 DyeColor::BROWN => Ids::BROWN_STAINED_GLASS_PANE,
515 DyeColor::CYAN => Ids::CYAN_STAINED_GLASS_PANE,
516 DyeColor::GRAY => Ids::GRAY_STAINED_GLASS_PANE,
517 DyeColor::GREEN => Ids::GREEN_STAINED_GLASS_PANE,
518 DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_STAINED_GLASS_PANE,
519 DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_STAINED_GLASS_PANE,
520 DyeColor::LIME => Ids::LIME_STAINED_GLASS_PANE,
521 DyeColor::MAGENTA => Ids::MAGENTA_STAINED_GLASS_PANE,
522 DyeColor::ORANGE => Ids::ORANGE_STAINED_GLASS_PANE,
523 DyeColor::PINK => Ids::PINK_STAINED_GLASS_PANE,
524 DyeColor::PURPLE => Ids::PURPLE_STAINED_GLASS_PANE,
525 DyeColor::RED => Ids::RED_STAINED_GLASS_PANE,
526 DyeColor::WHITE => Ids::WHITE_STAINED_GLASS_PANE,
527 DyeColor::YELLOW => Ids::YELLOW_STAINED_GLASS_PANE,
528 }));
529 }
530
531 private function registerFlatCoralSerializers() : void{
532 $this->map(Blocks::CORAL(), fn(Coral $block) => Writer::create(
533 match($block->getCoralType()){
534 CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL : Ids::BRAIN_CORAL,
535 CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL : Ids::BUBBLE_CORAL,
536 CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL : Ids::FIRE_CORAL,
537 CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL : Ids::HORN_CORAL,
538 CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL : Ids::TUBE_CORAL,
539 }
540 ));
541
542 $this->map(Blocks::CORAL_FAN(), fn(FloorCoralFan $block) => Writer::create(
543 match($block->getCoralType()){
544 CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_FAN : Ids::BRAIN_CORAL_FAN,
545 CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_FAN : Ids::BUBBLE_CORAL_FAN,
546 CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_FAN : Ids::FIRE_CORAL_FAN,
547 CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_FAN : Ids::HORN_CORAL_FAN,
548 CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_FAN : Ids::TUBE_CORAL_FAN,
549 })
550 ->writeInt(StateNames::CORAL_FAN_DIRECTION, match($axis = $block->getAxis()){
551 Axis::X => 0,
552 Axis::Z => 1,
553 default => throw new BlockStateSerializeException("Invalid axis {$axis}"),
554 }));
555
556 $this->map(Blocks::CORAL_BLOCK(), fn(CoralBlock $block) => Writer::create(
557 match($block->getCoralType()){
558 CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_BLOCK : Ids::BRAIN_CORAL_BLOCK,
559 CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_BLOCK : Ids::BUBBLE_CORAL_BLOCK,
560 CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_BLOCK : Ids::FIRE_CORAL_BLOCK,
561 CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_BLOCK : Ids::HORN_CORAL_BLOCK,
562 CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_BLOCK : Ids::TUBE_CORAL_BLOCK,
563 }
564 ));
565 }
566
567 private function registerCauldronSerializers() : void{
568 $this->map(Blocks::CAULDRON(), fn() => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, 0));
569 $this->map(Blocks::LAVA_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_LAVA, $b->getFillLevel()));
570 //potion cauldrons store their real information in the block actor data
571 $this->map(Blocks::POTION_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel()));
572 $this->map(Blocks::WATER_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel()));
573 }
574
575 private function registerFlatWoodBlockSerializers() : void{
576 $this->map(Blocks::ACACIA_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::ACACIA_BUTTON)));
577 $this->map(Blocks::ACACIA_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::ACACIA_DOOR)));
578 $this->map(Blocks::ACACIA_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::ACACIA_FENCE_GATE)));
579 $this->map(Blocks::ACACIA_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::ACACIA_PRESSURE_PLATE)));
580 $this->map(Blocks::ACACIA_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::ACACIA_STANDING_SIGN)));
581 $this->map(Blocks::ACACIA_STAIRS(), fn(WoodenStairs $block) => Helper::encodeStairs($block, new Writer(Ids::ACACIA_STAIRS)));
582 $this->map(Blocks::ACACIA_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::ACACIA_TRAPDOOR)));
583 $this->map(Blocks::ACACIA_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::ACACIA_WALL_SIGN)));
584 $this->mapLog(Blocks::ACACIA_LOG(), Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG);
585 $this->mapLog(Blocks::ACACIA_WOOD(), Ids::ACACIA_WOOD, Ids::STRIPPED_ACACIA_WOOD);
586 $this->mapSimple(Blocks::ACACIA_FENCE(), Ids::ACACIA_FENCE);
587 $this->mapSimple(Blocks::ACACIA_PLANKS(), Ids::ACACIA_PLANKS);
588 $this->mapSlab(Blocks::ACACIA_SLAB(), Ids::ACACIA_SLAB, Ids::ACACIA_DOUBLE_SLAB);
589
590 $this->map(Blocks::BIRCH_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::BIRCH_BUTTON)));
591 $this->map(Blocks::BIRCH_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::BIRCH_DOOR)));
592 $this->map(Blocks::BIRCH_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::BIRCH_FENCE_GATE)));
593 $this->map(Blocks::BIRCH_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::BIRCH_PRESSURE_PLATE)));
594 $this->map(Blocks::BIRCH_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::BIRCH_STANDING_SIGN)));
595 $this->map(Blocks::BIRCH_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::BIRCH_TRAPDOOR)));
596 $this->map(Blocks::BIRCH_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::BIRCH_WALL_SIGN)));
597 $this->mapLog(Blocks::BIRCH_LOG(), Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG);
598 $this->mapLog(Blocks::BIRCH_WOOD(), Ids::BIRCH_WOOD, Ids::STRIPPED_BIRCH_WOOD);
599 $this->mapSimple(Blocks::BIRCH_FENCE(), Ids::BIRCH_FENCE);
600 $this->mapSimple(Blocks::BIRCH_PLANKS(), Ids::BIRCH_PLANKS);
601 $this->mapSlab(Blocks::BIRCH_SLAB(), Ids::BIRCH_SLAB, Ids::BIRCH_DOUBLE_SLAB);
602 $this->mapStairs(Blocks::BIRCH_STAIRS(), Ids::BIRCH_STAIRS);
603
604 $this->map(Blocks::CHERRY_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CHERRY_BUTTON)));
605 $this->map(Blocks::CHERRY_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CHERRY_DOOR)));
606 $this->map(Blocks::CHERRY_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::CHERRY_FENCE_GATE)));
607 $this->map(Blocks::CHERRY_LOG(), fn(Wood $block) => Helper::encodeLog($block, Ids::CHERRY_LOG, Ids::STRIPPED_CHERRY_LOG));
608 $this->map(Blocks::CHERRY_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::CHERRY_PRESSURE_PLATE)));
609 $this->map(Blocks::CHERRY_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::CHERRY_STANDING_SIGN)));
610 $this->map(Blocks::CHERRY_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::CHERRY_TRAPDOOR)));
611 $this->map(Blocks::CHERRY_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::CHERRY_WALL_SIGN)));
612 $this->mapSimple(Blocks::CHERRY_FENCE(), Ids::CHERRY_FENCE);
613 $this->mapSimple(Blocks::CHERRY_PLANKS(), Ids::CHERRY_PLANKS);
614 $this->mapSlab(Blocks::CHERRY_SLAB(), Ids::CHERRY_SLAB, Ids::CHERRY_DOUBLE_SLAB);
615 $this->mapStairs(Blocks::CHERRY_STAIRS(), Ids::CHERRY_STAIRS);
616 $this->map(Blocks::CHERRY_WOOD(), function(Wood $block) : Writer{
617 //we can't use the standard method for this because cherry_wood has a useless property attached to it
618 if(!$block->isStripped()){
619 return Writer::create(Ids::CHERRY_WOOD)
620 ->writePillarAxis($block->getAxis())
621 ->writeBool(StateNames::STRIPPED_BIT, false); //this is useless, but it has to be written
622 }else{
623 return Writer::create(Ids::STRIPPED_CHERRY_WOOD)
624 ->writePillarAxis($block->getAxis());
625 }
626 });
627
628 $this->map(Blocks::CRIMSON_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CRIMSON_BUTTON)));
629 $this->map(Blocks::CRIMSON_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CRIMSON_DOOR)));
630 $this->map(Blocks::CRIMSON_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::CRIMSON_FENCE_GATE)));
631 $this->map(Blocks::CRIMSON_HYPHAE(), fn(Wood $block) => Helper::encodeLog($block, Ids::CRIMSON_HYPHAE, Ids::STRIPPED_CRIMSON_HYPHAE));
632 $this->map(Blocks::CRIMSON_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::CRIMSON_PRESSURE_PLATE)));
633 $this->map(Blocks::CRIMSON_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::CRIMSON_STANDING_SIGN)));
634 $this->map(Blocks::CRIMSON_STEM(), fn(Wood $block) => Helper::encodeLog($block, Ids::CRIMSON_STEM, Ids::STRIPPED_CRIMSON_STEM));
635 $this->map(Blocks::CRIMSON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::CRIMSON_TRAPDOOR)));
636 $this->map(Blocks::CRIMSON_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::CRIMSON_WALL_SIGN)));
637 $this->mapSimple(Blocks::CRIMSON_FENCE(), Ids::CRIMSON_FENCE);
638 $this->mapSimple(Blocks::CRIMSON_PLANKS(), Ids::CRIMSON_PLANKS);
639 $this->mapSlab(Blocks::CRIMSON_SLAB(), Ids::CRIMSON_SLAB, Ids::CRIMSON_DOUBLE_SLAB);
640 $this->mapStairs(Blocks::CRIMSON_STAIRS(), Ids::CRIMSON_STAIRS);
641
642 $this->map(Blocks::DARK_OAK_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::DARK_OAK_BUTTON)));
643 $this->map(Blocks::DARK_OAK_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::DARK_OAK_DOOR)));
644 $this->map(Blocks::DARK_OAK_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::DARK_OAK_FENCE_GATE)));
645 $this->map(Blocks::DARK_OAK_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::DARK_OAK_PRESSURE_PLATE)));
646 $this->map(Blocks::DARK_OAK_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::DARKOAK_STANDING_SIGN)));
647 $this->map(Blocks::DARK_OAK_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::DARK_OAK_TRAPDOOR)));
648 $this->map(Blocks::DARK_OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::DARKOAK_WALL_SIGN)));
649 $this->mapLog(Blocks::DARK_OAK_LOG(), Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG);
650 $this->mapLog(Blocks::DARK_OAK_WOOD(), Ids::DARK_OAK_WOOD, Ids::STRIPPED_DARK_OAK_WOOD);
651 $this->mapSimple(Blocks::DARK_OAK_FENCE(), Ids::DARK_OAK_FENCE);
652 $this->mapSimple(Blocks::DARK_OAK_PLANKS(), Ids::DARK_OAK_PLANKS);
653 $this->mapSlab(Blocks::DARK_OAK_SLAB(), Ids::DARK_OAK_SLAB, Ids::DARK_OAK_DOUBLE_SLAB);
654 $this->mapStairs(Blocks::DARK_OAK_STAIRS(), Ids::DARK_OAK_STAIRS);
655
656 $this->map(Blocks::JUNGLE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::JUNGLE_BUTTON)));
657 $this->map(Blocks::JUNGLE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::JUNGLE_DOOR)));
658 $this->map(Blocks::JUNGLE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::JUNGLE_FENCE_GATE)));
659 $this->map(Blocks::JUNGLE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::JUNGLE_PRESSURE_PLATE)));
660 $this->map(Blocks::JUNGLE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::JUNGLE_STANDING_SIGN)));
661 $this->map(Blocks::JUNGLE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::JUNGLE_TRAPDOOR)));
662 $this->map(Blocks::JUNGLE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::JUNGLE_WALL_SIGN)));
663 $this->mapLog(Blocks::JUNGLE_LOG(), Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG);
664 $this->mapLog(Blocks::JUNGLE_WOOD(), Ids::JUNGLE_WOOD, Ids::STRIPPED_JUNGLE_WOOD);
665 $this->mapSimple(Blocks::JUNGLE_FENCE(), Ids::JUNGLE_FENCE);
666 $this->mapSimple(Blocks::JUNGLE_PLANKS(), Ids::JUNGLE_PLANKS);
667 $this->mapSlab(Blocks::JUNGLE_SLAB(), Ids::JUNGLE_SLAB, Ids::JUNGLE_DOUBLE_SLAB);
668 $this->mapStairs(Blocks::JUNGLE_STAIRS(), Ids::JUNGLE_STAIRS);
669
670 $this->map(Blocks::MANGROVE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::MANGROVE_BUTTON)));
671 $this->map(Blocks::MANGROVE_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::MANGROVE_DOOR)));
672 $this->map(Blocks::MANGROVE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::MANGROVE_FENCE_GATE)));
673 $this->map(Blocks::MANGROVE_LOG(), fn(Wood $block) => Helper::encodeLog($block, Ids::MANGROVE_LOG, Ids::STRIPPED_MANGROVE_LOG));
674 $this->map(Blocks::MANGROVE_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::MANGROVE_PRESSURE_PLATE)));
675 $this->map(Blocks::MANGROVE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::MANGROVE_STANDING_SIGN)));
676 $this->map(Blocks::MANGROVE_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::MANGROVE_TRAPDOOR)));
677 $this->map(Blocks::MANGROVE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::MANGROVE_WALL_SIGN)));
678 $this->mapSimple(Blocks::MANGROVE_FENCE(), Ids::MANGROVE_FENCE);
679 $this->mapSimple(Blocks::MANGROVE_PLANKS(), Ids::MANGROVE_PLANKS);
680 $this->mapSlab(Blocks::MANGROVE_SLAB(), Ids::MANGROVE_SLAB, Ids::MANGROVE_DOUBLE_SLAB);
681 $this->mapStairs(Blocks::MANGROVE_STAIRS(), Ids::MANGROVE_STAIRS);
682 $this->map(Blocks::MANGROVE_WOOD(), function(Wood $block) : Writer{
683 //we can't use the standard method for this because mangrove_wood has a useless property attached to it
684 if(!$block->isStripped()){
685 return Writer::create(Ids::MANGROVE_WOOD)
686 ->writePillarAxis($block->getAxis())
687 ->writeBool(StateNames::STRIPPED_BIT, false); //this is useless, but it has to be written
688 }else{
689 return Writer::create(Ids::STRIPPED_MANGROVE_WOOD)
690 ->writePillarAxis($block->getAxis());
691 }
692 });
693
694 $this->map(Blocks::OAK_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::WOODEN_BUTTON)));
695 $this->map(Blocks::OAK_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::WOODEN_DOOR)));
696 $this->map(Blocks::OAK_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::FENCE_GATE)));
697 $this->map(Blocks::OAK_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::WOODEN_PRESSURE_PLATE)));
698 $this->map(Blocks::OAK_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::STANDING_SIGN)));
699 $this->map(Blocks::OAK_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::TRAPDOOR)));
700 $this->map(Blocks::OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WALL_SIGN)));
701 $this->mapLog(Blocks::OAK_LOG(), Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG);
702 $this->mapLog(Blocks::OAK_WOOD(), Ids::OAK_WOOD, Ids::STRIPPED_OAK_WOOD);
703 $this->mapSimple(Blocks::OAK_FENCE(), Ids::OAK_FENCE);
704 $this->mapSimple(Blocks::OAK_PLANKS(), Ids::OAK_PLANKS);
705 $this->mapSlab(Blocks::OAK_SLAB(), Ids::OAK_SLAB, Ids::OAK_DOUBLE_SLAB);
706 $this->mapStairs(Blocks::OAK_STAIRS(), Ids::OAK_STAIRS);
707
708 $this->map(Blocks::SPRUCE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::SPRUCE_BUTTON)));
709 $this->map(Blocks::SPRUCE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::SPRUCE_DOOR)));
710 $this->map(Blocks::SPRUCE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::SPRUCE_FENCE_GATE)));
711 $this->map(Blocks::SPRUCE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::SPRUCE_PRESSURE_PLATE)));
712 $this->map(Blocks::SPRUCE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::SPRUCE_STANDING_SIGN)));
713 $this->map(Blocks::SPRUCE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::SPRUCE_TRAPDOOR)));
714 $this->map(Blocks::SPRUCE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::SPRUCE_WALL_SIGN)));
715 $this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
716 $this->mapLog(Blocks::SPRUCE_WOOD(), Ids::SPRUCE_WOOD, Ids::STRIPPED_SPRUCE_WOOD);
717 $this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
718 $this->mapSimple(Blocks::SPRUCE_PLANKS(), Ids::SPRUCE_PLANKS);
719 $this->mapSlab(Blocks::SPRUCE_SLAB(), Ids::SPRUCE_SLAB, Ids::SPRUCE_DOUBLE_SLAB);
720 $this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
721 //wood and slabs still use the old way of storing wood type
722
723 $this->map(Blocks::WARPED_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::WARPED_BUTTON)));
724 $this->map(Blocks::WARPED_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::WARPED_DOOR)));
725 $this->map(Blocks::WARPED_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::WARPED_FENCE_GATE)));
726 $this->map(Blocks::WARPED_HYPHAE(), fn(Wood $block) => Helper::encodeLog($block, Ids::WARPED_HYPHAE, Ids::STRIPPED_WARPED_HYPHAE));
727 $this->map(Blocks::WARPED_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::WARPED_PRESSURE_PLATE)));
728 $this->map(Blocks::WARPED_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::WARPED_STANDING_SIGN)));
729 $this->map(Blocks::WARPED_STEM(), fn(Wood $block) => Helper::encodeLog($block, Ids::WARPED_STEM, Ids::STRIPPED_WARPED_STEM));
730 $this->map(Blocks::WARPED_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::WARPED_TRAPDOOR)));
731 $this->map(Blocks::WARPED_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WARPED_WALL_SIGN)));
732 $this->mapSimple(Blocks::WARPED_FENCE(), Ids::WARPED_FENCE);
733 $this->mapSimple(Blocks::WARPED_PLANKS(), Ids::WARPED_PLANKS);
734 $this->mapSlab(Blocks::WARPED_SLAB(), Ids::WARPED_SLAB, Ids::WARPED_DOUBLE_SLAB);
735 $this->mapStairs(Blocks::WARPED_STAIRS(), Ids::WARPED_STAIRS);
736 }
737
738 private function registerLeavesSerializers() : void{
739 //flattened IDs
740 $this->map(Blocks::AZALEA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::AZALEA_LEAVES)));
741 $this->map(Blocks::CHERRY_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::CHERRY_LEAVES)));
742 $this->map(Blocks::FLOWERING_AZALEA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::AZALEA_LEAVES_FLOWERED)));
743 $this->map(Blocks::MANGROVE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::MANGROVE_LEAVES)));
744
745 //legacy mess
746 $this->map(Blocks::ACACIA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::ACACIA_LEAVES)));
747 $this->map(Blocks::BIRCH_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::BIRCH_LEAVES)));
748 $this->map(Blocks::DARK_OAK_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::DARK_OAK_LEAVES)));
749 $this->map(Blocks::JUNGLE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::JUNGLE_LEAVES)));
750 $this->map(Blocks::OAK_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::OAK_LEAVES)));
751 $this->map(Blocks::SPRUCE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::SPRUCE_LEAVES)));
752 }
753
754 private function registerSaplingSerializers() : void{
755 foreach([
756 Ids::ACACIA_SAPLING => Blocks::ACACIA_SAPLING(),
757 Ids::BIRCH_SAPLING => Blocks::BIRCH_SAPLING(),
758 Ids::DARK_OAK_SAPLING => Blocks::DARK_OAK_SAPLING(),
759 Ids::JUNGLE_SAPLING => Blocks::JUNGLE_SAPLING(),
760 Ids::OAK_SAPLING => Blocks::OAK_SAPLING(),
761 Ids::SPRUCE_SAPLING => Blocks::SPRUCE_SAPLING(),
762 ] as $id => $block){
763 $this->map($block, fn(Sapling $block) => Helper::encodeSapling($block, new Writer($id)));
764 }
765 }
766
767 private function registerSimpleSerializers() : void{
768 $this->mapSimple(Blocks::AIR(), Ids::AIR);
769 $this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
770 $this->mapSimple(Blocks::ANCIENT_DEBRIS(), Ids::ANCIENT_DEBRIS);
771 $this->mapSimple(Blocks::ANDESITE(), Ids::ANDESITE);
772 $this->mapSimple(Blocks::BARRIER(), Ids::BARRIER);
773 $this->mapSimple(Blocks::BEACON(), Ids::BEACON);
774 $this->mapSimple(Blocks::BLACKSTONE(), Ids::BLACKSTONE);
775 $this->mapSimple(Blocks::BLUE_ICE(), Ids::BLUE_ICE);
776 $this->mapSimple(Blocks::BOOKSHELF(), Ids::BOOKSHELF);
777 $this->mapSimple(Blocks::BRICKS(), Ids::BRICK_BLOCK);
778 $this->mapSimple(Blocks::BROWN_MUSHROOM(), Ids::BROWN_MUSHROOM);
779 $this->mapSimple(Blocks::BUDDING_AMETHYST(), Ids::BUDDING_AMETHYST);
780 $this->mapSimple(Blocks::CALCITE(), Ids::CALCITE);
781 $this->mapSimple(Blocks::CARTOGRAPHY_TABLE(), Ids::CARTOGRAPHY_TABLE);
782 $this->mapSimple(Blocks::CHEMICAL_HEAT(), Ids::CHEMICAL_HEAT);
783 $this->mapSimple(Blocks::CHISELED_DEEPSLATE(), Ids::CHISELED_DEEPSLATE);
784 $this->mapSimple(Blocks::CHISELED_NETHER_BRICKS(), Ids::CHISELED_NETHER_BRICKS);
785 $this->mapSimple(Blocks::CHISELED_POLISHED_BLACKSTONE(), Ids::CHISELED_POLISHED_BLACKSTONE);
786 $this->mapSimple(Blocks::CHORUS_PLANT(), Ids::CHORUS_PLANT);
787 $this->mapSimple(Blocks::CLAY(), Ids::CLAY);
788 $this->mapSimple(Blocks::COAL(), Ids::COAL_BLOCK);
789 $this->mapSimple(Blocks::COAL_ORE(), Ids::COAL_ORE);
790 $this->mapSimple(Blocks::COBBLED_DEEPSLATE(), Ids::COBBLED_DEEPSLATE);
791 $this->mapSimple(Blocks::COBBLESTONE(), Ids::COBBLESTONE);
792 $this->mapSimple(Blocks::COBWEB(), Ids::WEB);
793 $this->mapSimple(Blocks::COPPER_ORE(), Ids::COPPER_ORE);
794 $this->mapSimple(Blocks::CRACKED_DEEPSLATE_BRICKS(), Ids::CRACKED_DEEPSLATE_BRICKS);
795 $this->mapSimple(Blocks::CRACKED_DEEPSLATE_TILES(), Ids::CRACKED_DEEPSLATE_TILES);
796 $this->mapSimple(Blocks::CRACKED_NETHER_BRICKS(), Ids::CRACKED_NETHER_BRICKS);
797 $this->mapSimple(Blocks::CRACKED_POLISHED_BLACKSTONE_BRICKS(), Ids::CRACKED_POLISHED_BLACKSTONE_BRICKS);
798 $this->mapSimple(Blocks::CRAFTING_TABLE(), Ids::CRAFTING_TABLE);
799 $this->mapSimple(Blocks::CRIMSON_ROOTS(), Ids::CRIMSON_ROOTS);
800 $this->mapSimple(Blocks::CRYING_OBSIDIAN(), Ids::CRYING_OBSIDIAN);
801 $this->mapSimple(Blocks::DANDELION(), Ids::YELLOW_FLOWER);
802 $this->mapSimple(Blocks::DEAD_BUSH(), Ids::DEADBUSH);
803 $this->mapSimple(Blocks::DEEPSLATE_BRICKS(), Ids::DEEPSLATE_BRICKS);
804 $this->mapSimple(Blocks::DEEPSLATE_COAL_ORE(), Ids::DEEPSLATE_COAL_ORE);
805 $this->mapSimple(Blocks::DEEPSLATE_COPPER_ORE(), Ids::DEEPSLATE_COPPER_ORE);
806 $this->mapSimple(Blocks::DEEPSLATE_DIAMOND_ORE(), Ids::DEEPSLATE_DIAMOND_ORE);
807 $this->mapSimple(Blocks::DEEPSLATE_EMERALD_ORE(), Ids::DEEPSLATE_EMERALD_ORE);
808 $this->mapSimple(Blocks::DEEPSLATE_GOLD_ORE(), Ids::DEEPSLATE_GOLD_ORE);
809 $this->mapSimple(Blocks::DEEPSLATE_IRON_ORE(), Ids::DEEPSLATE_IRON_ORE);
810 $this->mapSimple(Blocks::DEEPSLATE_LAPIS_LAZULI_ORE(), Ids::DEEPSLATE_LAPIS_ORE);
811 $this->mapSimple(Blocks::DEEPSLATE_TILES(), Ids::DEEPSLATE_TILES);
812 $this->mapSimple(Blocks::DIAMOND(), Ids::DIAMOND_BLOCK);
813 $this->mapSimple(Blocks::DIAMOND_ORE(), Ids::DIAMOND_ORE);
814 $this->mapSimple(Blocks::DIORITE(), Ids::DIORITE);
815 $this->mapSimple(Blocks::DRAGON_EGG(), Ids::DRAGON_EGG);
816 $this->mapSimple(Blocks::DRIED_KELP(), Ids::DRIED_KELP_BLOCK);
817 $this->mapSimple(Blocks::ELEMENT_ACTINIUM(), Ids::ELEMENT_89);
818 $this->mapSimple(Blocks::ELEMENT_ALUMINUM(), Ids::ELEMENT_13);
819 $this->mapSimple(Blocks::ELEMENT_AMERICIUM(), Ids::ELEMENT_95);
820 $this->mapSimple(Blocks::ELEMENT_ANTIMONY(), Ids::ELEMENT_51);
821 $this->mapSimple(Blocks::ELEMENT_ARGON(), Ids::ELEMENT_18);
822 $this->mapSimple(Blocks::ELEMENT_ARSENIC(), Ids::ELEMENT_33);
823 $this->mapSimple(Blocks::ELEMENT_ASTATINE(), Ids::ELEMENT_85);
824 $this->mapSimple(Blocks::ELEMENT_BARIUM(), Ids::ELEMENT_56);
825 $this->mapSimple(Blocks::ELEMENT_BERKELIUM(), Ids::ELEMENT_97);
826 $this->mapSimple(Blocks::ELEMENT_BERYLLIUM(), Ids::ELEMENT_4);
827 $this->mapSimple(Blocks::ELEMENT_BISMUTH(), Ids::ELEMENT_83);
828 $this->mapSimple(Blocks::ELEMENT_BOHRIUM(), Ids::ELEMENT_107);
829 $this->mapSimple(Blocks::ELEMENT_BORON(), Ids::ELEMENT_5);
830 $this->mapSimple(Blocks::ELEMENT_BROMINE(), Ids::ELEMENT_35);
831 $this->mapSimple(Blocks::ELEMENT_CADMIUM(), Ids::ELEMENT_48);
832 $this->mapSimple(Blocks::ELEMENT_CALCIUM(), Ids::ELEMENT_20);
833 $this->mapSimple(Blocks::ELEMENT_CALIFORNIUM(), Ids::ELEMENT_98);
834 $this->mapSimple(Blocks::ELEMENT_CARBON(), Ids::ELEMENT_6);
835 $this->mapSimple(Blocks::ELEMENT_CERIUM(), Ids::ELEMENT_58);
836 $this->mapSimple(Blocks::ELEMENT_CESIUM(), Ids::ELEMENT_55);
837 $this->mapSimple(Blocks::ELEMENT_CHLORINE(), Ids::ELEMENT_17);
838 $this->mapSimple(Blocks::ELEMENT_CHROMIUM(), Ids::ELEMENT_24);
839 $this->mapSimple(Blocks::ELEMENT_COBALT(), Ids::ELEMENT_27);
840 $this->mapSimple(Blocks::ELEMENT_COPERNICIUM(), Ids::ELEMENT_112);
841 $this->mapSimple(Blocks::ELEMENT_COPPER(), Ids::ELEMENT_29);
842 $this->mapSimple(Blocks::ELEMENT_CURIUM(), Ids::ELEMENT_96);
843 $this->mapSimple(Blocks::ELEMENT_DARMSTADTIUM(), Ids::ELEMENT_110);
844 $this->mapSimple(Blocks::ELEMENT_DUBNIUM(), Ids::ELEMENT_105);
845 $this->mapSimple(Blocks::ELEMENT_DYSPROSIUM(), Ids::ELEMENT_66);
846 $this->mapSimple(Blocks::ELEMENT_EINSTEINIUM(), Ids::ELEMENT_99);
847 $this->mapSimple(Blocks::ELEMENT_ERBIUM(), Ids::ELEMENT_68);
848 $this->mapSimple(Blocks::ELEMENT_EUROPIUM(), Ids::ELEMENT_63);
849 $this->mapSimple(Blocks::ELEMENT_FERMIUM(), Ids::ELEMENT_100);
850 $this->mapSimple(Blocks::ELEMENT_FLEROVIUM(), Ids::ELEMENT_114);
851 $this->mapSimple(Blocks::ELEMENT_FLUORINE(), Ids::ELEMENT_9);
852 $this->mapSimple(Blocks::ELEMENT_FRANCIUM(), Ids::ELEMENT_87);
853 $this->mapSimple(Blocks::ELEMENT_GADOLINIUM(), Ids::ELEMENT_64);
854 $this->mapSimple(Blocks::ELEMENT_GALLIUM(), Ids::ELEMENT_31);
855 $this->mapSimple(Blocks::ELEMENT_GERMANIUM(), Ids::ELEMENT_32);
856 $this->mapSimple(Blocks::ELEMENT_GOLD(), Ids::ELEMENT_79);
857 $this->mapSimple(Blocks::ELEMENT_HAFNIUM(), Ids::ELEMENT_72);
858 $this->mapSimple(Blocks::ELEMENT_HASSIUM(), Ids::ELEMENT_108);
859 $this->mapSimple(Blocks::ELEMENT_HELIUM(), Ids::ELEMENT_2);
860 $this->mapSimple(Blocks::ELEMENT_HOLMIUM(), Ids::ELEMENT_67);
861 $this->mapSimple(Blocks::ELEMENT_HYDROGEN(), Ids::ELEMENT_1);
862 $this->mapSimple(Blocks::ELEMENT_INDIUM(), Ids::ELEMENT_49);
863 $this->mapSimple(Blocks::ELEMENT_IODINE(), Ids::ELEMENT_53);
864 $this->mapSimple(Blocks::ELEMENT_IRIDIUM(), Ids::ELEMENT_77);
865 $this->mapSimple(Blocks::ELEMENT_IRON(), Ids::ELEMENT_26);
866 $this->mapSimple(Blocks::ELEMENT_KRYPTON(), Ids::ELEMENT_36);
867 $this->mapSimple(Blocks::ELEMENT_LANTHANUM(), Ids::ELEMENT_57);
868 $this->mapSimple(Blocks::ELEMENT_LAWRENCIUM(), Ids::ELEMENT_103);
869 $this->mapSimple(Blocks::ELEMENT_LEAD(), Ids::ELEMENT_82);
870 $this->mapSimple(Blocks::ELEMENT_LITHIUM(), Ids::ELEMENT_3);
871 $this->mapSimple(Blocks::ELEMENT_LIVERMORIUM(), Ids::ELEMENT_116);
872 $this->mapSimple(Blocks::ELEMENT_LUTETIUM(), Ids::ELEMENT_71);
873 $this->mapSimple(Blocks::ELEMENT_MAGNESIUM(), Ids::ELEMENT_12);
874 $this->mapSimple(Blocks::ELEMENT_MANGANESE(), Ids::ELEMENT_25);
875 $this->mapSimple(Blocks::ELEMENT_MEITNERIUM(), Ids::ELEMENT_109);
876 $this->mapSimple(Blocks::ELEMENT_MENDELEVIUM(), Ids::ELEMENT_101);
877 $this->mapSimple(Blocks::ELEMENT_MERCURY(), Ids::ELEMENT_80);
878 $this->mapSimple(Blocks::ELEMENT_MOLYBDENUM(), Ids::ELEMENT_42);
879 $this->mapSimple(Blocks::ELEMENT_MOSCOVIUM(), Ids::ELEMENT_115);
880 $this->mapSimple(Blocks::ELEMENT_NEODYMIUM(), Ids::ELEMENT_60);
881 $this->mapSimple(Blocks::ELEMENT_NEON(), Ids::ELEMENT_10);
882 $this->mapSimple(Blocks::ELEMENT_NEPTUNIUM(), Ids::ELEMENT_93);
883 $this->mapSimple(Blocks::ELEMENT_NICKEL(), Ids::ELEMENT_28);
884 $this->mapSimple(Blocks::ELEMENT_NIHONIUM(), Ids::ELEMENT_113);
885 $this->mapSimple(Blocks::ELEMENT_NIOBIUM(), Ids::ELEMENT_41);
886 $this->mapSimple(Blocks::ELEMENT_NITROGEN(), Ids::ELEMENT_7);
887 $this->mapSimple(Blocks::ELEMENT_NOBELIUM(), Ids::ELEMENT_102);
888 $this->mapSimple(Blocks::ELEMENT_OGANESSON(), Ids::ELEMENT_118);
889 $this->mapSimple(Blocks::ELEMENT_OSMIUM(), Ids::ELEMENT_76);
890 $this->mapSimple(Blocks::ELEMENT_OXYGEN(), Ids::ELEMENT_8);
891 $this->mapSimple(Blocks::ELEMENT_PALLADIUM(), Ids::ELEMENT_46);
892 $this->mapSimple(Blocks::ELEMENT_PHOSPHORUS(), Ids::ELEMENT_15);
893 $this->mapSimple(Blocks::ELEMENT_PLATINUM(), Ids::ELEMENT_78);
894 $this->mapSimple(Blocks::ELEMENT_PLUTONIUM(), Ids::ELEMENT_94);
895 $this->mapSimple(Blocks::ELEMENT_POLONIUM(), Ids::ELEMENT_84);
896 $this->mapSimple(Blocks::ELEMENT_POTASSIUM(), Ids::ELEMENT_19);
897 $this->mapSimple(Blocks::ELEMENT_PRASEODYMIUM(), Ids::ELEMENT_59);
898 $this->mapSimple(Blocks::ELEMENT_PROMETHIUM(), Ids::ELEMENT_61);
899 $this->mapSimple(Blocks::ELEMENT_PROTACTINIUM(), Ids::ELEMENT_91);
900 $this->mapSimple(Blocks::ELEMENT_RADIUM(), Ids::ELEMENT_88);
901 $this->mapSimple(Blocks::ELEMENT_RADON(), Ids::ELEMENT_86);
902 $this->mapSimple(Blocks::ELEMENT_RHENIUM(), Ids::ELEMENT_75);
903 $this->mapSimple(Blocks::ELEMENT_RHODIUM(), Ids::ELEMENT_45);
904 $this->mapSimple(Blocks::ELEMENT_ROENTGENIUM(), Ids::ELEMENT_111);
905 $this->mapSimple(Blocks::ELEMENT_RUBIDIUM(), Ids::ELEMENT_37);
906 $this->mapSimple(Blocks::ELEMENT_RUTHENIUM(), Ids::ELEMENT_44);
907 $this->mapSimple(Blocks::ELEMENT_RUTHERFORDIUM(), Ids::ELEMENT_104);
908 $this->mapSimple(Blocks::ELEMENT_SAMARIUM(), Ids::ELEMENT_62);
909 $this->mapSimple(Blocks::ELEMENT_SCANDIUM(), Ids::ELEMENT_21);
910 $this->mapSimple(Blocks::ELEMENT_SEABORGIUM(), Ids::ELEMENT_106);
911 $this->mapSimple(Blocks::ELEMENT_SELENIUM(), Ids::ELEMENT_34);
912 $this->mapSimple(Blocks::ELEMENT_SILICON(), Ids::ELEMENT_14);
913 $this->mapSimple(Blocks::ELEMENT_SILVER(), Ids::ELEMENT_47);
914 $this->mapSimple(Blocks::ELEMENT_SODIUM(), Ids::ELEMENT_11);
915 $this->mapSimple(Blocks::ELEMENT_STRONTIUM(), Ids::ELEMENT_38);
916 $this->mapSimple(Blocks::ELEMENT_SULFUR(), Ids::ELEMENT_16);
917 $this->mapSimple(Blocks::ELEMENT_TANTALUM(), Ids::ELEMENT_73);
918 $this->mapSimple(Blocks::ELEMENT_TECHNETIUM(), Ids::ELEMENT_43);
919 $this->mapSimple(Blocks::ELEMENT_TELLURIUM(), Ids::ELEMENT_52);
920 $this->mapSimple(Blocks::ELEMENT_TENNESSINE(), Ids::ELEMENT_117);
921 $this->mapSimple(Blocks::ELEMENT_TERBIUM(), Ids::ELEMENT_65);
922 $this->mapSimple(Blocks::ELEMENT_THALLIUM(), Ids::ELEMENT_81);
923 $this->mapSimple(Blocks::ELEMENT_THORIUM(), Ids::ELEMENT_90);
924 $this->mapSimple(Blocks::ELEMENT_THULIUM(), Ids::ELEMENT_69);
925 $this->mapSimple(Blocks::ELEMENT_TIN(), Ids::ELEMENT_50);
926 $this->mapSimple(Blocks::ELEMENT_TITANIUM(), Ids::ELEMENT_22);
927 $this->mapSimple(Blocks::ELEMENT_TUNGSTEN(), Ids::ELEMENT_74);
928 $this->mapSimple(Blocks::ELEMENT_URANIUM(), Ids::ELEMENT_92);
929 $this->mapSimple(Blocks::ELEMENT_VANADIUM(), Ids::ELEMENT_23);
930 $this->mapSimple(Blocks::ELEMENT_XENON(), Ids::ELEMENT_54);
931 $this->mapSimple(Blocks::ELEMENT_YTTERBIUM(), Ids::ELEMENT_70);
932 $this->mapSimple(Blocks::ELEMENT_YTTRIUM(), Ids::ELEMENT_39);
933 $this->mapSimple(Blocks::ELEMENT_ZERO(), Ids::ELEMENT_0);
934 $this->mapSimple(Blocks::ELEMENT_ZINC(), Ids::ELEMENT_30);
935 $this->mapSimple(Blocks::ELEMENT_ZIRCONIUM(), Ids::ELEMENT_40);
936 $this->mapSimple(Blocks::EMERALD(), Ids::EMERALD_BLOCK);
937 $this->mapSimple(Blocks::EMERALD_ORE(), Ids::EMERALD_ORE);
938 $this->mapSimple(Blocks::ENCHANTING_TABLE(), Ids::ENCHANTING_TABLE);
939 $this->mapSimple(Blocks::END_STONE(), Ids::END_STONE);
940 $this->mapSimple(Blocks::END_STONE_BRICKS(), Ids::END_BRICKS);
941 $this->mapSimple(Blocks::FERN(), Ids::FERN);
942 $this->mapSimple(Blocks::FLETCHING_TABLE(), Ids::FLETCHING_TABLE);
943 $this->mapSimple(Blocks::GILDED_BLACKSTONE(), Ids::GILDED_BLACKSTONE);
944 $this->mapSimple(Blocks::GLASS(), Ids::GLASS);
945 $this->mapSimple(Blocks::GLASS_PANE(), Ids::GLASS_PANE);
946 $this->mapSimple(Blocks::GLOWING_OBSIDIAN(), Ids::GLOWINGOBSIDIAN);
947 $this->mapSimple(Blocks::GLOWSTONE(), Ids::GLOWSTONE);
948 $this->mapSimple(Blocks::GOLD(), Ids::GOLD_BLOCK);
949 $this->mapSimple(Blocks::GOLD_ORE(), Ids::GOLD_ORE);
950 $this->mapSimple(Blocks::GRANITE(), Ids::GRANITE);
951 $this->mapSimple(Blocks::GRASS(), Ids::GRASS_BLOCK);
952 $this->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
953 $this->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
954 $this->mapSimple(Blocks::HANGING_ROOTS(), Ids::HANGING_ROOTS);
955 $this->mapSimple(Blocks::HARDENED_CLAY(), Ids::HARDENED_CLAY);
956 $this->mapSimple(Blocks::HARDENED_GLASS(), Ids::HARD_GLASS);
957 $this->mapSimple(Blocks::HARDENED_GLASS_PANE(), Ids::HARD_GLASS_PANE);
958 $this->mapSimple(Blocks::HONEYCOMB(), Ids::HONEYCOMB_BLOCK);
959 $this->mapSimple(Blocks::ICE(), Ids::ICE);
960 $this->mapSimple(Blocks::INFO_UPDATE(), Ids::INFO_UPDATE);
961 $this->mapSimple(Blocks::INFO_UPDATE2(), Ids::INFO_UPDATE2);
962 $this->mapSimple(Blocks::INVISIBLE_BEDROCK(), Ids::INVISIBLE_BEDROCK);
963 $this->mapSimple(Blocks::IRON(), Ids::IRON_BLOCK);
964 $this->mapSimple(Blocks::IRON_BARS(), Ids::IRON_BARS);
965 $this->mapSimple(Blocks::IRON_ORE(), Ids::IRON_ORE);
966 $this->mapSimple(Blocks::JUKEBOX(), Ids::JUKEBOX);
967 $this->mapSimple(Blocks::LAPIS_LAZULI(), Ids::LAPIS_BLOCK);
968 $this->mapSimple(Blocks::LAPIS_LAZULI_ORE(), Ids::LAPIS_ORE);
969 $this->mapSimple(Blocks::LEGACY_STONECUTTER(), Ids::STONECUTTER);
970 $this->mapSimple(Blocks::LILY_PAD(), Ids::WATERLILY);
971 $this->mapSimple(Blocks::MAGMA(), Ids::MAGMA);
972 $this->mapSimple(Blocks::MANGROVE_ROOTS(), Ids::MANGROVE_ROOTS);
973 $this->mapSimple(Blocks::MELON(), Ids::MELON_BLOCK);
974 $this->mapSimple(Blocks::MONSTER_SPAWNER(), Ids::MOB_SPAWNER);
975 $this->mapSimple(Blocks::MOSSY_COBBLESTONE(), Ids::MOSSY_COBBLESTONE);
976 $this->mapSimple(Blocks::MUD(), Ids::MUD);
977 $this->mapSimple(Blocks::MUD_BRICKS(), Ids::MUD_BRICKS);
978 $this->mapSimple(Blocks::MYCELIUM(), Ids::MYCELIUM);
979 $this->mapSimple(Blocks::NETHERITE(), Ids::NETHERITE_BLOCK);
980 $this->mapSimple(Blocks::NETHERRACK(), Ids::NETHERRACK);
981 $this->mapSimple(Blocks::NETHER_BRICKS(), Ids::NETHER_BRICK);
982 $this->mapSimple(Blocks::NETHER_BRICK_FENCE(), Ids::NETHER_BRICK_FENCE);
983 $this->mapSimple(Blocks::NETHER_GOLD_ORE(), Ids::NETHER_GOLD_ORE);
984 $this->mapSimple(Blocks::NETHER_QUARTZ_ORE(), Ids::QUARTZ_ORE);
985 $this->mapSimple(Blocks::NETHER_REACTOR_CORE(), Ids::NETHERREACTOR);
986 $this->mapSimple(Blocks::NETHER_WART_BLOCK(), Ids::NETHER_WART_BLOCK);
987 $this->mapSimple(Blocks::NOTE_BLOCK(), Ids::NOTEBLOCK);
988 $this->mapSimple(Blocks::OBSIDIAN(), Ids::OBSIDIAN);
989 $this->mapSimple(Blocks::PACKED_ICE(), Ids::PACKED_ICE);
990 $this->mapSimple(Blocks::PACKED_MUD(), Ids::PACKED_MUD);
991 $this->mapSimple(Blocks::PODZOL(), Ids::PODZOL);
992 $this->mapSimple(Blocks::POLISHED_ANDESITE(), Ids::POLISHED_ANDESITE);
993 $this->mapSimple(Blocks::POLISHED_BLACKSTONE(), Ids::POLISHED_BLACKSTONE);
994 $this->mapSimple(Blocks::POLISHED_BLACKSTONE_BRICKS(), Ids::POLISHED_BLACKSTONE_BRICKS);
995 $this->mapSimple(Blocks::POLISHED_DEEPSLATE(), Ids::POLISHED_DEEPSLATE);
996 $this->mapSimple(Blocks::POLISHED_DIORITE(), Ids::POLISHED_DIORITE);
997 $this->mapSimple(Blocks::POLISHED_GRANITE(), Ids::POLISHED_GRANITE);
998 $this->mapSimple(Blocks::QUARTZ_BRICKS(), Ids::QUARTZ_BRICKS);
999 $this->mapSimple(Blocks::RAW_COPPER(), Ids::RAW_COPPER_BLOCK);
1000 $this->mapSimple(Blocks::RAW_GOLD(), Ids::RAW_GOLD_BLOCK);
1001 $this->mapSimple(Blocks::RAW_IRON(), Ids::RAW_IRON_BLOCK);
1002 $this->mapSimple(Blocks::REDSTONE(), Ids::REDSTONE_BLOCK);
1003 $this->mapSimple(Blocks::RED_MUSHROOM(), Ids::RED_MUSHROOM);
1004 $this->mapSimple(Blocks::RED_NETHER_BRICKS(), Ids::RED_NETHER_BRICK);
1005 $this->mapSimple(Blocks::REINFORCED_DEEPSLATE(), Ids::REINFORCED_DEEPSLATE);
1006 $this->mapSimple(Blocks::RESERVED6(), Ids::RESERVED6);
1007 $this->mapSimple(Blocks::SCULK(), Ids::SCULK);
1008 $this->mapSimple(Blocks::SEA_LANTERN(), Ids::SEA_LANTERN);
1009 $this->mapSimple(Blocks::SHROOMLIGHT(), Ids::SHROOMLIGHT);
1010 $this->mapSimple(Blocks::SHULKER_BOX(), Ids::UNDYED_SHULKER_BOX);
1011 $this->mapSimple(Blocks::SLIME(), Ids::SLIME);
1012 $this->mapSimple(Blocks::SMITHING_TABLE(), Ids::SMITHING_TABLE);
1013 $this->mapSimple(Blocks::SMOOTH_BASALT(), Ids::SMOOTH_BASALT);
1014 $this->mapSimple(Blocks::SMOOTH_STONE(), Ids::SMOOTH_STONE);
1015 $this->mapSimple(Blocks::SNOW(), Ids::SNOW);
1016 $this->mapSimple(Blocks::SOUL_SAND(), Ids::SOUL_SAND);
1017 $this->mapSimple(Blocks::SOUL_SOIL(), Ids::SOUL_SOIL);
1018 $this->mapSimple(Blocks::SPORE_BLOSSOM(), Ids::SPORE_BLOSSOM);
1019 $this->mapSimple(Blocks::STONE(), Ids::STONE);
1020 $this->mapSimple(Blocks::TALL_GRASS(), Ids::SHORT_GRASS); //no, this is not a typo - tall_grass is now the double block, just to be confusing :(
1021 $this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
1022 $this->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER);
1023 $this->mapSimple(Blocks::TUFF(), Ids::TUFF);
1024 $this->mapSimple(Blocks::WARPED_WART_BLOCK(), Ids::WARPED_WART_BLOCK);
1025 $this->mapSimple(Blocks::WARPED_ROOTS(), Ids::WARPED_ROOTS);
1026 $this->mapSimple(Blocks::WITHER_ROSE(), Ids::WITHER_ROSE);
1027
1028 $this->mapSimple(Blocks::ALLIUM(), Ids::ALLIUM);
1029 $this->mapSimple(Blocks::CORNFLOWER(), Ids::CORNFLOWER);
1030 $this->mapSimple(Blocks::AZURE_BLUET(), Ids::AZURE_BLUET);
1031 $this->mapSimple(Blocks::LILY_OF_THE_VALLEY(), Ids::LILY_OF_THE_VALLEY);
1032 $this->mapSimple(Blocks::BLUE_ORCHID(), Ids::BLUE_ORCHID);
1033 $this->mapSimple(Blocks::OXEYE_DAISY(), Ids::OXEYE_DAISY);
1034 $this->mapSimple(Blocks::POPPY(), Ids::POPPY);
1035 $this->mapSimple(Blocks::ORANGE_TULIP(), Ids::ORANGE_TULIP);
1036 $this->mapSimple(Blocks::PINK_TULIP(), Ids::PINK_TULIP);
1037 $this->mapSimple(Blocks::RED_TULIP(), Ids::RED_TULIP);
1038 $this->mapSimple(Blocks::WHITE_TULIP(), Ids::WHITE_TULIP);
1039 }
1040
1041 private function registerSerializers() : void{
1042 $this->map(Blocks::ACTIVATOR_RAIL(), function(ActivatorRail $block) : Writer{
1043 return Writer::create(Ids::ACTIVATOR_RAIL)
1044 ->writeBool(StateNames::RAIL_DATA_BIT, $block->isPowered())
1045 ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
1046 });
1047 $this->map(Blocks::ALL_SIDED_MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK)
1048 ->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM));
1049 $this->map(Blocks::AMETHYST_CLUSTER(), fn(AmethystCluster $block) => Writer::create(
1050 match($stage = $block->getStage()){
1051 AmethystCluster::STAGE_SMALL_BUD => Ids::SMALL_AMETHYST_BUD,
1052 AmethystCluster::STAGE_MEDIUM_BUD => Ids::MEDIUM_AMETHYST_BUD,
1053 AmethystCluster::STAGE_LARGE_BUD => Ids::LARGE_AMETHYST_BUD,
1054 AmethystCluster::STAGE_CLUSTER => Ids::AMETHYST_CLUSTER,
1055 default => throw new BlockStateSerializeException("Invalid Amethyst Cluster stage $stage"),
1056 })
1057 ->writeBlockFace($block->getFacing())
1058 );
1059 $this->map(Blocks::ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_ANDESITE));
1060 $this->map(Blocks::ANDESITE_STAIRS(), fn(Stair $block) => Helper::encodeStairs($block, new Writer(Ids::ANDESITE_STAIRS)));
1061 $this->map(Blocks::ANDESITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_ANDESITE));
1062 $this->map(Blocks::ANVIL(), function(Anvil $block) : Writer{
1063 return Writer::create(Ids::ANVIL)
1064 ->writeCardinalHorizontalFacing($block->getFacing())
1065 ->writeString(StateNames::DAMAGE, match($damage = $block->getDamage()){
1066 0 => StringValues::DAMAGE_UNDAMAGED,
1067 1 => StringValues::DAMAGE_SLIGHTLY_DAMAGED,
1068 2 => StringValues::DAMAGE_VERY_DAMAGED,
1069 default => throw new BlockStateSerializeException("Invalid Anvil damage {$damage}"),
1070 });
1071 });
1072 $this->map(Blocks::BAMBOO(), function(Bamboo $block) : Writer{
1073 return Writer::create(Ids::BAMBOO)
1074 ->writeBool(StateNames::AGE_BIT, $block->isReady())
1075 ->writeString(StateNames::BAMBOO_LEAF_SIZE, match($block->getLeafSize()){
1076 Bamboo::NO_LEAVES => StringValues::BAMBOO_LEAF_SIZE_NO_LEAVES,
1077 Bamboo::SMALL_LEAVES => StringValues::BAMBOO_LEAF_SIZE_SMALL_LEAVES,
1078 Bamboo::LARGE_LEAVES => StringValues::BAMBOO_LEAF_SIZE_LARGE_LEAVES,
1079 default => throw new BlockStateSerializeException("Invalid Bamboo leaf thickness " . $block->getLeafSize()),
1080 })
1081 ->writeString(StateNames::BAMBOO_STALK_THICKNESS, $block->isThick() ? StringValues::BAMBOO_STALK_THICKNESS_THICK : StringValues::BAMBOO_STALK_THICKNESS_THIN);
1082 });
1083 $this->map(Blocks::BAMBOO_SAPLING(), function(BambooSapling $block) : Writer{
1084 return Writer::create(Ids::BAMBOO_SAPLING)
1085 ->writeBool(StateNames::AGE_BIT, $block->isReady());
1086 });
1087 $this->map(Blocks::BANNER(), function(FloorBanner $block) : Writer{
1088 return Writer::create(Ids::STANDING_BANNER)
1089 ->writeInt(StateNames::GROUND_SIGN_DIRECTION, $block->getRotation());
1090 });
1091 $this->map(Blocks::BARREL(), function(Barrel $block) : Writer{
1092 return Writer::create(Ids::BARREL)
1093 ->writeBool(StateNames::OPEN_BIT, $block->isOpen())
1094 ->writeFacingDirection($block->getFacing());
1095 });
1096 $this->map(Blocks::BASALT(), function(SimplePillar $block) : Writer{
1097 return Writer::create(Ids::BASALT)
1098 ->writePillarAxis($block->getAxis());
1099 });
1100 $this->map(Blocks::BED(), function(Bed $block) : Writer{
1101 return Writer::create(Ids::BED)
1102 ->writeBool(StateNames::HEAD_PIECE_BIT, $block->isHeadPart())
1103 ->writeBool(StateNames::OCCUPIED_BIT, $block->isOccupied())
1104 ->writeLegacyHorizontalFacing($block->getFacing());
1105 });
1106 $this->map(Blocks::BEDROCK(), function(Block $block) : Writer{
1107 return Writer::create(Ids::BEDROCK)
1108 ->writeBool(StateNames::INFINIBURN_BIT, $block->burnsForever());
1109 });
1110 $this->map(Blocks::BEETROOTS(), fn(Beetroot $block) => Helper::encodeCrops($block, new Writer(Ids::BEETROOT)));
1111 $this->map(Blocks::BELL(), function(Bell $block) : Writer{
1112 return Writer::create(Ids::BELL)
1113 ->writeBellAttachmentType($block->getAttachmentType())
1114 ->writeBool(StateNames::TOGGLE_BIT, false) //we don't care about this; it's just to keep MCPE happy
1115 ->writeLegacyHorizontalFacing($block->getFacing());
1116
1117 });
1118 $this->map(Blocks::BIG_DRIPLEAF_HEAD(), function(BigDripleafHead $block) : Writer{
1119 return Writer::create(Ids::BIG_DRIPLEAF)
1120 ->writeCardinalHorizontalFacing($block->getFacing())
1121 ->writeString(StateNames::BIG_DRIPLEAF_TILT, match($block->getLeafState()){
1122 DripleafState::STABLE => StringValues::BIG_DRIPLEAF_TILT_NONE,
1123 DripleafState::UNSTABLE => StringValues::BIG_DRIPLEAF_TILT_UNSTABLE,
1124 DripleafState::PARTIAL_TILT => StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT,
1125 DripleafState::FULL_TILT => StringValues::BIG_DRIPLEAF_TILT_FULL_TILT,
1126 })
1127 ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, true);
1128 });
1129 $this->map(Blocks::BIG_DRIPLEAF_STEM(), function(BigDripleafStem $block) : Writer{
1130 return Writer::create(Ids::BIG_DRIPLEAF)
1131 ->writeCardinalHorizontalFacing($block->getFacing())
1132 ->writeString(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE)
1133 ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, false);
1134 });
1135 $this->mapSlab(Blocks::BLACKSTONE_SLAB(), Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB);
1136 $this->mapStairs(Blocks::BLACKSTONE_STAIRS(), Ids::BLACKSTONE_STAIRS);
1137 $this->map(Blocks::BLACKSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::BLACKSTONE_WALL)));
1138 $this->map(Blocks::BLAST_FURNACE(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::BLAST_FURNACE, Ids::LIT_BLAST_FURNACE));
1139 $this->map(Blocks::BLUE_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, false, Writer::create(Ids::COLORED_TORCH_BP)));
1140 $this->map(Blocks::BONE_BLOCK(), function(BoneBlock $block) : Writer{
1141 return Writer::create(Ids::BONE_BLOCK)
1142 ->writeInt(StateNames::DEPRECATED, 0)
1143 ->writePillarAxis($block->getAxis());
1144 });
1145 $this->map(Blocks::BREWING_STAND(), function(BrewingStand $block) : Writer{
1146 return Writer::create(Ids::BREWING_STAND)
1147 ->writeBool(StateNames::BREWING_STAND_SLOT_A_BIT, $block->hasSlot(BrewingStandSlot::EAST))
1148 ->writeBool(StateNames::BREWING_STAND_SLOT_B_BIT, $block->hasSlot(BrewingStandSlot::SOUTHWEST))
1149 ->writeBool(StateNames::BREWING_STAND_SLOT_C_BIT, $block->hasSlot(BrewingStandSlot::NORTHWEST));
1150 });
1151 $this->map(Blocks::BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::BRICK_SLAB, StringValues::STONE_SLAB_TYPE_BRICK));
1152 $this->mapStairs(Blocks::BRICK_STAIRS(), Ids::BRICK_STAIRS);
1153 $this->map(Blocks::BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_BRICK));
1154 $this->map(Blocks::BROWN_MUSHROOM_BLOCK(), fn(BrownMushroomBlock $block) => Helper::encodeMushroomBlock($block, new Writer(Ids::BROWN_MUSHROOM_BLOCK)));
1155 $this->map(Blocks::CACTUS(), function(Cactus $block) : Writer{
1156 return Writer::create(Ids::CACTUS)
1157 ->writeInt(StateNames::AGE, $block->getAge());
1158 });
1159 $this->map(Blocks::CAKE(), function(Cake $block) : Writer{
1160 return Writer::create(Ids::CAKE)
1161 ->writeInt(StateNames::BITE_COUNTER, $block->getBites());
1162 });
1163 $this->map(Blocks::CARROTS(), fn(Carrot $block) => Helper::encodeCrops($block, new Writer(Ids::CARROTS)));
1164 $this->map(Blocks::CARVED_PUMPKIN(), function(CarvedPumpkin $block) : Writer{
1165 return Writer::create(Ids::CARVED_PUMPKIN)
1166 ->writeCardinalHorizontalFacing($block->getFacing());
1167 });
1168 $this->map(Blocks::CAVE_VINES(), function(CaveVines $block) : Writer{
1169 //I have no idea why this only has 3 IDs - there are 4 in Java and 4 visually distinct states in Bedrock
1170 return Writer::create($block->hasBerries() ?
1171 ($block->isHead() ?
1172 Ids::CAVE_VINES_HEAD_WITH_BERRIES :
1173 Ids::CAVE_VINES_BODY_WITH_BERRIES
1174 ) :
1175 Ids::CAVE_VINES
1176 )
1177 ->writeInt(StateNames::GROWING_PLANT_AGE, $block->getAge());
1178 });
1179 $this->map(Blocks::CHAIN(), function(Chain $block) : Writer{
1180 return Writer::create(Ids::CHAIN)
1181 ->writePillarAxis($block->getAxis());
1182 });
1183 $this->map(Blocks::CHEST(), function(Chest $block) : Writer{
1184 return Writer::create(Ids::CHEST)
1185 ->writeCardinalHorizontalFacing($block->getFacing());
1186 });
1187 $this->map(Blocks::CHISELED_BOOKSHELF(), function(ChiseledBookshelf $block) : Writer{
1188 $flags = 0;
1189 foreach($block->getSlots() as $slot){
1190 $flags |= 1 << $slot->value;
1191 }
1192 return Writer::create(Ids::CHISELED_BOOKSHELF)
1193 ->writeLegacyHorizontalFacing($block->getFacing())
1194 ->writeInt(StateNames::BOOKS_STORED, $flags);
1195 });
1196 $this->map(Blocks::CHISELED_QUARTZ(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_CHISELED, $block->getAxis()));
1197 $this->map(Blocks::CHISELED_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_HEIROGLYPHS));
1198 $this->map(Blocks::CHISELED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_HEIROGLYPHS));
1199 $this->map(Blocks::CHISELED_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_CHISELED));
1200 $this->map(Blocks::CHORUS_FLOWER(), function(ChorusFlower $block) : Writer{
1201 return Writer::create(Ids::CHORUS_FLOWER)
1202 ->writeInt(StateNames::AGE, $block->getAge());
1203 });
1204 $this->mapSlab(Blocks::COBBLED_DEEPSLATE_SLAB(), Ids::COBBLED_DEEPSLATE_SLAB, Ids::COBBLED_DEEPSLATE_DOUBLE_SLAB);
1205 $this->mapStairs(Blocks::COBBLED_DEEPSLATE_STAIRS(), Ids::COBBLED_DEEPSLATE_STAIRS);
1206 $this->map(Blocks::COBBLED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::COBBLED_DEEPSLATE_WALL)));
1207 $this->map(Blocks::COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::COBBLESTONE_SLAB, StringValues::STONE_SLAB_TYPE_COBBLESTONE));
1208 $this->mapStairs(Blocks::COBBLESTONE_STAIRS(), Ids::STONE_STAIRS);
1209 $this->map(Blocks::COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_COBBLESTONE));
1210 $this->map(Blocks::COPPER(), function(Copper $block) : Writer{
1211 $oxidation = $block->getOxidation();
1212 return new Writer($block->isWaxed() ?
1213 Helper::selectCopperId($oxidation, Ids::WAXED_COPPER, Ids::WAXED_EXPOSED_COPPER, Ids::WAXED_WEATHERED_COPPER, Ids::WAXED_OXIDIZED_COPPER) :
1214 Helper::selectCopperId($oxidation, Ids::COPPER_BLOCK, Ids::EXPOSED_COPPER, Ids::WEATHERED_COPPER, Ids::OXIDIZED_COPPER)
1215 );
1216 });
1217 $this->map(Blocks::CUT_COPPER(), function(Copper $block) : Writer{
1218 $oxidation = $block->getOxidation();
1219 return new Writer($block->isWaxed() ?
1220 Helper::selectCopperId($oxidation, Ids::WAXED_CUT_COPPER, Ids::WAXED_EXPOSED_CUT_COPPER, Ids::WAXED_WEATHERED_CUT_COPPER, Ids::WAXED_OXIDIZED_CUT_COPPER) :
1221 Helper::selectCopperId($oxidation, Ids::CUT_COPPER, Ids::EXPOSED_CUT_COPPER, Ids::WEATHERED_CUT_COPPER, Ids::OXIDIZED_CUT_COPPER)
1222 );
1223 });
1224 $this->map(Blocks::CUT_COPPER_SLAB(), function(CopperSlab $block) : Writer{
1225 $oxidation = $block->getOxidation();
1226 return Helper::encodeSlab(
1227 $block,
1228 ($block->isWaxed() ?
1229 Helper::selectCopperId(
1230 $oxidation,
1231 Ids::WAXED_CUT_COPPER_SLAB,
1232 Ids::WAXED_EXPOSED_CUT_COPPER_SLAB,
1233 Ids::WAXED_WEATHERED_CUT_COPPER_SLAB,
1234 Ids::WAXED_OXIDIZED_CUT_COPPER_SLAB
1235 ) :
1236 Helper::selectCopperId(
1237 $oxidation,
1238 Ids::CUT_COPPER_SLAB,
1239 Ids::EXPOSED_CUT_COPPER_SLAB,
1240 Ids::WEATHERED_CUT_COPPER_SLAB,
1241 Ids::OXIDIZED_CUT_COPPER_SLAB
1242 )
1243 ),
1244 ($block->isWaxed() ?
1245 Helper::selectCopperId(
1246 $oxidation,
1247 Ids::WAXED_DOUBLE_CUT_COPPER_SLAB,
1248 Ids::WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB,
1249 Ids::WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB,
1250 Ids::WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB
1251 ) :
1252 Helper::selectCopperId(
1253 $oxidation,
1254 Ids::DOUBLE_CUT_COPPER_SLAB,
1255 Ids::EXPOSED_DOUBLE_CUT_COPPER_SLAB,
1256 Ids::WEATHERED_DOUBLE_CUT_COPPER_SLAB,
1257 Ids::OXIDIZED_DOUBLE_CUT_COPPER_SLAB
1258 )
1259 )
1260 );
1261 });
1262 $this->map(Blocks::CUT_COPPER_STAIRS(), function(CopperStairs $block) : Writer{
1263 $oxidation = $block->getOxidation();
1264 return Helper::encodeStairs(
1265 $block,
1266 new Writer($block->isWaxed() ?
1267 Helper::selectCopperId(
1268 $oxidation,
1269 Ids::WAXED_CUT_COPPER_STAIRS,
1270 Ids::WAXED_EXPOSED_CUT_COPPER_STAIRS,
1271 Ids::WAXED_WEATHERED_CUT_COPPER_STAIRS,
1272 Ids::WAXED_OXIDIZED_CUT_COPPER_STAIRS
1273 ) :
1274 Helper::selectCopperId(
1275 $oxidation,
1276 Ids::CUT_COPPER_STAIRS,
1277 Ids::EXPOSED_CUT_COPPER_STAIRS,
1278 Ids::WEATHERED_CUT_COPPER_STAIRS,
1279 Ids::OXIDIZED_CUT_COPPER_STAIRS
1280 )
1281 )
1282 );
1283 });
1284 $this->map(Blocks::COCOA_POD(), function(CocoaBlock $block) : Writer{
1285 return Writer::create(Ids::COCOA)
1286 ->writeInt(StateNames::AGE, $block->getAge())
1287 ->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
1288 });
1289 $this->map(Blocks::COMPOUND_CREATOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR, new Writer(Ids::CHEMISTRY_TABLE)));
1290 $this->map(Blocks::CRACKED_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_CRACKED));
1291 $this->map(Blocks::CUT_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
1292 $this->map(Blocks::CUT_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE));
1293 $this->map(Blocks::CUT_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
1294 $this->map(Blocks::CUT_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_SANDSTONE));
1295 $this->map(Blocks::DARK_PRISMARINE(), fn() => Writer::create(Ids::PRISMARINE)
1296 ->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_DARK));
1297 $this->map(Blocks::DARK_PRISMARINE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_DARK));
1298 $this->mapStairs(Blocks::DARK_PRISMARINE_STAIRS(), Ids::DARK_PRISMARINE_STAIRS);
1299 $this->map(Blocks::DAYLIGHT_SENSOR(), function(DaylightSensor $block) : Writer{
1300 return Writer::create($block->isInverted() ? Ids::DAYLIGHT_DETECTOR_INVERTED : Ids::DAYLIGHT_DETECTOR)
1301 ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
1302 });
1303 $this->map(Blocks::DEEPSLATE(), function(SimplePillar $block) : Writer{
1304 return Writer::create(Ids::DEEPSLATE)
1305 ->writePillarAxis($block->getAxis());
1306 });
1307 $this->mapSlab(Blocks::DEEPSLATE_BRICK_SLAB(), Ids::DEEPSLATE_BRICK_SLAB, Ids::DEEPSLATE_BRICK_DOUBLE_SLAB);
1308 $this->mapStairs(Blocks::DEEPSLATE_BRICK_STAIRS(), Ids::DEEPSLATE_BRICK_STAIRS);
1309 $this->map(Blocks::DEEPSLATE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::DEEPSLATE_BRICK_WALL)));
1310 $this->map(Blocks::DEEPSLATE_REDSTONE_ORE(), fn(RedstoneOre $block) => new Writer($block->isLit() ? Ids::LIT_DEEPSLATE_REDSTONE_ORE : Ids::DEEPSLATE_REDSTONE_ORE));
1311 $this->mapSlab(Blocks::DEEPSLATE_TILE_SLAB(), Ids::DEEPSLATE_TILE_SLAB, Ids::DEEPSLATE_TILE_DOUBLE_SLAB);
1312 $this->mapStairs(Blocks::DEEPSLATE_TILE_STAIRS(), Ids::DEEPSLATE_TILE_STAIRS);
1313 $this->map(Blocks::DEEPSLATE_TILE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::DEEPSLATE_TILE_WALL)));
1314 $this->map(Blocks::DETECTOR_RAIL(), function(DetectorRail $block) : Writer{
1315 return Writer::create(Ids::DETECTOR_RAIL)
1316 ->writeBool(StateNames::RAIL_DATA_BIT, $block->isActivated())
1317 ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
1318 });
1319 $this->map(Blocks::DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_DIORITE));
1320 $this->mapStairs(Blocks::DIORITE_STAIRS(), Ids::DIORITE_STAIRS);
1321 $this->map(Blocks::DIORITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_DIORITE));
1322 $this->map(Blocks::DIRT(), function(Dirt $block) : Writer{
1323 $dirtType = $block->getDirtType();
1324 if($dirtType === DirtType::ROOTED){
1325 return new Writer(Ids::DIRT_WITH_ROOTS);
1326 }
1327 return Writer::create(Ids::DIRT)
1328 ->writeString(StateNames::DIRT_TYPE, match($dirtType){
1329 DirtType::COARSE => StringValues::DIRT_TYPE_COARSE,
1330 DirtType::NORMAL => StringValues::DIRT_TYPE_NORMAL,
1331 //ROOTED was already checked above
1332 });
1333 });
1334 $this->map(Blocks::DOUBLE_TALLGRASS(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::TALL_GRASS)));
1335 $this->map(Blocks::ELEMENT_CONSTRUCTOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR, new Writer(Ids::CHEMISTRY_TABLE)));
1336 $this->map(Blocks::ENDER_CHEST(), function(EnderChest $block) : Writer{
1337 return Writer::create(Ids::ENDER_CHEST)
1338 ->writeCardinalHorizontalFacing($block->getFacing());
1339 });
1340 $this->map(Blocks::END_PORTAL_FRAME(), function(EndPortalFrame $block) : Writer{
1341 return Writer::create(Ids::END_PORTAL_FRAME)
1342 ->writeBool(StateNames::END_PORTAL_EYE_BIT, $block->hasEye())
1343 ->writeCardinalHorizontalFacing($block->getFacing());
1344 });
1345 $this->map(Blocks::END_ROD(), function(EndRod $block) : Writer{
1346 return Writer::create(Ids::END_ROD)
1347 ->writeEndRodFacingDirection($block->getFacing());
1348 });
1349 $this->map(Blocks::END_STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_END_STONE_BRICK));
1350 $this->mapStairs(Blocks::END_STONE_BRICK_STAIRS(), Ids::END_BRICK_STAIRS);
1351 $this->map(Blocks::END_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_END_BRICK));
1352 $this->map(Blocks::FAKE_WOODEN_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::PETRIFIED_OAK_SLAB, StringValues::STONE_SLAB_TYPE_WOOD));
1353 $this->map(Blocks::FARMLAND(), function(Farmland $block) : Writer{
1354 return Writer::create(Ids::FARMLAND)
1355 ->writeInt(StateNames::MOISTURIZED_AMOUNT, $block->getWetness());
1356 });
1357 $this->map(Blocks::FIRE(), function(Fire $block) : Writer{
1358 return Writer::create(Ids::FIRE)
1359 ->writeInt(StateNames::AGE, $block->getAge());
1360 });
1361 $this->map(Blocks::FLOWER_POT(), function() : Writer{
1362 return Writer::create(Ids::FLOWER_POT)
1363 ->writeBool(StateNames::UPDATE_BIT, false); //to keep MCPE happy
1364 });
1365 $this->map(Blocks::FROGLIGHT(), function(Froglight $block){
1366 return Writer::create(match($block->getFroglightType()){
1367 FroglightType::OCHRE => Ids::OCHRE_FROGLIGHT,
1368 FroglightType::PEARLESCENT => Ids::PEARLESCENT_FROGLIGHT,
1369 FroglightType::VERDANT => Ids::VERDANT_FROGLIGHT,
1370 })
1371 ->writePillarAxis($block->getAxis());
1372 });
1373 $this->map(Blocks::FROSTED_ICE(), function(FrostedIce $block) : Writer{
1374 return Writer::create(Ids::FROSTED_ICE)
1375 ->writeInt(StateNames::AGE, $block->getAge());
1376 });
1377 $this->map(Blocks::FURNACE(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::FURNACE, Ids::LIT_FURNACE));
1378 $this->map(Blocks::GLOW_LICHEN(), function(GlowLichen $block) : Writer{
1379 return Writer::create(Ids::GLOW_LICHEN)
1380 ->writeFacingFlags($block->getFaces());
1381 });
1382 $this->map(Blocks::GLOWING_ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::GLOW_FRAME));
1383 $this->map(Blocks::GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_GRANITE));
1384 $this->mapStairs(Blocks::GRANITE_STAIRS(), Ids::GRANITE_STAIRS);
1385 $this->map(Blocks::GRANITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_GRANITE));
1386 $this->map(Blocks::GREEN_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, true, Writer::create(Ids::COLORED_TORCH_RG)));
1387 $this->map(Blocks::HAY_BALE(), function(HayBale $block) : Writer{
1388 return Writer::create(Ids::HAY_BLOCK)
1389 ->writeInt(StateNames::DEPRECATED, 0)
1390 ->writePillarAxis($block->getAxis());
1391 });
1392 $this->map(Blocks::HOPPER(), function(Hopper $block) : Writer{
1393 return Writer::create(Ids::HOPPER)
1394 ->writeBool(StateNames::TOGGLE_BIT, $block->isPowered())
1395 ->writeFacingWithoutUp($block->getFacing());
1396 });
1397 $this->map(Blocks::INFESTED_CHISELED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
1398 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK));
1399 $this->map(Blocks::INFESTED_COBBLESTONE(), fn() => Writer::create(Ids::MONSTER_EGG)
1400 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_COBBLESTONE));
1401 $this->map(Blocks::INFESTED_CRACKED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
1402 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK));
1403 $this->map(Blocks::INFESTED_MOSSY_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
1404 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_MOSSY_STONE_BRICK));
1405 $this->map(Blocks::INFESTED_STONE(), fn() => Writer::create(Ids::MONSTER_EGG)
1406 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_STONE));
1407 $this->map(Blocks::INFESTED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
1408 ->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_STONE_BRICK));
1409 $this->map(Blocks::IRON_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::IRON_DOOR)));
1410 $this->map(Blocks::IRON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::IRON_TRAPDOOR)));
1411 $this->map(Blocks::ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::FRAME));
1412 $this->map(Blocks::LAB_TABLE(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_LAB_TABLE, new Writer(Ids::CHEMISTRY_TABLE)));
1413 $this->map(Blocks::LADDER(), function(Ladder $block) : Writer{
1414 return Writer::create(Ids::LADDER)
1415 ->writeHorizontalFacing($block->getFacing());
1416 });
1417 $this->map(Blocks::LANTERN(), function(Lantern $block) : Writer{
1418 return Writer::create(Ids::LANTERN)
1419 ->writeBool(StateNames::HANGING, $block->isHanging());
1420 });
1421 $this->map(Blocks::LARGE_FERN(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LARGE_FERN)));
1422 $this->map(Blocks::LAVA(), fn(Lava $block) => Helper::encodeLiquid($block, Ids::LAVA, Ids::FLOWING_LAVA));
1423 $this->map(Blocks::LECTERN(), function(Lectern $block) : Writer{
1424 return Writer::create(Ids::LECTERN)
1425 ->writeBool(StateNames::POWERED_BIT, $block->isProducingSignal())
1426 ->writeCardinalHorizontalFacing($block->getFacing());
1427 });
1428 $this->map(Blocks::LEVER(), function(Lever $block) : Writer{
1429 return Writer::create(Ids::LEVER)
1430 ->writeBool(StateNames::OPEN_BIT, $block->isActivated())
1431 ->writeString(StateNames::LEVER_DIRECTION, match($block->getFacing()){
1432 LeverFacing::DOWN_AXIS_Z => StringValues::LEVER_DIRECTION_DOWN_NORTH_SOUTH,
1433 LeverFacing::DOWN_AXIS_X => StringValues::LEVER_DIRECTION_DOWN_EAST_WEST,
1434 LeverFacing::UP_AXIS_Z => StringValues::LEVER_DIRECTION_UP_NORTH_SOUTH,
1435 LeverFacing::UP_AXIS_X => StringValues::LEVER_DIRECTION_UP_EAST_WEST,
1436 LeverFacing::NORTH => StringValues::LEVER_DIRECTION_NORTH,
1437 LeverFacing::SOUTH => StringValues::LEVER_DIRECTION_SOUTH,
1438 LeverFacing::WEST => StringValues::LEVER_DIRECTION_WEST,
1439 LeverFacing::EAST => StringValues::LEVER_DIRECTION_EAST,
1440 });
1441 });
1442 $this->map(Blocks::LIGHT(), function(Light $block) : Writer{
1443 return Writer::create(Ids::LIGHT_BLOCK)
1444 ->writeInt(StateNames::BLOCK_LIGHT_LEVEL, $block->getLightLevel());
1445 });
1446 $this->map(Blocks::LIGHTNING_ROD(), function(LightningRod $block) : Writer{
1447 return Writer::create(Ids::LIGHTNING_ROD)
1448 ->writeFacingDirection($block->getFacing());
1449 });
1450 $this->map(Blocks::LILAC(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LILAC)));
1451 $this->map(Blocks::LIT_PUMPKIN(), function(LitPumpkin $block) : Writer{
1452 return Writer::create(Ids::LIT_PUMPKIN)
1453 ->writeCardinalHorizontalFacing($block->getFacing());
1454 });
1455 $this->map(Blocks::LOOM(), function(Loom $block) : Writer{
1456 return Writer::create(Ids::LOOM)
1457 ->writeLegacyHorizontalFacing($block->getFacing());
1458 });
1459 $this->map(Blocks::MATERIAL_REDUCER(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_MATERIAL_REDUCER, new Writer(Ids::CHEMISTRY_TABLE)));
1460 $this->map(Blocks::MELON_STEM(), fn(MelonStem $block) => Helper::encodeStem($block, new Writer(Ids::MELON_STEM)));
1461 $this->map(Blocks::MOB_HEAD(), function(MobHead $block) : Writer{
1462 return Writer::create(Ids::SKULL)
1463 ->writeFacingWithoutDown($block->getFacing());
1464 });
1465 $this->map(Blocks::MOSSY_COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_MOSSY_COBBLESTONE));
1466 $this->mapStairs(Blocks::MOSSY_COBBLESTONE_STAIRS(), Ids::MOSSY_COBBLESTONE_STAIRS);
1467 $this->map(Blocks::MOSSY_COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_MOSSY_COBBLESTONE));
1468 $this->map(Blocks::MOSSY_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_MOSSY));
1469 $this->map(Blocks::MOSSY_STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_MOSSY_STONE_BRICK));
1470 $this->mapStairs(Blocks::MOSSY_STONE_BRICK_STAIRS(), Ids::MOSSY_STONE_BRICK_STAIRS);
1471 $this->map(Blocks::MOSSY_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_MOSSY_STONE_BRICK));
1472 $this->mapSlab(Blocks::MUD_BRICK_SLAB(), Ids::MUD_BRICK_SLAB, Ids::MUD_BRICK_DOUBLE_SLAB);
1473 $this->mapStairs(Blocks::MUD_BRICK_STAIRS(), Ids::MUD_BRICK_STAIRS);
1474 $this->map(Blocks::MUD_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::MUD_BRICK_WALL)));
1475 $this->map(Blocks::MUDDY_MANGROVE_ROOTS(), fn(SimplePillar $block) => Writer::create(Ids::MUDDY_MANGROVE_ROOTS)
1476 ->writePillarAxis($block->getAxis()));
1477 $this->map(Blocks::MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK)
1478 ->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM));
1479 $this->map(Blocks::NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::NETHER_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_NETHER_BRICK));
1480 $this->mapStairs(Blocks::NETHER_BRICK_STAIRS(), Ids::NETHER_BRICK_STAIRS);
1481 $this->map(Blocks::NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_NETHER_BRICK));
1482 $this->map(Blocks::NETHER_PORTAL(), function(NetherPortal $block) : Writer{
1483 return Writer::create(Ids::PORTAL)
1484 ->writeString(StateNames::PORTAL_AXIS, match($block->getAxis()){
1485 Axis::X => StringValues::PORTAL_AXIS_X,
1486 Axis::Z => StringValues::PORTAL_AXIS_Z,
1487 default => throw new BlockStateSerializeException("Invalid Nether Portal axis " . $block->getAxis()),
1488 });
1489 });
1490 $this->map(Blocks::NETHER_WART(), function(NetherWartPlant $block) : Writer{
1491 return Writer::create(Ids::NETHER_WART)
1492 ->writeInt(StateNames::AGE, $block->getAge());
1493 });
1494 $this->map(Blocks::PEONY(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::PEONY)));
1495 $this->map(Blocks::PINK_PETALS(), function(PinkPetals $block) : Writer{
1496 return Writer::create(Ids::PINK_PETALS)
1497 ->writeCardinalHorizontalFacing($block->getFacing())
1498 ->writeInt(StateNames::GROWTH, $block->getCount() - 1);
1499 });
1500 $this->map(Blocks::PITCHER_PLANT(), function(DoublePlant $block) : Writer{
1501 return Writer::create(Ids::PITCHER_PLANT)
1502 ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
1503 });
1504 $this->map(Blocks::PITCHER_CROP(), function(PitcherCrop $block) : Writer{
1505 return Writer::create(Ids::PITCHER_CROP)
1506 ->writeInt(StateNames::GROWTH, $block->getAge())
1507 ->writeBool(StateNames::UPPER_BLOCK_BIT, false);
1508 });
1509 $this->map(Blocks::DOUBLE_PITCHER_CROP(), function(DoublePitcherCrop $block) : Writer{
1510 return Writer::create(Ids::PITCHER_CROP)
1511 ->writeInt(StateNames::GROWTH, $block->getAge() + 1 + PitcherCrop::MAX_AGE)
1512 ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
1513 });
1514 $this->map(Blocks::POLISHED_ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_ANDESITE));
1515 $this->mapStairs(Blocks::POLISHED_ANDESITE_STAIRS(), Ids::POLISHED_ANDESITE_STAIRS);
1516 $this->map(Blocks::POLISHED_BASALT(), function(SimplePillar $block) : Writer{
1517 return Writer::create(Ids::POLISHED_BASALT)
1518 ->writePillarAxis($block->getAxis());
1519 });
1520 $this->mapSlab(Blocks::POLISHED_BLACKSTONE_BRICK_SLAB(), Ids::POLISHED_BLACKSTONE_BRICK_SLAB, Ids::POLISHED_BLACKSTONE_BRICK_DOUBLE_SLAB);
1521 $this->mapStairs(Blocks::POLISHED_BLACKSTONE_BRICK_STAIRS(), Ids::POLISHED_BLACKSTONE_BRICK_STAIRS);
1522 $this->map(Blocks::POLISHED_BLACKSTONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_BLACKSTONE_BRICK_WALL)));
1523 $this->map(Blocks::POLISHED_BLACKSTONE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::POLISHED_BLACKSTONE_BUTTON)));
1524 $this->map(Blocks::POLISHED_BLACKSTONE_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::POLISHED_BLACKSTONE_PRESSURE_PLATE)));
1525 $this->mapSlab(Blocks::POLISHED_BLACKSTONE_SLAB(), Ids::POLISHED_BLACKSTONE_SLAB, Ids::POLISHED_BLACKSTONE_DOUBLE_SLAB);
1526 $this->mapStairs(Blocks::POLISHED_BLACKSTONE_STAIRS(), Ids::POLISHED_BLACKSTONE_STAIRS);
1527 $this->map(Blocks::POLISHED_BLACKSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_BLACKSTONE_WALL)));
1528 $this->mapSlab(Blocks::POLISHED_DEEPSLATE_SLAB(), Ids::POLISHED_DEEPSLATE_SLAB, Ids::POLISHED_DEEPSLATE_DOUBLE_SLAB);
1529 $this->mapStairs(Blocks::POLISHED_DEEPSLATE_STAIRS(), Ids::POLISHED_DEEPSLATE_STAIRS);
1530 $this->map(Blocks::POLISHED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_DEEPSLATE_WALL)));
1531 $this->map(Blocks::POLISHED_DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_DIORITE));
1532 $this->mapStairs(Blocks::POLISHED_DIORITE_STAIRS(), Ids::POLISHED_DIORITE_STAIRS);
1533 $this->map(Blocks::POLISHED_GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_GRANITE));
1534 $this->mapStairs(Blocks::POLISHED_GRANITE_STAIRS(), Ids::POLISHED_GRANITE_STAIRS);
1535 $this->map(Blocks::POTATOES(), fn(Potato $block) => Helper::encodeCrops($block, new Writer(Ids::POTATOES)));
1536 $this->map(Blocks::POWERED_RAIL(), function(PoweredRail $block) : Writer{
1537 return Writer::create(Ids::GOLDEN_RAIL)
1538 ->writeBool(StateNames::RAIL_DATA_BIT, $block->isPowered())
1539 ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
1540 });
1541 $this->map(Blocks::PRISMARINE(), fn() => Writer::create(Ids::PRISMARINE)
1542 ->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_DEFAULT));
1543 $this->map(Blocks::PRISMARINE_BRICKS(), fn() => Writer::create(Ids::PRISMARINE)
1544 ->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_BRICKS));
1545 $this->map(Blocks::PRISMARINE_BRICKS_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_BRICK));
1546 $this->mapStairs(Blocks::PRISMARINE_BRICKS_STAIRS(), Ids::PRISMARINE_BRICKS_STAIRS);
1547 $this->map(Blocks::PRISMARINE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_ROUGH));
1548 $this->mapStairs(Blocks::PRISMARINE_STAIRS(), Ids::PRISMARINE_STAIRS);
1549 $this->map(Blocks::PRISMARINE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_PRISMARINE));
1550 $this->map(Blocks::PUMPKIN(), function() : Writer{
1551 return Writer::create(Ids::PUMPKIN)
1552 ->writeCardinalHorizontalFacing(Facing::SOUTH); //no longer used
1553 });
1554 $this->map(Blocks::PUMPKIN_STEM(), fn(PumpkinStem $block) => Helper::encodeStem($block, new Writer(Ids::PUMPKIN_STEM)));
1555 $this->map(Blocks::PURPLE_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, true, Writer::create(Ids::COLORED_TORCH_BP)));
1556 $this->map(Blocks::PURPUR(), function() : Writer{
1557 return Writer::create(Ids::PURPUR_BLOCK)
1558 ->writeString(StateNames::CHISEL_TYPE, StringValues::CHISEL_TYPE_DEFAULT)
1559 ->writePillarAxis(Axis::Y); //useless, but MCPE wants it
1560 });
1561 $this->map(Blocks::PURPUR_PILLAR(), function(SimplePillar $block) : Writer{
1562 return Writer::create(Ids::PURPUR_BLOCK)
1563 ->writeString(StateNames::CHISEL_TYPE, StringValues::CHISEL_TYPE_LINES)
1564 ->writePillarAxis($block->getAxis());
1565 });
1566 $this->map(Blocks::PURPUR_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PURPUR));
1567 $this->mapStairs(Blocks::PURPUR_STAIRS(), Ids::PURPUR_STAIRS);
1568 $this->map(Blocks::QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_DEFAULT, Axis::Y));
1569 $this->map(Blocks::QUARTZ_PILLAR(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_LINES, $block->getAxis()));
1570 $this->map(Blocks::QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::QUARTZ_SLAB, StringValues::STONE_SLAB_TYPE_QUARTZ));
1571 $this->mapStairs(Blocks::QUARTZ_STAIRS(), Ids::QUARTZ_STAIRS);
1572 $this->map(Blocks::RAIL(), function(Rail $block) : Writer{
1573 return Writer::create(Ids::RAIL)
1574 ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
1575 });
1576 $this->map(Blocks::REDSTONE_COMPARATOR(), function(RedstoneComparator $block) : Writer{
1577 return Writer::create($block->isPowered() ? Ids::POWERED_COMPARATOR : Ids::UNPOWERED_COMPARATOR)
1578 ->writeBool(StateNames::OUTPUT_LIT_BIT, $block->isPowered())
1579 ->writeBool(StateNames::OUTPUT_SUBTRACT_BIT, $block->isSubtractMode())
1580 ->writeCardinalHorizontalFacing($block->getFacing());
1581 });
1582 $this->map(Blocks::REDSTONE_LAMP(), fn(RedstoneLamp $block) => new Writer($block->isPowered() ? Ids::LIT_REDSTONE_LAMP : Ids::REDSTONE_LAMP));
1583 $this->map(Blocks::REDSTONE_ORE(), fn(RedstoneOre $block) => new Writer($block->isLit() ? Ids::LIT_REDSTONE_ORE : Ids::REDSTONE_ORE));
1584 $this->map(Blocks::REDSTONE_REPEATER(), function(RedstoneRepeater $block) : Writer{
1585 return Writer::create($block->isPowered() ? Ids::POWERED_REPEATER : Ids::UNPOWERED_REPEATER)
1586 ->writeCardinalHorizontalFacing($block->getFacing())
1587 ->writeInt(StateNames::REPEATER_DELAY, $block->getDelay() - 1);
1588 });
1589 $this->map(Blocks::REDSTONE_TORCH(), function(RedstoneTorch $block) : Writer{
1590 return Writer::create($block->isLit() ? Ids::REDSTONE_TORCH : Ids::UNLIT_REDSTONE_TORCH)
1591 ->writeTorchFacing($block->getFacing());
1592 });
1593 $this->map(Blocks::REDSTONE_WIRE(), function(RedstoneWire $block) : Writer{
1594 return Writer::create(Ids::REDSTONE_WIRE)
1595 ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
1596 });
1597 $this->map(Blocks::RED_MUSHROOM_BLOCK(), fn(RedMushroomBlock $block) => Helper::encodeMushroomBlock($block, new Writer(Ids::RED_MUSHROOM_BLOCK)));
1598 $this->map(Blocks::RED_NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_RED_NETHER_BRICK));
1599 $this->mapStairs(Blocks::RED_NETHER_BRICK_STAIRS(), Ids::RED_NETHER_BRICK_STAIRS);
1600 $this->map(Blocks::RED_NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_RED_NETHER_BRICK));
1601 $this->map(Blocks::RED_SAND(), fn() => Writer::create(Ids::SAND)
1602 ->writeString(StateNames::SAND_TYPE, StringValues::SAND_TYPE_RED));
1603 $this->map(Blocks::RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_DEFAULT));
1604 $this->map(Blocks::RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_RED_SANDSTONE));
1605 $this->mapStairs(Blocks::RED_SANDSTONE_STAIRS(), Ids::RED_SANDSTONE_STAIRS);
1606 $this->map(Blocks::RED_SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_RED_SANDSTONE));
1607 $this->map(Blocks::RED_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, false, Writer::create(Ids::COLORED_TORCH_RG)));
1608 $this->map(Blocks::ROSE_BUSH(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::ROSE_BUSH)));
1609 $this->map(Blocks::SAND(), fn() => Writer::create(Ids::SAND)
1610 ->writeString(StateNames::SAND_TYPE, StringValues::SAND_TYPE_NORMAL));
1611 $this->map(Blocks::SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_DEFAULT));
1612 $this->map(Blocks::SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SANDSTONE_SLAB, StringValues::STONE_SLAB_TYPE_SANDSTONE));
1613 $this->mapStairs(Blocks::SANDSTONE_STAIRS(), Ids::SANDSTONE_STAIRS);
1614 $this->map(Blocks::SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_SANDSTONE));
1615 $this->map(Blocks::SEA_PICKLE(), function(SeaPickle $block) : Writer{
1616 return Writer::create(Ids::SEA_PICKLE)
1617 ->writeBool(StateNames::DEAD_BIT, !$block->isUnderwater())
1618 ->writeInt(StateNames::CLUSTER_COUNT, $block->getCount() - 1);
1619 });
1620 $this->map(Blocks::SMALL_DRIPLEAF(), function(SmallDripleaf $block) : Writer{
1621 return Writer::create(Ids::SMALL_DRIPLEAF_BLOCK)
1622 ->writeCardinalHorizontalFacing($block->getFacing())
1623 ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
1624 });
1625 $this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER));
1626 $this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_SMOOTH, Axis::Y));
1627 $this->map(Blocks::SMOOTH_QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_SMOOTH_QUARTZ));
1628 $this->mapStairs(Blocks::SMOOTH_QUARTZ_STAIRS(), Ids::SMOOTH_QUARTZ_STAIRS);
1629 $this->map(Blocks::SMOOTH_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_SMOOTH));
1630 $this->map(Blocks::SMOOTH_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_SMOOTH_RED_SANDSTONE));
1631 $this->mapStairs(Blocks::SMOOTH_RED_SANDSTONE_STAIRS(), Ids::SMOOTH_RED_SANDSTONE_STAIRS);
1632 $this->map(Blocks::SMOOTH_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_SMOOTH));
1633 $this->map(Blocks::SMOOTH_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE));
1634 $this->mapStairs(Blocks::SMOOTH_SANDSTONE_STAIRS(), Ids::SMOOTH_SANDSTONE_STAIRS);
1635 $this->map(Blocks::SMOOTH_STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SMOOTH_STONE_SLAB, StringValues::STONE_SLAB_TYPE_SMOOTH_STONE));
1636 $this->map(Blocks::SNOW_LAYER(), function(SnowLayer $block) : Writer{
1637 return Writer::create(Ids::SNOW_LAYER)
1638 ->writeBool(StateNames::COVERED_BIT, false)
1639 ->writeInt(StateNames::HEIGHT, $block->getLayers() - 1);
1640 });
1641 $this->map(Blocks::SOUL_FIRE(), function() : Writer{
1642 return Writer::create(Ids::SOUL_FIRE)
1643 ->writeInt(StateNames::AGE, 0); //useless for soul fire, we don't track it
1644 });
1645 $this->map(Blocks::SOUL_LANTERN(), function(Lantern $block) : Writer{
1646 return Writer::create(Ids::SOUL_LANTERN)
1647 ->writeBool(StateNames::HANGING, $block->isHanging());
1648 });
1649 $this->map(Blocks::SOUL_TORCH(), function(Torch $block) : Writer{
1650 return Writer::create(Ids::SOUL_TORCH)
1651 ->writeTorchFacing($block->getFacing());
1652 });
1653 $this->map(Blocks::SPONGE(), function(Sponge $block) : Writer{
1654 return Writer::create(Ids::SPONGE)
1655 ->writeString(StateNames::SPONGE_TYPE, $block->isWet() ? StringValues::SPONGE_TYPE_WET : StringValues::SPONGE_TYPE_DRY);
1656 });
1657 $this->map(Blocks::STONECUTTER(), fn(Stonecutter $block) => Writer::create(Ids::STONECUTTER_BLOCK)
1658 ->writeCardinalHorizontalFacing($block->getFacing()));
1659 $this->map(Blocks::STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_DEFAULT));
1660 $this->map(Blocks::STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::STONE_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_STONE_BRICK));
1661 $this->mapStairs(Blocks::STONE_BRICK_STAIRS(), Ids::STONE_BRICK_STAIRS);
1662 $this->map(Blocks::STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_STONE_BRICK));
1663 $this->map(Blocks::STONE_BUTTON(), fn(StoneButton $block) => Helper::encodeButton($block, new Writer(Ids::STONE_BUTTON)));
1664 $this->map(Blocks::STONE_PRESSURE_PLATE(), fn(StonePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::STONE_PRESSURE_PLATE)));
1665 $this->map(Blocks::STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_STONE));
1666 $this->mapStairs(Blocks::STONE_STAIRS(), Ids::NORMAL_STONE_STAIRS);
1667 $this->map(Blocks::SUGARCANE(), function(Sugarcane $block) : Writer{
1668 return Writer::create(Ids::REEDS)
1669 ->writeInt(StateNames::AGE, $block->getAge());
1670 });
1671 $this->map(Blocks::SUNFLOWER(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::SUNFLOWER)));
1672 $this->map(Blocks::SWEET_BERRY_BUSH(), function(SweetBerryBush $block) : Writer{
1673 return Writer::create(Ids::SWEET_BERRY_BUSH)
1674 ->writeInt(StateNames::GROWTH, $block->getAge());
1675 });
1676 $this->map(Blocks::TNT(), function(TNT $block) : Writer{
1677 return Writer::create(Ids::TNT)
1678 ->writeBool(StateNames::ALLOW_UNDERWATER_BIT, $block->worksUnderwater())
1679 ->writeBool(StateNames::EXPLODE_BIT, $block->isUnstable());
1680 });
1681 $this->map(Blocks::TORCH(), function(Torch $block) : Writer{
1682 return Writer::create(Ids::TORCH)
1683 ->writeTorchFacing($block->getFacing());
1684 });
1685 $this->map(Blocks::TORCHFLOWER_CROP(), function(TorchflowerCrop $block){
1686 return Writer::create(Ids::TORCHFLOWER_CROP)
1687 ->writeInt(StateNames::GROWTH, $block->isReady() ? 1 : 0);
1688 });
1689 $this->map(Blocks::TRAPPED_CHEST(), function(TrappedChest $block) : Writer{
1690 return Writer::create(Ids::TRAPPED_CHEST)
1691 ->writeCardinalHorizontalFacing($block->getFacing());
1692 });
1693 $this->map(Blocks::TRIPWIRE(), function(Tripwire $block) : Writer{
1694 return Writer::create(Ids::TRIP_WIRE)
1695 ->writeBool(StateNames::ATTACHED_BIT, $block->isConnected())
1696 ->writeBool(StateNames::DISARMED_BIT, $block->isDisarmed())
1697 ->writeBool(StateNames::POWERED_BIT, $block->isTriggered())
1698 ->writeBool(StateNames::SUSPENDED_BIT, $block->isSuspended());
1699 });
1700 $this->map(Blocks::TRIPWIRE_HOOK(), function(TripwireHook $block) : Writer{
1701 return Writer::create(Ids::TRIPWIRE_HOOK)
1702 ->writeBool(StateNames::ATTACHED_BIT, $block->isConnected())
1703 ->writeBool(StateNames::POWERED_BIT, $block->isPowered())
1704 ->writeLegacyHorizontalFacing($block->getFacing());
1705 });
1706 $this->map(Blocks::TWISTING_VINES(), function(NetherVines $block) : Writer{
1707 return Writer::create(Ids::TWISTING_VINES)
1708 ->writeInt(StateNames::TWISTING_VINES_AGE, $block->getAge());
1709 });
1710 $this->map(Blocks::UNDERWATER_TORCH(), function(UnderwaterTorch $block) : Writer{
1711 return Writer::create(Ids::UNDERWATER_TORCH)
1712 ->writeTorchFacing($block->getFacing());
1713 });
1714 $this->map(Blocks::VINES(), function(Vine $block) : Writer{
1715 return Writer::create(Ids::VINE)
1716 ->writeInt(StateNames::VINE_DIRECTION_BITS, ($block->hasFace(Facing::NORTH) ? BlockLegacyMetadata::VINE_FLAG_NORTH : 0) | ($block->hasFace(Facing::SOUTH) ? BlockLegacyMetadata::VINE_FLAG_SOUTH : 0) | ($block->hasFace(Facing::WEST) ? BlockLegacyMetadata::VINE_FLAG_WEST : 0) | ($block->hasFace(Facing::EAST) ? BlockLegacyMetadata::VINE_FLAG_EAST : 0));
1717 });
1718 $this->map(Blocks::WALL_BANNER(), function(WallBanner $block) : Writer{
1719 return Writer::create(Ids::WALL_BANNER)
1720 ->writeHorizontalFacing($block->getFacing());
1721 });
1722 $this->map(Blocks::WALL_CORAL_FAN(), function(WallCoralFan $block) : Writer{
1723 $coralType = $block->getCoralType();
1724 return Writer::create(match($coralType){
1725 CoralType::TUBE, CoralType::BRAIN => Ids::CORAL_FAN_HANG,
1726 CoralType::BUBBLE, CoralType::FIRE => Ids::CORAL_FAN_HANG2,
1727 CoralType::HORN => Ids::CORAL_FAN_HANG3,
1728 })
1729 ->writeBool(StateNames::CORAL_HANG_TYPE_BIT, $coralType === CoralType::BRAIN || $coralType === CoralType::FIRE)
1730 ->writeBool(StateNames::DEAD_BIT, $block->isDead())
1731 ->writeCoralFacing($block->getFacing());
1732 });
1733 $this->map(Blocks::WATER(), fn(Water $block) => Helper::encodeLiquid($block, Ids::WATER, Ids::FLOWING_WATER));
1734 $this->map(Blocks::WEEPING_VINES(), function(NetherVines $block) : Writer{
1735 return Writer::create(Ids::WEEPING_VINES)
1736 ->writeInt(StateNames::WEEPING_VINES_AGE, $block->getAge());
1737 });
1738 $this->map(Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY(), function(WeightedPressurePlateHeavy $block) : Writer{
1739 return Writer::create(Ids::HEAVY_WEIGHTED_PRESSURE_PLATE)
1740 ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
1741 });
1742 $this->map(Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT(), function(WeightedPressurePlateLight $block) : Writer{
1743 return Writer::create(Ids::LIGHT_WEIGHTED_PRESSURE_PLATE)
1744 ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
1745 });
1746 $this->map(Blocks::WHEAT(), fn(Wheat $block) => Helper::encodeCrops($block, new Writer(Ids::WHEAT)));
1747 }
1748}