PocketMine-MP 5.35.1 git-e32e836dad793a3a3c8ddd8927c00e112b1e576a
Loading...
Searching...
No Matches
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
17use pmmp\encoding\ByteBufferReader;
18use pmmp\encoding\ByteBufferWriter;
19use pmmp\encoding\DataDecodeException;
20use pmmp\encoding\VarInt;
21use function get_class;
22
23abstract class DataPacket implements Packet{
24
25 public const NETWORK_ID = 0;
26
27 public const PID_MASK = 0x3ff; //10 bits
28
29 private const SUBCLIENT_ID_MASK = 0x03; //2 bits
30 private const SENDER_SUBCLIENT_ID_SHIFT = 10;
31 private const RECIPIENT_SUBCLIENT_ID_SHIFT = 12;
32
33 public int $senderSubId = 0;
34 public int $recipientSubId = 0;
35
36 public function pid() : int{
37 return $this::NETWORK_ID;
38 }
39
40 public function getName() : string{
41 return (new \ReflectionClass($this))->getShortName();
42 }
43
44 public function canBeSentBeforeLogin() : bool{
45 return false;
46 }
47
51 final public function decode(ByteBufferReader $in) : void{
52 try{
53 $this->decodeHeader($in);
54 $this->decodePayload($in);
55 }catch(DataDecodeException | PacketDecodeException $e){
56 throw PacketDecodeException::wrap($e, $this->getName());
57 }
58 }
59
64 protected function decodeHeader(ByteBufferReader $in) : void{
65 $header = VarInt::readUnsignedInt($in);
66 $pid = $header & self::PID_MASK;
67 if($pid !== static::NETWORK_ID){
68 //TODO: this means a logical error in the code, but how to prevent it from happening?
69 throw new PacketDecodeException("Expected " . static::NETWORK_ID . " for packet ID, got $pid");
70 }
71 $this->senderSubId = ($header >> self::SENDER_SUBCLIENT_ID_SHIFT) & self::SUBCLIENT_ID_MASK;
72 $this->recipientSubId = ($header >> self::RECIPIENT_SUBCLIENT_ID_SHIFT) & self::SUBCLIENT_ID_MASK;
73
74 }
75
82 abstract protected function decodePayload(ByteBufferReader $in) : void;
83
84 final public function encode(ByteBufferWriter $out) : void{
85 $this->encodeHeader($out);
86 $this->encodePayload($out);
87 }
88
89 protected function encodeHeader(ByteBufferWriter $out) : void{
90 VarInt::writeUnsignedInt($out,
91 static::NETWORK_ID |
92 ($this->senderSubId << self::SENDER_SUBCLIENT_ID_SHIFT) |
93 ($this->recipientSubId << self::RECIPIENT_SUBCLIENT_ID_SHIFT)
94 );
95 }
96
100 abstract protected function encodePayload(ByteBufferWriter $out) : void;
101
107 public function __get($name){
108 throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
109 }
110
115 public function __set($name, $value) : void{
116 throw new \Error("Undefined property: " . get_class($this) . "::\$" . $name);
117 }
118}