PocketMine-MP 5.43.2 git-c9e7b3ab9bd2149f206392522e8eb7e9d8d68cfa
Loading...
Searching...
No Matches
CommonTypes.php
1<?php
2
3/*
4 * This file is part of BedrockProtocol.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/BedrockProtocol>
6 *
7 * BedrockProtocol is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13declare(strict_types=1);
14
15namespace pocketmine\network\mcpe\protocol\serializer;
16
17use pmmp\encoding\Byte;
18use pmmp\encoding\ByteBufferReader;
19use pmmp\encoding\ByteBufferWriter;
20use pmmp\encoding\DataDecodeException;
21use pmmp\encoding\LE;
22use pmmp\encoding\VarInt;
62use Ramsey\Uuid\Uuid;
63use Ramsey\Uuid\UuidInterface;
64use function count;
65use function strlen;
66use function strrev;
67use function substr;
68
69final class CommonTypes{
70
71 private function __construct(){
72 //NOOP
73 }
74
76 public static function getString(ByteBufferReader $in) : string{
77 return $in->readByteArray(VarInt::readUnsignedInt($in));
78 }
79
80 public static function putString(ByteBufferWriter $out, string $v) : void{
81 VarInt::writeUnsignedInt($out, strlen($v));
82 $out->writeByteArray($v);
83 }
84
86 public static function getBool(ByteBufferReader $in) : bool{
87 return Byte::readUnsigned($in) !== 0;
88 }
89
90 public static function putBool(ByteBufferWriter $out, bool $v) : void{
91 Byte::writeUnsigned($out, $v ? 1 : 0);
92 }
93
95 public static function getUUID(ByteBufferReader $in) : UuidInterface{
96 //This is two little-endian longs: bytes 7-0 followed by bytes 15-8
97 $p1 = strrev($in->readByteArray(8));
98 $p2 = strrev($in->readByteArray(8));
99 return Uuid::fromBytes($p1 . $p2);
100 }
101
102 public static function putUUID(ByteBufferWriter $out, UuidInterface $uuid) : void{
103 $bytes = $uuid->getBytes();
104 $out->writeByteArray(strrev(substr($bytes, 0, 8)));
105 $out->writeByteArray(strrev(substr($bytes, 8, 8)));
106 }
107
109 public static function getSkin(ByteBufferReader $in) : SkinData{
110 $skinId = self::getString($in);
111 $skinPlayFabId = self::getString($in);
112 $skinResourcePatch = self::getString($in);
113 $skinData = self::getSkinImage($in);
114 $animationCount = LE::readUnsignedInt($in);
115 $animations = [];
116 for($i = 0; $i < $animationCount; ++$i){
117 $skinImage = self::getSkinImage($in);
118 $animationType = LE::readUnsignedInt($in);
119 $animationFrames = LE::readFloat($in);
120 $expressionType = LE::readUnsignedInt($in);
121 $animations[] = new SkinAnimation($skinImage, $animationType, $animationFrames, $expressionType);
122 }
123 $capeData = self::getSkinImage($in);
124 $geometryData = self::getString($in);
125 $geometryDataVersion = self::getString($in);
126 $animationData = self::getString($in);
127 $capeId = self::getString($in);
128 $fullSkinId = self::getString($in);
129 $armSize = self::getString($in);
130 $skinColor = self::getString($in);
131 $personaPieceCount = LE::readUnsignedInt($in);
132 $personaPieces = [];
133 for($i = 0; $i < $personaPieceCount; ++$i){
134 $pieceId = self::getString($in);
135 $pieceType = self::getString($in);
136 $packId = self::getString($in);
137 $isDefaultPiece = self::getBool($in);
138 $productId = self::getString($in);
139 $personaPieces[] = new PersonaSkinPiece($pieceId, $pieceType, $packId, $isDefaultPiece, $productId);
140 }
141 $pieceTintColorCount = LE::readUnsignedInt($in);
142 $pieceTintColors = [];
143 for($i = 0; $i < $pieceTintColorCount; ++$i){
144 $pieceType = self::getString($in);
145 $colorCount = LE::readUnsignedInt($in);
146 $colors = [];
147 for($j = 0; $j < $colorCount; ++$j){
148 $colors[] = self::getString($in);
149 }
150 $pieceTintColors[] = new PersonaPieceTintColor(
151 $pieceType,
152 $colors
153 );
154 }
155
156 $premium = self::getBool($in);
157 $persona = self::getBool($in);
158 $capeOnClassic = self::getBool($in);
159 $isPrimaryUser = self::getBool($in);
160 $override = self::getBool($in);
161
162 return new SkinData(
163 $skinId,
164 $skinPlayFabId,
165 $skinResourcePatch,
166 $skinData,
167 $animations,
168 $capeData,
169 $geometryData,
170 $geometryDataVersion,
171 $animationData,
172 $capeId,
173 $fullSkinId,
174 $armSize,
175 $skinColor,
176 $personaPieces,
177 $pieceTintColors,
178 true,
179 $premium,
180 $persona,
181 $capeOnClassic,
182 $isPrimaryUser,
183 $override,
184 );
185 }
186
187 public static function putSkin(ByteBufferWriter $out, SkinData $skin) : void{
188 self::putString($out, $skin->getSkinId());
189 self::putString($out, $skin->getPlayFabId());
190 self::putString($out, $skin->getResourcePatch());
191 self::putSkinImage($out, $skin->getSkinImage());
192 LE::writeUnsignedInt($out, count($skin->getAnimations()));
193 foreach($skin->getAnimations() as $animation){
194 self::putSkinImage($out, $animation->getImage());
195 LE::writeUnsignedInt($out, $animation->getType());
196 LE::writeFloat($out, $animation->getFrames());
197 LE::writeUnsignedInt($out, $animation->getExpressionType());
198 }
199 self::putSkinImage($out, $skin->getCapeImage());
200 self::putString($out, $skin->getGeometryData());
201 self::putString($out, $skin->getGeometryDataEngineVersion());
202 self::putString($out, $skin->getAnimationData());
203 self::putString($out, $skin->getCapeId());
204 self::putString($out, $skin->getFullSkinId());
205 self::putString($out, $skin->getArmSize());
206 self::putString($out, $skin->getSkinColor());
207 LE::writeUnsignedInt($out, count($skin->getPersonaPieces()));
208 foreach($skin->getPersonaPieces() as $piece){
209 self::putString($out, $piece->getPieceId());
210 self::putString($out, $piece->getPieceType());
211 self::putString($out, $piece->getPackId());
212 self::putBool($out, $piece->isDefaultPiece());
213 self::putString($out, $piece->getProductId());
214 }
215 LE::writeUnsignedInt($out, count($skin->getPieceTintColors()));
216 foreach($skin->getPieceTintColors() as $tint){
217 self::putString($out, $tint->getPieceType());
218 LE::writeUnsignedInt($out, count($tint->getColors()));
219 foreach($tint->getColors() as $color){
220 self::putString($out, $color);
221 }
222 }
223 self::putBool($out, $skin->isPremium());
224 self::putBool($out, $skin->isPersona());
225 self::putBool($out, $skin->isPersonaCapeOnClassic());
226 self::putBool($out, $skin->isPrimaryUser());
227 self::putBool($out, $skin->isOverride());
228 }
229
231 private static function getSkinImage(ByteBufferReader $in) : SkinImage{
232 $width = LE::readUnsignedInt($in);
233 $height = LE::readUnsignedInt($in);
234 $data = self::getString($in);
235 try{
236 return new SkinImage($height, $width, $data);
237 }catch(\InvalidArgumentException $e){
238 throw new PacketDecodeException($e->getMessage(), 0, $e);
239 }
240 }
241
242 private static function putSkinImage(ByteBufferWriter $out, SkinImage $image) : void{
243 LE::writeUnsignedInt($out, $image->getWidth());
244 LE::writeUnsignedInt($out, $image->getHeight());
245 self::putString($out, $image->getData());
246 }
247
253 private static function getItemStackHeader(ByteBufferReader $in) : array{
254 $id = VarInt::readSignedInt($in);
255 if($id === 0){
256 return [0, 0, 0];
257 }
258
259 $count = LE::readUnsignedShort($in);
260 $meta = VarInt::readUnsignedInt($in);
261
262 return [$id, $count, $meta];
263 }
264
265 private static function putItemStackHeader(ByteBufferWriter $out, ItemStack $itemStack) : bool{
266 if($itemStack->getId() === 0){
267 VarInt::writeSignedInt($out, 0);
268 return false;
269 }
270
271 VarInt::writeSignedInt($out, $itemStack->getId());
272 LE::writeUnsignedShort($out, $itemStack->getCount());
273 VarInt::writeUnsignedInt($out, $itemStack->getMeta());
274
275 return true;
276 }
277
279 private static function getItemStackFooter(ByteBufferReader $in, int $id, int $meta, int $count) : ItemStack{
280 $blockRuntimeId = VarInt::readSignedInt($in);
281 $rawExtraData = self::getString($in);
282
283 return new ItemStack($id, $meta, $count, $blockRuntimeId, $rawExtraData);
284 }
285
286 private static function putItemStackFooter(ByteBufferWriter $out, ItemStack $itemStack) : void{
287 VarInt::writeSignedInt($out, $itemStack->getBlockRuntimeId());
288 self::putString($out, $itemStack->getRawExtraData());
289 }
290
295 public static function getItemStackWithoutStackId(ByteBufferReader $in) : ItemStack{
296 [$id, $count, $meta] = self::getItemStackHeader($in);
297
298 return $id !== 0 ? self::getItemStackFooter($in, $id, $meta, $count) : ItemStack::null();
299
300 }
301
302 public static function putItemStackWithoutStackId(ByteBufferWriter $out, ItemStack $itemStack) : void{
303 if(self::putItemStackHeader($out, $itemStack)){
304 self::putItemStackFooter($out, $itemStack);
305 }
306 }
307
309 public static function getItemStackWrapper(ByteBufferReader $in) : ItemStackWrapper{
310 [$id, $count, $meta] = self::getItemStackHeader($in);
311 if($id === 0){
312 return new ItemStackWrapper(0, ItemStack::null());
313 }
314
315 $hasNetId = self::getBool($in);
316 $stackId = $hasNetId ? self::readServerItemStackId($in) : 0;
317
318 $itemStack = self::getItemStackFooter($in, $id, $meta, $count);
319
320 return new ItemStackWrapper($stackId, $itemStack);
321 }
322
323 public static function putItemStackWrapper(ByteBufferWriter $out, ItemStackWrapper $itemStackWrapper) : void{
324 $itemStack = $itemStackWrapper->getItemStack();
325 if(self::putItemStackHeader($out, $itemStack)){
326 $hasNetId = $itemStackWrapper->getStackId() !== 0;
327 self::putBool($out, $hasNetId);
328 if($hasNetId){
329 self::writeServerItemStackId($out, $itemStackWrapper->getStackId());
330 }
331
332 self::putItemStackFooter($out, $itemStack);
333 }
334 }
335
336 public static function getNetworkItemStackDescriptor(ByteBufferReader $in) : ItemStackWrapper{
337 $id = LE::readSignedShort($in);
338 $count = LE::readUnsignedShort($in);
339 $meta = VarInt::readUnsignedInt($in);
340
341 $hasNetId = self::getBool($in);
342 if ($hasNetId) {
343 $variant = VarInt::readUnsignedInt($in);
344 $stackId = VarInt::readSignedInt($in);
345 } else {
346 $variant = 0;
347 $stackId = 0;
348 }
349
350 $blockRuntimeId = VarInt::readUnsignedInt($in);
351 $rawExtraData = self::getString($in);
352
353 return new ItemStackWrapper($stackId, new ItemStack($id, $meta, $count, $blockRuntimeId, $rawExtraData), $variant);
354 }
355
356 public static function putNetworkItemStackDescriptor(ByteBufferWriter $out, ItemStackWrapper $itemStackWrapper) : void{
357 LE::writeSignedShort($out, $itemStackWrapper->getItemStack()->getId());
358 LE::writeUnsignedShort($out, $itemStackWrapper->getItemStack()->getCount());
359 VarInt::writeUnsignedInt($out, $itemStackWrapper->getItemStack()->getMeta());
360
361 self::putBool($out, $hasNetId = $itemStackWrapper->getStackId() !== 0);
362 if($hasNetId){
363 VarInt::writeUnsignedInt($out, $itemStackWrapper->getStackIdVariant());
364 VarInt::writeSignedInt($out, $itemStackWrapper->getStackId());
365 }
366
367 VarInt::writeUnsignedInt($out, $itemStackWrapper->getItemStack()->getBlockRuntimeId());
368 self::putString($out, $itemStackWrapper->getItemStack()->getRawExtraData());
369 }
370
372 public static function getRecipeIngredient(ByteBufferReader $in) : RecipeIngredient{
373 $descriptorType = Byte::readUnsigned($in);
374 $descriptor = match($descriptorType){
375 ItemDescriptorType::INT_ID_META => IntIdMetaItemDescriptor::read($in),
376 ItemDescriptorType::STRING_ID_META => StringIdMetaItemDescriptor::read($in),
377 ItemDescriptorType::TAG => TagItemDescriptor::read($in),
378 ItemDescriptorType::MOLANG => MolangItemDescriptor::read($in),
379 ItemDescriptorType::COMPLEX_ALIAS => ComplexAliasItemDescriptor::read($in),
380 default => null
381 };
382 $count = VarInt::readSignedInt($in);
383
384 return new RecipeIngredient($descriptor, $count);
385 }
386
387 public static function putRecipeIngredient(ByteBufferWriter $out, RecipeIngredient $ingredient) : void{
388 $type = $ingredient->getDescriptor();
389
390 Byte::writeUnsigned($out, $type?->getTypeId() ?? 0);
391 $type?->write($out);
392
393 VarInt::writeSignedInt($out, $ingredient->getCount());
394 }
395
405 public static function getEntityMetadata(ByteBufferReader $in) : array{
406 $count = VarInt::readUnsignedInt($in);
407 $data = [];
408 for($i = 0; $i < $count; ++$i){
409 $key = VarInt::readUnsignedInt($in);
410 $type = VarInt::readUnsignedInt($in);
411
412 $data[$key] = self::readMetadataProperty($in, $type);
413 }
414
415 return $data;
416 }
417
419 private static function readMetadataProperty(ByteBufferReader $in, int $type) : MetadataProperty{
420 return match($type){
421 ByteMetadataProperty::ID => ByteMetadataProperty::read($in),
422 ShortMetadataProperty::ID => ShortMetadataProperty::read($in),
423 IntMetadataProperty::ID => IntMetadataProperty::read($in),
424 FloatMetadataProperty::ID => FloatMetadataProperty::read($in),
425 StringMetadataProperty::ID => StringMetadataProperty::read($in),
426 CompoundTagMetadataProperty::ID => CompoundTagMetadataProperty::read($in),
427 BlockPosMetadataProperty::ID => BlockPosMetadataProperty::read($in),
428 LongMetadataProperty::ID => LongMetadataProperty::read($in),
429 Vec3MetadataProperty::ID => Vec3MetadataProperty::read($in),
430 default => throw new PacketDecodeException("Unknown entity metadata type " . $type),
431 };
432 }
433
441 public static function putEntityMetadata(ByteBufferWriter $out, array $metadata) : void{
442 VarInt::writeUnsignedInt($out, count($metadata));
443 foreach($metadata as $key => $d){
444 VarInt::writeUnsignedInt($out, $key);
445 VarInt::writeUnsignedInt($out, $d->getTypeId());
446 $d->write($out);
447 }
448 }
449
451 public static function getActorUniqueId(ByteBufferReader $in) : int{
452 return VarInt::readSignedLong($in);
453 }
454
455 public static function putActorUniqueId(ByteBufferWriter $out, int $eid) : void{
456 VarInt::writeSignedLong($out, $eid);
457 }
458
460 public static function getActorRuntimeId(ByteBufferReader $in) : int{
461 return VarInt::readUnsignedLong($in);
462 }
463
464 public static function putActorRuntimeId(ByteBufferWriter $out, int $eid) : void{
465 VarInt::writeUnsignedLong($out, $eid);
466 }
467
473 public static function getBlockPosition(ByteBufferReader $in) : BlockPosition{
474 $x = VarInt::readSignedInt($in);
475 $y = VarInt::readSignedInt($in);
476 $z = VarInt::readSignedInt($in);
477 return new BlockPosition($x, $y, $z);
478 }
479
483 public static function putBlockPosition(ByteBufferWriter $out, BlockPosition $blockPosition) : void{
484 VarInt::writeSignedInt($out, $blockPosition->getX());
485 VarInt::writeSignedInt($out, $blockPosition->getY());
486 VarInt::writeSignedInt($out, $blockPosition->getZ());
487 }
488
494 public static function getVector3(ByteBufferReader $in) : Vector3{
495 $x = LE::readFloat($in);
496 $y = LE::readFloat($in);
497 $z = LE::readFloat($in);
498 return new Vector3($x, $y, $z);
499 }
500
506 public static function getVector2(ByteBufferReader $in) : Vector2{
507 $x = LE::readFloat($in);
508 $y = LE::readFloat($in);
509 return new Vector2($x, $y);
510 }
511
520 public static function putVector3Nullable(ByteBufferWriter $out, ?Vector3 $vector) : void{
521 if($vector !== null){
522 self::putVector3($out, $vector);
523 }else{
524 LE::writeFloat($out, 0.0);
525 LE::writeFloat($out, 0.0);
526 LE::writeFloat($out, 0.0);
527 }
528 }
529
533 public static function putVector3(ByteBufferWriter $out, Vector3 $vector) : void{
534 LE::writeFloat($out, $vector->x);
535 LE::writeFloat($out, $vector->y);
536 LE::writeFloat($out, $vector->z);
537 }
538
542 public static function putVector2(ByteBufferWriter $out, Vector2 $vector2) : void{
543 LE::writeFloat($out, $vector2->x);
544 LE::writeFloat($out, $vector2->y);
545 }
546
548 public static function getRotationByte(ByteBufferReader $in) : float{
549 return Byte::readUnsigned($in) * (360 / 256);
550 }
551
552 public static function putRotationByte(ByteBufferWriter $out, float $rotation) : void{
553 Byte::writeUnsigned($out, (int) ($rotation / (360 / 256)));
554 }
555
557 private static function readGameRule(ByteBufferReader $in, int $type, bool $isPlayerModifiable, bool $isStartGame) : GameRule{
558 return match($type){
559 BoolGameRule::ID => BoolGameRule::decode($in, $isPlayerModifiable),
560 IntGameRule::ID => IntGameRule::decode($in, $isPlayerModifiable, $isStartGame),
561 FloatGameRule::ID => FloatGameRule::decode($in, $isPlayerModifiable),
562 default => throw new PacketDecodeException("Unknown gamerule type $type"),
563 };
564 }
565
575 public static function getGameRules(ByteBufferReader $in, bool $isStartGame) : array{
576 $count = VarInt::readUnsignedInt($in);
577 $rules = [];
578 for($i = 0; $i < $count; ++$i){
579 $name = self::getString($in);
580 $isPlayerModifiable = self::getBool($in);
581 $type = VarInt::readUnsignedInt($in);
582 $rules[$name] = self::readGameRule($in, $type, $isPlayerModifiable, $isStartGame);
583 }
584
585 return $rules;
586 }
587
594 public static function putGameRules(ByteBufferWriter $out, array $rules, bool $isStartGame) : void{
595 VarInt::writeUnsignedInt($out, count($rules));
596 foreach($rules as $name => $rule){
597 self::putString($out, $name);
598 self::putBool($out, $rule->isPlayerModifiable());
599 VarInt::writeUnsignedInt($out, $rule->getTypeId());
600 $rule->encode($out, $isStartGame);
601 }
602 }
603
605 public static function getEntityLink(ByteBufferReader $in) : EntityLink{
606 $fromActorUniqueId = self::getActorUniqueId($in);
607 $toActorUniqueId = self::getActorUniqueId($in);
608 $type = Byte::readUnsigned($in);
609 $immediate = self::getBool($in);
610 $causedByRider = self::getBool($in);
611 $vehicleAngularVelocity = LE::readFloat($in);
612 return new EntityLink($fromActorUniqueId, $toActorUniqueId, $type, $immediate, $causedByRider, $vehicleAngularVelocity);
613 }
614
615 public static function putEntityLink(ByteBufferWriter $out, EntityLink $link) : void{
616 self::putActorUniqueId($out, $link->fromActorUniqueId);
617 self::putActorUniqueId($out, $link->toActorUniqueId);
618 Byte::writeUnsigned($out, $link->type);
619 self::putBool($out, $link->immediate);
620 self::putBool($out, $link->causedByRider);
621 LE::writeFloat($out, $link->vehicleAngularVelocity);
622 }
623
625 public static function getCommandOriginData(ByteBufferReader $in) : CommandOriginData{
626 $result = new CommandOriginData();
627
628 $result->type = CommonTypes::getString($in);
629 $result->uuid = self::getUUID($in);
630 $result->requestId = self::getString($in);
631 $result->playerActorUniqueId = LE::readSignedLong($in);
632
633 return $result;
634 }
635
636 public static function putCommandOriginData(ByteBufferWriter $out, CommandOriginData $data) : void{
637 self::putString($out, $data->type);
638 self::putUUID($out, $data->uuid);
639 self::putString($out, $data->requestId);
640 LE::writeSignedLong($out, $data->playerActorUniqueId);
641 }
642
644 public static function getStructureSettings(ByteBufferReader $in) : StructureSettings{
645 $result = new StructureSettings();
646
647 $result->paletteName = self::getString($in);
648
649 $result->ignoreEntities = self::getBool($in);
650 $result->ignoreBlocks = self::getBool($in);
651 $result->allowNonTickingChunks = self::getBool($in);
652
653 $result->dimensions = self::getBlockPosition($in);
654 $result->offset = self::getBlockPosition($in);
655
656 $result->lastTouchedByPlayerID = self::getActorUniqueId($in);
657 $result->rotation = Byte::readUnsigned($in);
658 $result->mirror = Byte::readUnsigned($in);
659 $result->animationMode = Byte::readUnsigned($in);
660 $result->animationSeconds = LE::readFloat($in);
661 $result->integrityValue = LE::readFloat($in);
662 $result->integritySeed = LE::readUnsignedInt($in);
663 $result->pivot = self::getVector3($in);
664
665 return $result;
666 }
667
668 public static function putStructureSettings(ByteBufferWriter $out, StructureSettings $structureSettings) : void{
669 self::putString($out, $structureSettings->paletteName);
670
671 self::putBool($out, $structureSettings->ignoreEntities);
672 self::putBool($out, $structureSettings->ignoreBlocks);
673 self::putBool($out, $structureSettings->allowNonTickingChunks);
674
675 self::putBlockPosition($out, $structureSettings->dimensions);
676 self::putBlockPosition($out, $structureSettings->offset);
677
678 self::putActorUniqueId($out, $structureSettings->lastTouchedByPlayerID);
679 Byte::writeUnsigned($out, $structureSettings->rotation);
680 Byte::writeUnsigned($out, $structureSettings->mirror);
681 Byte::writeUnsigned($out, $structureSettings->animationMode);
682 LE::writeFloat($out, $structureSettings->animationSeconds);
683 LE::writeFloat($out, $structureSettings->integrityValue);
684 LE::writeUnsignedInt($out, $structureSettings->integritySeed);
685 self::putVector3($out, $structureSettings->pivot);
686 }
687
689 public static function getStructureEditorData(ByteBufferReader $in) : StructureEditorData{
690 $result = new StructureEditorData();
691
692 $result->structureName = self::getString($in);
693 $result->filteredStructureName = self::getString($in);
694 $result->structureDataField = self::getString($in);
695
696 $result->includePlayers = self::getBool($in);
697 $result->showBoundingBox = self::getBool($in);
698
699 $result->structureBlockType = VarInt::readSignedInt($in);
700 $result->structureSettings = self::getStructureSettings($in);
701 $result->structureRedstoneSaveMode = VarInt::readSignedInt($in);
702
703 return $result;
704 }
705
706 public static function putStructureEditorData(ByteBufferWriter $out, StructureEditorData $structureEditorData) : void{
707 self::putString($out, $structureEditorData->structureName);
708 self::putString($out, $structureEditorData->filteredStructureName);
709 self::putString($out, $structureEditorData->structureDataField);
710
711 self::putBool($out, $structureEditorData->includePlayers);
712 self::putBool($out, $structureEditorData->showBoundingBox);
713
714 VarInt::writeSignedInt($out, $structureEditorData->structureBlockType);
715 self::putStructureSettings($out, $structureEditorData->structureSettings);
716 VarInt::writeSignedInt($out, $structureEditorData->structureRedstoneSaveMode);
717 }
718
720 public static function getNbtRoot(ByteBufferReader $in) : TreeRoot{
721 $offset = $in->getOffset();
722 try{
723 return (new NetworkNbtSerializer())->read($in->getData(), $offset, 512);
724 }catch(NbtDataException $e){
725 throw PacketDecodeException::wrap($e, "Failed decoding NBT root");
726 }finally{
727 $in->setOffset($offset);
728 }
729 }
730
731 public static function getNbtCompoundRoot(ByteBufferReader $in) : CompoundTag{
732 try{
733 return self::getNbtRoot($in)->mustGetCompoundTag();
734 }catch(NbtDataException $e){
735 throw PacketDecodeException::wrap($e, "Expected TAG_Compound NBT root");
736 }
737 }
738
740 public static function readRecipeNetId(ByteBufferReader $in) : int{
741 return VarInt::readUnsignedInt($in);
742 }
743
744 public static function writeRecipeNetId(ByteBufferWriter $out, int $id) : void{
745 VarInt::writeUnsignedInt($out, $id);
746 }
747
749 public static function readCreativeItemNetId(ByteBufferReader $in) : int{
750 return VarInt::readUnsignedInt($in);
751 }
752
753 public static function writeCreativeItemNetId(ByteBufferWriter $out, int $id) : void{
754 VarInt::writeUnsignedInt($out, $id);
755 }
756
769 public static function readItemStackNetIdVariant(ByteBufferReader $in) : int{
770 return VarInt::readSignedInt($in);
771 }
772
778 public static function writeItemStackNetIdVariant(ByteBufferWriter $out, int $id) : void{
779 VarInt::writeSignedInt($out, $id);
780 }
781
783 public static function readItemStackRequestId(ByteBufferReader $in) : int{
784 return VarInt::readSignedInt($in);
785 }
786
787 public static function writeItemStackRequestId(ByteBufferWriter $out, int $id) : void{
788 VarInt::writeSignedInt($out, $id);
789 }
790
792 public static function readLegacyItemStackRequestId(ByteBufferReader $in) : int{
793 return VarInt::readSignedInt($in);
794 }
795
796 public static function writeLegacyItemStackRequestId(ByteBufferWriter $out, int $id) : void{
797 VarInt::writeSignedInt($out, $id);
798 }
799
801 public static function readServerItemStackId(ByteBufferReader $in) : int{
802 return VarInt::readSignedInt($in);
803 }
804
805 public static function writeServerItemStackId(ByteBufferWriter $out, int $id) : void{
806 VarInt::writeSignedInt($out, $id);
807 }
808
815 public static function readOptional(ByteBufferReader $in, \Closure $reader) : mixed{
816 if(self::getBool($in)){
817 return $reader($in);
818 }
819 return null;
820 }
821
827 public static function writeOptional(ByteBufferWriter $out, mixed $value, \Closure $writer) : void{
828 if($value !== null){
829 self::putBool($out, true);
830 $writer($out, $value);
831 }else{
832 self::putBool($out, false);
833 }
834 }
835}
static putVector3Nullable(ByteBufferWriter $out, ?Vector3 $vector)
static readOptional(ByteBufferReader $in, \Closure $reader)
static writeItemStackNetIdVariant(ByteBufferWriter $out, int $id)
static putGameRules(ByteBufferWriter $out, array $rules, bool $isStartGame)
static putVector2(ByteBufferWriter $out, Vector2 $vector2)
static getGameRules(ByteBufferReader $in, bool $isStartGame)
static writeOptional(ByteBufferWriter $out, mixed $value, \Closure $writer)
static putEntityMetadata(ByteBufferWriter $out, array $metadata)
static putBlockPosition(ByteBufferWriter $out, BlockPosition $blockPosition)
static putVector3(ByteBufferWriter $out, Vector3 $vector)