PocketMine-MP 5.42.2 git-40e2639b20bdc4ddba49d9f7f5fa0d5e92aa266f
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
337 public static function getRecipeIngredient(ByteBufferReader $in) : RecipeIngredient{
338 $descriptorType = Byte::readUnsigned($in);
339 $descriptor = match($descriptorType){
340 ItemDescriptorType::INT_ID_META => IntIdMetaItemDescriptor::read($in),
341 ItemDescriptorType::STRING_ID_META => StringIdMetaItemDescriptor::read($in),
342 ItemDescriptorType::TAG => TagItemDescriptor::read($in),
343 ItemDescriptorType::MOLANG => MolangItemDescriptor::read($in),
344 ItemDescriptorType::COMPLEX_ALIAS => ComplexAliasItemDescriptor::read($in),
345 default => null
346 };
347 $count = VarInt::readSignedInt($in);
348
349 return new RecipeIngredient($descriptor, $count);
350 }
351
352 public static function putRecipeIngredient(ByteBufferWriter $out, RecipeIngredient $ingredient) : void{
353 $type = $ingredient->getDescriptor();
354
355 Byte::writeUnsigned($out, $type?->getTypeId() ?? 0);
356 $type?->write($out);
357
358 VarInt::writeSignedInt($out, $ingredient->getCount());
359 }
360
370 public static function getEntityMetadata(ByteBufferReader $in) : array{
371 $count = VarInt::readUnsignedInt($in);
372 $data = [];
373 for($i = 0; $i < $count; ++$i){
374 $key = VarInt::readUnsignedInt($in);
375 $type = VarInt::readUnsignedInt($in);
376
377 $data[$key] = self::readMetadataProperty($in, $type);
378 }
379
380 return $data;
381 }
382
384 private static function readMetadataProperty(ByteBufferReader $in, int $type) : MetadataProperty{
385 return match($type){
386 ByteMetadataProperty::ID => ByteMetadataProperty::read($in),
387 ShortMetadataProperty::ID => ShortMetadataProperty::read($in),
388 IntMetadataProperty::ID => IntMetadataProperty::read($in),
389 FloatMetadataProperty::ID => FloatMetadataProperty::read($in),
390 StringMetadataProperty::ID => StringMetadataProperty::read($in),
391 CompoundTagMetadataProperty::ID => CompoundTagMetadataProperty::read($in),
392 BlockPosMetadataProperty::ID => BlockPosMetadataProperty::read($in),
393 LongMetadataProperty::ID => LongMetadataProperty::read($in),
394 Vec3MetadataProperty::ID => Vec3MetadataProperty::read($in),
395 default => throw new PacketDecodeException("Unknown entity metadata type " . $type),
396 };
397 }
398
406 public static function putEntityMetadata(ByteBufferWriter $out, array $metadata) : void{
407 VarInt::writeUnsignedInt($out, count($metadata));
408 foreach($metadata as $key => $d){
409 VarInt::writeUnsignedInt($out, $key);
410 VarInt::writeUnsignedInt($out, $d->getTypeId());
411 $d->write($out);
412 }
413 }
414
416 public static function getActorUniqueId(ByteBufferReader $in) : int{
417 return VarInt::readSignedLong($in);
418 }
419
420 public static function putActorUniqueId(ByteBufferWriter $out, int $eid) : void{
421 VarInt::writeSignedLong($out, $eid);
422 }
423
425 public static function getActorRuntimeId(ByteBufferReader $in) : int{
426 return VarInt::readUnsignedLong($in);
427 }
428
429 public static function putActorRuntimeId(ByteBufferWriter $out, int $eid) : void{
430 VarInt::writeUnsignedLong($out, $eid);
431 }
432
438 public static function getBlockPosition(ByteBufferReader $in) : BlockPosition{
439 $x = VarInt::readSignedInt($in);
440 $y = VarInt::readSignedInt($in);
441 $z = VarInt::readSignedInt($in);
442 return new BlockPosition($x, $y, $z);
443 }
444
448 public static function putBlockPosition(ByteBufferWriter $out, BlockPosition $blockPosition) : void{
449 VarInt::writeSignedInt($out, $blockPosition->getX());
450 VarInt::writeSignedInt($out, $blockPosition->getY());
451 VarInt::writeSignedInt($out, $blockPosition->getZ());
452 }
453
459 public static function getVector3(ByteBufferReader $in) : Vector3{
460 $x = LE::readFloat($in);
461 $y = LE::readFloat($in);
462 $z = LE::readFloat($in);
463 return new Vector3($x, $y, $z);
464 }
465
471 public static function getVector2(ByteBufferReader $in) : Vector2{
472 $x = LE::readFloat($in);
473 $y = LE::readFloat($in);
474 return new Vector2($x, $y);
475 }
476
485 public static function putVector3Nullable(ByteBufferWriter $out, ?Vector3 $vector) : void{
486 if($vector !== null){
487 self::putVector3($out, $vector);
488 }else{
489 LE::writeFloat($out, 0.0);
490 LE::writeFloat($out, 0.0);
491 LE::writeFloat($out, 0.0);
492 }
493 }
494
498 public static function putVector3(ByteBufferWriter $out, Vector3 $vector) : void{
499 LE::writeFloat($out, $vector->x);
500 LE::writeFloat($out, $vector->y);
501 LE::writeFloat($out, $vector->z);
502 }
503
507 public static function putVector2(ByteBufferWriter $out, Vector2 $vector2) : void{
508 LE::writeFloat($out, $vector2->x);
509 LE::writeFloat($out, $vector2->y);
510 }
511
513 public static function getRotationByte(ByteBufferReader $in) : float{
514 return Byte::readUnsigned($in) * (360 / 256);
515 }
516
517 public static function putRotationByte(ByteBufferWriter $out, float $rotation) : void{
518 Byte::writeUnsigned($out, (int) ($rotation / (360 / 256)));
519 }
520
522 private static function readGameRule(ByteBufferReader $in, int $type, bool $isPlayerModifiable, bool $isStartGame) : GameRule{
523 return match($type){
524 BoolGameRule::ID => BoolGameRule::decode($in, $isPlayerModifiable),
525 IntGameRule::ID => IntGameRule::decode($in, $isPlayerModifiable, $isStartGame),
526 FloatGameRule::ID => FloatGameRule::decode($in, $isPlayerModifiable),
527 default => throw new PacketDecodeException("Unknown gamerule type $type"),
528 };
529 }
530
540 public static function getGameRules(ByteBufferReader $in, bool $isStartGame) : array{
541 $count = VarInt::readUnsignedInt($in);
542 $rules = [];
543 for($i = 0; $i < $count; ++$i){
544 $name = self::getString($in);
545 $isPlayerModifiable = self::getBool($in);
546 $type = VarInt::readUnsignedInt($in);
547 $rules[$name] = self::readGameRule($in, $type, $isPlayerModifiable, $isStartGame);
548 }
549
550 return $rules;
551 }
552
559 public static function putGameRules(ByteBufferWriter $out, array $rules, bool $isStartGame) : void{
560 VarInt::writeUnsignedInt($out, count($rules));
561 foreach($rules as $name => $rule){
562 self::putString($out, $name);
563 self::putBool($out, $rule->isPlayerModifiable());
564 VarInt::writeUnsignedInt($out, $rule->getTypeId());
565 $rule->encode($out, $isStartGame);
566 }
567 }
568
570 public static function getEntityLink(ByteBufferReader $in) : EntityLink{
571 $fromActorUniqueId = self::getActorUniqueId($in);
572 $toActorUniqueId = self::getActorUniqueId($in);
573 $type = Byte::readUnsigned($in);
574 $immediate = self::getBool($in);
575 $causedByRider = self::getBool($in);
576 $vehicleAngularVelocity = LE::readFloat($in);
577 return new EntityLink($fromActorUniqueId, $toActorUniqueId, $type, $immediate, $causedByRider, $vehicleAngularVelocity);
578 }
579
580 public static function putEntityLink(ByteBufferWriter $out, EntityLink $link) : void{
581 self::putActorUniqueId($out, $link->fromActorUniqueId);
582 self::putActorUniqueId($out, $link->toActorUniqueId);
583 Byte::writeUnsigned($out, $link->type);
584 self::putBool($out, $link->immediate);
585 self::putBool($out, $link->causedByRider);
586 LE::writeFloat($out, $link->vehicleAngularVelocity);
587 }
588
590 public static function getCommandOriginData(ByteBufferReader $in) : CommandOriginData{
591 $result = new CommandOriginData();
592
593 $result->type = CommonTypes::getString($in);
594 $result->uuid = self::getUUID($in);
595 $result->requestId = self::getString($in);
596 $result->playerActorUniqueId = LE::readSignedLong($in);
597
598 return $result;
599 }
600
601 public static function putCommandOriginData(ByteBufferWriter $out, CommandOriginData $data) : void{
602 self::putString($out, $data->type);
603 self::putUUID($out, $data->uuid);
604 self::putString($out, $data->requestId);
605 LE::writeSignedLong($out, $data->playerActorUniqueId);
606 }
607
609 public static function getStructureSettings(ByteBufferReader $in) : StructureSettings{
610 $result = new StructureSettings();
611
612 $result->paletteName = self::getString($in);
613
614 $result->ignoreEntities = self::getBool($in);
615 $result->ignoreBlocks = self::getBool($in);
616 $result->allowNonTickingChunks = self::getBool($in);
617
618 $result->dimensions = self::getBlockPosition($in);
619 $result->offset = self::getBlockPosition($in);
620
621 $result->lastTouchedByPlayerID = self::getActorUniqueId($in);
622 $result->rotation = Byte::readUnsigned($in);
623 $result->mirror = Byte::readUnsigned($in);
624 $result->animationMode = Byte::readUnsigned($in);
625 $result->animationSeconds = LE::readFloat($in);
626 $result->integrityValue = LE::readFloat($in);
627 $result->integritySeed = LE::readUnsignedInt($in);
628 $result->pivot = self::getVector3($in);
629
630 return $result;
631 }
632
633 public static function putStructureSettings(ByteBufferWriter $out, StructureSettings $structureSettings) : void{
634 self::putString($out, $structureSettings->paletteName);
635
636 self::putBool($out, $structureSettings->ignoreEntities);
637 self::putBool($out, $structureSettings->ignoreBlocks);
638 self::putBool($out, $structureSettings->allowNonTickingChunks);
639
640 self::putBlockPosition($out, $structureSettings->dimensions);
641 self::putBlockPosition($out, $structureSettings->offset);
642
643 self::putActorUniqueId($out, $structureSettings->lastTouchedByPlayerID);
644 Byte::writeUnsigned($out, $structureSettings->rotation);
645 Byte::writeUnsigned($out, $structureSettings->mirror);
646 Byte::writeUnsigned($out, $structureSettings->animationMode);
647 LE::writeFloat($out, $structureSettings->animationSeconds);
648 LE::writeFloat($out, $structureSettings->integrityValue);
649 LE::writeUnsignedInt($out, $structureSettings->integritySeed);
650 self::putVector3($out, $structureSettings->pivot);
651 }
652
654 public static function getStructureEditorData(ByteBufferReader $in) : StructureEditorData{
655 $result = new StructureEditorData();
656
657 $result->structureName = self::getString($in);
658 $result->filteredStructureName = self::getString($in);
659 $result->structureDataField = self::getString($in);
660
661 $result->includePlayers = self::getBool($in);
662 $result->showBoundingBox = self::getBool($in);
663
664 $result->structureBlockType = VarInt::readSignedInt($in);
665 $result->structureSettings = self::getStructureSettings($in);
666 $result->structureRedstoneSaveMode = VarInt::readSignedInt($in);
667
668 return $result;
669 }
670
671 public static function putStructureEditorData(ByteBufferWriter $out, StructureEditorData $structureEditorData) : void{
672 self::putString($out, $structureEditorData->structureName);
673 self::putString($out, $structureEditorData->filteredStructureName);
674 self::putString($out, $structureEditorData->structureDataField);
675
676 self::putBool($out, $structureEditorData->includePlayers);
677 self::putBool($out, $structureEditorData->showBoundingBox);
678
679 VarInt::writeSignedInt($out, $structureEditorData->structureBlockType);
680 self::putStructureSettings($out, $structureEditorData->structureSettings);
681 VarInt::writeSignedInt($out, $structureEditorData->structureRedstoneSaveMode);
682 }
683
685 public static function getNbtRoot(ByteBufferReader $in) : TreeRoot{
686 $offset = $in->getOffset();
687 try{
688 return (new NetworkNbtSerializer())->read($in->getData(), $offset, 512);
689 }catch(NbtDataException $e){
690 throw PacketDecodeException::wrap($e, "Failed decoding NBT root");
691 }finally{
692 $in->setOffset($offset);
693 }
694 }
695
696 public static function getNbtCompoundRoot(ByteBufferReader $in) : CompoundTag{
697 try{
698 return self::getNbtRoot($in)->mustGetCompoundTag();
699 }catch(NbtDataException $e){
700 throw PacketDecodeException::wrap($e, "Expected TAG_Compound NBT root");
701 }
702 }
703
705 public static function readRecipeNetId(ByteBufferReader $in) : int{
706 return VarInt::readUnsignedInt($in);
707 }
708
709 public static function writeRecipeNetId(ByteBufferWriter $out, int $id) : void{
710 VarInt::writeUnsignedInt($out, $id);
711 }
712
714 public static function readCreativeItemNetId(ByteBufferReader $in) : int{
715 return VarInt::readUnsignedInt($in);
716 }
717
718 public static function writeCreativeItemNetId(ByteBufferWriter $out, int $id) : void{
719 VarInt::writeUnsignedInt($out, $id);
720 }
721
734 public static function readItemStackNetIdVariant(ByteBufferReader $in) : int{
735 return VarInt::readSignedInt($in);
736 }
737
743 public static function writeItemStackNetIdVariant(ByteBufferWriter $out, int $id) : void{
744 VarInt::writeSignedInt($out, $id);
745 }
746
748 public static function readItemStackRequestId(ByteBufferReader $in) : int{
749 return VarInt::readSignedInt($in);
750 }
751
752 public static function writeItemStackRequestId(ByteBufferWriter $out, int $id) : void{
753 VarInt::writeSignedInt($out, $id);
754 }
755
757 public static function readLegacyItemStackRequestId(ByteBufferReader $in) : int{
758 return VarInt::readSignedInt($in);
759 }
760
761 public static function writeLegacyItemStackRequestId(ByteBufferWriter $out, int $id) : void{
762 VarInt::writeSignedInt($out, $id);
763 }
764
766 public static function readServerItemStackId(ByteBufferReader $in) : int{
767 return VarInt::readSignedInt($in);
768 }
769
770 public static function writeServerItemStackId(ByteBufferWriter $out, int $id) : void{
771 VarInt::writeSignedInt($out, $id);
772 }
773
780 public static function readOptional(ByteBufferReader $in, \Closure $reader) : mixed{
781 if(self::getBool($in)){
782 return $reader($in);
783 }
784 return null;
785 }
786
792 public static function writeOptional(ByteBufferWriter $out, mixed $value, \Closure $writer) : void{
793 if($value !== null){
794 self::putBool($out, true);
795 $writer($out, $value);
796 }else{
797 self::putBool($out, false);
798 }
799 }
800}
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)