diff --git a/src/pocketmine/network/protocol/AddEntityPacket.php b/src/pocketmine/network/protocol/AddEntityPacket.php index 02cfc5cafc..b987fd4c6d 100644 --- a/src/pocketmine/network/protocol/AddEntityPacket.php +++ b/src/pocketmine/network/protocol/AddEntityPacket.php @@ -25,11 +25,6 @@ namespace pocketmine\network\protocol; use pocketmine\entity\Attribute; -#ifndef COMPILE -use pocketmine\utils\Binary; - -#endif - class AddEntityPacket extends DataPacket{ const NETWORK_ID = Info::ADD_ENTITY_PACKET; @@ -68,8 +63,7 @@ class AddEntityPacket extends DataPacket{ $this->putLFloat($entry->getValue()); $this->putLFloat($entry->getMaxValue()); } - $meta = Binary::writeMetadata($this->metadata); - $this->put($meta); + $this->putEntityMetadata($this->metadata); $this->putUnsignedVarInt(count($this->links)); foreach($this->links as $link){ $this->putEntityId($link[0]); diff --git a/src/pocketmine/network/protocol/AddPlayerPacket.php b/src/pocketmine/network/protocol/AddPlayerPacket.php index 139b410318..892cb391c5 100644 --- a/src/pocketmine/network/protocol/AddPlayerPacket.php +++ b/src/pocketmine/network/protocol/AddPlayerPacket.php @@ -23,11 +23,6 @@ namespace pocketmine\network\protocol; #include -#ifndef COMPILE -use pocketmine\utils\Binary; - -#endif - class AddPlayerPacket extends DataPacket{ const NETWORK_ID = Info::ADD_PLAYER_PACKET; @@ -62,8 +57,7 @@ class AddPlayerPacket extends DataPacket{ $this->putLFloat($this->headYaw ?? $this->yaw); $this->putLFloat($this->yaw); $this->putSlot($this->item); - $meta = Binary::writeMetadata($this->metadata); - $this->put($meta); + $this->putEntityMetadata($this->metadata); } } diff --git a/src/pocketmine/network/protocol/CraftingEventPacket.php b/src/pocketmine/network/protocol/CraftingEventPacket.php index 8474cfb830..ffc294b19f 100644 --- a/src/pocketmine/network/protocol/CraftingEventPacket.php +++ b/src/pocketmine/network/protocol/CraftingEventPacket.php @@ -23,6 +23,7 @@ namespace pocketmine\network\protocol; #include +use pocketmine\item\Item; class CraftingEventPacket extends DataPacket{ const NETWORK_ID = Info::CRAFTING_EVENT_PACKET; @@ -30,7 +31,9 @@ class CraftingEventPacket extends DataPacket{ public $windowId; public $type; public $id; + /** @var Item[] */ public $input = []; + /** @var Item[] */ public $output = []; public function clean(){ diff --git a/src/pocketmine/network/protocol/DataPacket.php b/src/pocketmine/network/protocol/DataPacket.php index 03d3525105..94d989ee1b 100644 --- a/src/pocketmine/network/protocol/DataPacket.php +++ b/src/pocketmine/network/protocol/DataPacket.php @@ -23,6 +23,8 @@ namespace pocketmine\network\protocol; #include +use pocketmine\entity\Entity; +use pocketmine\item\Item; use pocketmine\utils\BinaryStream; use pocketmine\utils\Utils; @@ -67,4 +69,114 @@ abstract class DataPacket extends BinaryStream{ return $data; } + + /** + * Decodes entity metadata from the stream. + * + * @param bool $types Whether to include metadata types along with values in the returned array + * + * @return array + */ + public function getEntityMetadata(bool $types = true) : array{ + $count = $this->getUnsignedVarInt(); + $data = []; + for($i = 0; $i < $count; ++$i){ + $key = $this->getUnsignedVarInt(); + $type = $this->getUnsignedVarInt(); + $value = null; + switch($type){ + case Entity::DATA_TYPE_BYTE: + $value = $this->getByte(); + break; + case Entity::DATA_TYPE_SHORT: + $value = $this->getLShort(true); //signed + break; + case Entity::DATA_TYPE_INT: + $value = $this->getVarInt(); + break; + case Entity::DATA_TYPE_FLOAT: + $value = $this->getLFloat(); + break; + case Entity::DATA_TYPE_STRING: + $value = $this->getString(); + break; + case Entity::DATA_TYPE_SLOT: + //TODO: use objects directly + $value = []; + $item = $this->getSlot(); + $value[0] = $item->getId(); + $value[1] = $item->getCount(); + $value[2] = $item->getDamage(); + break; + case Entity::DATA_TYPE_POS: + $value = []; + $value[0] = $this->getVarInt(); //x + $value[1] = $this->getVarInt(); //y (SIGNED) + $value[2] = $this->getVarInt(); //z + break; + case Entity::DATA_TYPE_LONG: + $value = $this->getVarInt(); //TODO: varint64 proper support + break; + case Entity::DATA_TYPE_VECTOR3F: + $value = [0.0, 0.0, 0.0]; + $this->getVector3f($value[0], $value[1], $value[2]); + break; + default: + $value = []; + } + if($types === true){ + $data[$key] = [$value, $type]; + }else{ + $data[$key] = $value; + } + } + + return $data; + } + + /** + * Writes entity metadata to the packet buffer. + * + * @param array $metadata + */ + public function putEntityMetadata(array $metadata){ + $this->putUnsignedVarInt(count($metadata)); + foreach($metadata as $key => $d){ + $this->putUnsignedVarInt($key); //data key + $this->putUnsignedVarInt($d[0]); //data type + switch($d[0]){ + case Entity::DATA_TYPE_BYTE: + $this->putByte($d[1]); + break; + case Entity::DATA_TYPE_SHORT: + $this->putLShort($d[1]); //SIGNED short! + break; + case Entity::DATA_TYPE_INT: + $this->putVarInt($d[1]); + break; + case Entity::DATA_TYPE_FLOAT: + $this->putLFloat($d[1]); + break; + case Entity::DATA_TYPE_STRING: + $this->putString($d[1]); + break; + case Entity::DATA_TYPE_SLOT: + //TODO: change this implementation (use objects) + $this->putSlot(Item::get($d[1][0], $d[1][2], $d[1][1])); //ID, damage, count + break; + case Entity::DATA_TYPE_POS: + //TODO: change this implementation (use objects) + $this->putVarInt($d[1][0]); //x + $this->putVarInt($d[1][1]); //y (SIGNED) + $this->putVarInt($d[1][2]); //z + break; + case Entity::DATA_TYPE_LONG: + $this->putVarInt($d[1]); //TODO: varint64 support + break; + case Entity::DATA_TYPE_VECTOR3F: + //TODO: change this implementation (use objects) + $this->putVector3f($d[1][0], $d[1][1], $d[1][2]); //x, y, z + } + } + } } diff --git a/src/pocketmine/network/protocol/SetEntityDataPacket.php b/src/pocketmine/network/protocol/SetEntityDataPacket.php index f116faf706..32b3697467 100644 --- a/src/pocketmine/network/protocol/SetEntityDataPacket.php +++ b/src/pocketmine/network/protocol/SetEntityDataPacket.php @@ -23,10 +23,6 @@ namespace pocketmine\network\protocol; #include -#ifndef COMPILE -use pocketmine\utils\Binary; - -#endif class SetEntityDataPacket extends DataPacket{ const NETWORK_ID = Info::SET_ENTITY_DATA_PACKET; @@ -41,8 +37,7 @@ class SetEntityDataPacket extends DataPacket{ public function encode(){ $this->reset(); $this->putEntityId($this->eid); - $meta = Binary::writeMetadata($this->metadata); - $this->put($meta); + $this->putEntityMetadata($this->metadata); } } diff --git a/src/pocketmine/utils/Binary.php b/src/pocketmine/utils/Binary.php index 9544972457..7899e53838 100644 --- a/src/pocketmine/utils/Binary.php +++ b/src/pocketmine/utils/Binary.php @@ -20,12 +20,10 @@ */ /** - * Various Utilities used around the code + * Methods for working with binary strings */ namespace pocketmine\utils; -use pocketmine\entity\Entity; -use pocketmine\item\Item; class Binary{ const BIG_ENDIAN = 0x00; @@ -81,124 +79,6 @@ class Binary{ return substr(pack("V", $value), 0, -1); } - /** - * Writes a coded metadata string - * - * @param array $data - * - * @return string - */ - public static function writeMetadata(array $data){ - $stream = new BinaryStream(); - $stream->putUnsignedVarInt(count($data)); - foreach($data as $key => $d){ - $stream->putUnsignedVarInt($key); //data key - $stream->putUnsignedVarInt($d[0]); //data type - switch($d[0]){ - case Entity::DATA_TYPE_BYTE: - $stream->putByte($d[1]); - break; - case Entity::DATA_TYPE_SHORT: - $stream->putLShort($d[1]); //SIGNED short! - break; - case Entity::DATA_TYPE_INT: - $stream->putVarInt($d[1]); - break; - case Entity::DATA_TYPE_FLOAT: - $stream->putLFloat($d[1]); - break; - case Entity::DATA_TYPE_STRING: - $stream->putString($d[1]); - break; - case Entity::DATA_TYPE_SLOT: - //TODO: change this implementation (use objects) - $stream->putSlot(Item::get($d[1][0], $d[1][2], $d[1][1])); //ID, damage, count - break; - case Entity::DATA_TYPE_POS: - //TODO: change this implementation (use objects) - $stream->putVarInt($d[1][0]); //x - $stream->putVarInt($d[1][1]); //y (SIGNED) - $stream->putVarInt($d[1][2]); //z - break; - case Entity::DATA_TYPE_LONG: - $stream->putVarInt($d[1]); //TODO: varint64 support - break; - case Entity::DATA_TYPE_VECTOR3F: - //TODO: change this implementation (use objects) - $stream->putVector3f($d[1][0], $d[1][1], $d[1][2]); //x, y, z - } - } - - return $stream->getBuffer(); - } - - /** - * Reads a metadata coded string - * - * @param $value - * @param bool $types - * - * @return array - */ - public static function readMetadata($value, $types = false){ - $stream = new BinaryStream(); - $stream->setBuffer($value); - $count = $stream->getUnsignedVarInt(); - $data = []; - for($i = 0; $i < $count; ++$i){ - $key = $stream->getUnsignedVarInt(); - $type = $stream->getUnsignedVarInt(); - $value = null; - switch($type){ - case Entity::DATA_TYPE_BYTE: - $value = $stream->getByte(); - break; - case Entity::DATA_TYPE_SHORT: - $value = $stream->getLShort(true); //signed - break; - case Entity::DATA_TYPE_INT: - $value = $stream->getVarInt(); - break; - case Entity::DATA_TYPE_FLOAT: - $value = $stream->getLFloat(); - break; - case Entity::DATA_TYPE_STRING: - $value = $stream->getString(); - break; - case Entity::DATA_TYPE_SLOT: - //TODO: use objects directly - $value = []; - $item = $stream->getSlot(); - $value[0] = $item->getId(); - $value[1] = $item->getCount(); - $value[2] = $item->getDamage(); - break; - case Entity::DATA_TYPE_POS: - $value = []; - $value[0] = $stream->getVarInt(); //x - $value[1] = $stream->getVarInt(); //y (SIGNED) - $value[2] = $stream->getVarInt(); //z - break; - case Entity::DATA_TYPE_LONG: - $value = $stream->getVarInt(); //TODO: varint64 proper support - break; - case Entity::DATA_TYPE_VECTOR3F: - $value = [0.0, 0.0, 0.0]; - $stream->getVector3f($value[0], $value[1], $value[2]); - break; - default: - $value = []; - } - if($types === true){ - $data[$key] = [$value, $type]; - }else{ - $data[$key] = $value; - } - } - - return $data; - } - /** * Reads a byte boolean *