PocketMine-MP 5.15.1 git-08c6e63aac45a450fe3b437616ee8aa2500e04e2
DataPacket.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;
16
19use function get_class;
20
21abstract class DataPacket implements Packet{
22
23 public const NETWORK_ID = 0;
24
25 public const PID_MASK = 0x3ff; //10 bits
26
27 private const SUBCLIENT_ID_MASK = 0x03; //2 bits
28 private const SENDER_SUBCLIENT_ID_SHIFT = 10;
29 private const RECIPIENT_SUBCLIENT_ID_SHIFT = 12;
30
31 public int $senderSubId = 0;
32 public int $recipientSubId = 0;
33
34 public function pid() : int{
35 return $this::NETWORK_ID;
36 }
37
38 public function getName() : string{
39 return (new \ReflectionClass($this))->getShortName();
40 }
41
42 public function canBeSentBeforeLogin() : bool{
43 return false;
44 }
45
49 final public function decode(PacketSerializer $in) : void{
50 try{
51 $this->decodeHeader($in);
52 $this->decodePayload($in);
54 throw PacketDecodeException::wrap($e, $this->getName());
55 }
56 }
57
62 protected function decodeHeader(PacketSerializer $in) : void{
63 $header = $in->getUnsignedVarInt();
64 $pid = $header & self::PID_MASK;
65 if($pid !== static::NETWORK_ID){
66 //TODO: this means a logical error in the code, but how to prevent it from happening?
67 throw new PacketDecodeException("Expected " . static::NETWORK_ID . " for packet ID, got $pid");
68 }
69 $this->senderSubId = ($header >> self::SENDER_SUBCLIENT_ID_SHIFT) & self::SUBCLIENT_ID_MASK;
70 $this->recipientSubId = ($header >> self::RECIPIENT_SUBCLIENT_ID_SHIFT) & self::SUBCLIENT_ID_MASK;
71
72 }
73
80 abstract protected function decodePayload(PacketSerializer $in) : void;
81
82 final public function encode(PacketSerializer $out) : void{
83 $this->encodeHeader($out);
84 $this->encodePayload($out);
85 }
86
87 protected function encodeHeader(PacketSerializer $out) : void{
88 $out->putUnsignedVarInt(
89 static::NETWORK_ID |
90 ($this->senderSubId << self::SENDER_SUBCLIENT_ID_SHIFT) |
91 ($this->recipientSubId << self::RECIPIENT_SUBCLIENT_ID_SHIFT)
92 );
93 }
94
98 abstract protected function encodePayload(PacketSerializer $out) : void;
99
105 public function __get($name){
106 throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
107 }
108
113 public function __set($name, $value) : void{
114 throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
115 }
116}