mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-07 18:32:55 +00:00
Merge branch 'stable'
This commit is contained in:
@ -28,7 +28,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
|
||||
class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
|
||||
@ -37,7 +37,7 @@ class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
||||
public $entityUniqueId = null; //TODO
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $item;
|
||||
/** @var Vector3 */
|
||||
public $position;
|
||||
@ -54,7 +54,7 @@ class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
||||
protected function decodePayload(PacketSerializer $in) : void{
|
||||
$this->entityUniqueId = $in->getEntityUniqueId();
|
||||
$this->entityRuntimeId = $in->getEntityRuntimeId();
|
||||
$this->item = $in->getSlot();
|
||||
$this->item = ItemStackWrapper::read($in);
|
||||
$this->position = $in->getVector3();
|
||||
$this->motion = $in->getVector3();
|
||||
$this->metadata = $in->getEntityMetadata();
|
||||
@ -64,7 +64,7 @@ class AddItemActorPacket extends DataPacket implements ClientboundPacket{
|
||||
protected function encodePayload(PacketSerializer $out) : void{
|
||||
$out->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
|
||||
$out->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$out->putSlot($this->item);
|
||||
$this->item->write($out);
|
||||
$out->putVector3($this->position);
|
||||
$out->putVector3Nullable($this->motion);
|
||||
$out->putEntityMetadata($this->metadata);
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\types\DeviceOS;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityLink;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use function count;
|
||||
|
||||
@ -57,7 +57,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
||||
public $yaw = 0.0;
|
||||
/** @var float|null */
|
||||
public $headYaw = null; //TODO
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $item;
|
||||
/**
|
||||
* @var MetadataProperty[]
|
||||
@ -99,7 +99,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
||||
$this->pitch = $in->getLFloat();
|
||||
$this->yaw = $in->getLFloat();
|
||||
$this->headYaw = $in->getLFloat();
|
||||
$this->item = $in->getSlot();
|
||||
$this->item = ItemStackWrapper::read($in);
|
||||
$this->metadata = $in->getEntityMetadata();
|
||||
|
||||
$this->uvarint1 = $in->getUnsignedVarInt();
|
||||
@ -130,7 +130,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
||||
$out->putLFloat($this->pitch);
|
||||
$out->putLFloat($this->yaw);
|
||||
$out->putLFloat($this->headYaw ?? $this->yaw);
|
||||
$out->putSlot($this->item);
|
||||
$this->item->write($out);
|
||||
$out->putEntityMetadata($this->metadata);
|
||||
|
||||
$out->putUnsignedVarInt($this->uvarint1);
|
||||
|
@ -26,7 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use function count;
|
||||
|
||||
@ -39,9 +39,9 @@ class CraftingEventPacket extends DataPacket implements ServerboundPacket{
|
||||
public $type;
|
||||
/** @var UuidInterface */
|
||||
public $id;
|
||||
/** @var ItemStack[] */
|
||||
/** @var ItemStackWrapper[] */
|
||||
public $input = [];
|
||||
/** @var ItemStack[] */
|
||||
/** @var ItemStackWrapper[] */
|
||||
public $output = [];
|
||||
|
||||
protected function decodePayload(PacketSerializer $in) : void{
|
||||
@ -51,12 +51,12 @@ class CraftingEventPacket extends DataPacket implements ServerboundPacket{
|
||||
|
||||
$size = $in->getUnsignedVarInt();
|
||||
for($i = 0; $i < $size and $i < 128; ++$i){
|
||||
$this->input[] = $in->getSlot();
|
||||
$this->input[] = ItemStackWrapper::read($in);
|
||||
}
|
||||
|
||||
$size = $in->getUnsignedVarInt();
|
||||
for($i = 0; $i < $size and $i < 128; ++$i){
|
||||
$this->output[] = $in->getSlot();
|
||||
$this->output[] = ItemStackWrapper::read($in);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,12 +67,12 @@ class CraftingEventPacket extends DataPacket implements ServerboundPacket{
|
||||
|
||||
$out->putUnsignedVarInt(count($this->input));
|
||||
foreach($this->input as $item){
|
||||
$out->putSlot($item);
|
||||
$item->write($out);
|
||||
}
|
||||
|
||||
$out->putUnsignedVarInt(count($this->output));
|
||||
foreach($this->output as $item){
|
||||
$out->putSlot($item);
|
||||
$item->write($out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,6 @@ class InventoryTransactionPacket extends DataPacket implements ClientboundPacket
|
||||
public $requestId;
|
||||
/** @var InventoryTransactionChangedSlotsHack[] */
|
||||
public $requestChangedSlots;
|
||||
/** @var bool */
|
||||
public $hasItemStackIds;
|
||||
/** @var TransactionData */
|
||||
public $trData;
|
||||
|
||||
@ -67,8 +65,6 @@ class InventoryTransactionPacket extends DataPacket implements ClientboundPacket
|
||||
|
||||
$transactionType = $in->getUnsignedVarInt();
|
||||
|
||||
$this->hasItemStackIds = $in->getBool();
|
||||
|
||||
switch($transactionType){
|
||||
case self::TYPE_NORMAL:
|
||||
$this->trData = new NormalTransactionData();
|
||||
@ -89,7 +85,7 @@ class InventoryTransactionPacket extends DataPacket implements ClientboundPacket
|
||||
throw new PacketDecodeException("Unknown transaction type $transactionType");
|
||||
}
|
||||
|
||||
$this->trData->decode($in, $this->hasItemStackIds);
|
||||
$this->trData->decode($in);
|
||||
}
|
||||
|
||||
protected function encodePayload(PacketSerializer $out) : void{
|
||||
@ -103,9 +99,7 @@ class InventoryTransactionPacket extends DataPacket implements ClientboundPacket
|
||||
|
||||
$out->putUnsignedVarInt($this->trData->getTypeId());
|
||||
|
||||
$out->putBool($this->hasItemStackIds);
|
||||
|
||||
$this->trData->encode($out, $this->hasItemStackIds);
|
||||
$this->trData->encode($out);
|
||||
}
|
||||
|
||||
public function handle(PacketHandlerInterface $handler) : bool{
|
||||
|
@ -26,7 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
|
||||
class MobArmorEquipmentPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET;
|
||||
@ -36,16 +36,16 @@ class MobArmorEquipmentPacket extends DataPacket implements ClientboundPacket, S
|
||||
|
||||
//this intentionally doesn't use an array because we don't want any implicit dependencies on internal order
|
||||
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $head;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $chest;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $legs;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $feet;
|
||||
|
||||
public static function create(int $entityRuntimeId, ItemStack $head, ItemStack $chest, ItemStack $legs, ItemStack $feet) : self{
|
||||
public static function create(int $entityRuntimeId, ItemStackWrapper $head, ItemStackWrapper $chest, ItemStackWrapper $legs, ItemStackWrapper $feet) : self{
|
||||
$result = new self;
|
||||
$result->entityRuntimeId = $entityRuntimeId;
|
||||
$result->head = $head;
|
||||
@ -58,18 +58,18 @@ class MobArmorEquipmentPacket extends DataPacket implements ClientboundPacket, S
|
||||
|
||||
protected function decodePayload(PacketSerializer $in) : void{
|
||||
$this->entityRuntimeId = $in->getEntityRuntimeId();
|
||||
$this->head = $in->getSlot();
|
||||
$this->chest = $in->getSlot();
|
||||
$this->legs = $in->getSlot();
|
||||
$this->feet = $in->getSlot();
|
||||
$this->head = ItemStackWrapper::read($in);
|
||||
$this->chest = ItemStackWrapper::read($in);
|
||||
$this->legs = ItemStackWrapper::read($in);
|
||||
$this->feet = ItemStackWrapper::read($in);
|
||||
}
|
||||
|
||||
protected function encodePayload(PacketSerializer $out) : void{
|
||||
$out->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$out->putSlot($this->head);
|
||||
$out->putSlot($this->chest);
|
||||
$out->putSlot($this->legs);
|
||||
$out->putSlot($this->feet);
|
||||
$this->head->write($out);
|
||||
$this->chest->write($out);
|
||||
$this->legs->write($out);
|
||||
$this->feet->write($out);
|
||||
}
|
||||
|
||||
public function handle(PacketHandlerInterface $handler) : bool{
|
||||
|
@ -26,14 +26,14 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
|
||||
class MobEquipmentPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOB_EQUIPMENT_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $item;
|
||||
/** @var int */
|
||||
public $inventorySlot;
|
||||
@ -42,7 +42,7 @@ class MobEquipmentPacket extends DataPacket implements ClientboundPacket, Server
|
||||
/** @var int */
|
||||
public $windowId = 0;
|
||||
|
||||
public static function create(int $entityRuntimeId, ItemStack $item, int $inventorySlot, int $windowId) : self{
|
||||
public static function create(int $entityRuntimeId, ItemStackWrapper $item, int $inventorySlot, int $windowId) : self{
|
||||
$result = new self;
|
||||
$result->entityRuntimeId = $entityRuntimeId;
|
||||
$result->item = $item;
|
||||
@ -54,7 +54,7 @@ class MobEquipmentPacket extends DataPacket implements ClientboundPacket, Server
|
||||
|
||||
protected function decodePayload(PacketSerializer $in) : void{
|
||||
$this->entityRuntimeId = $in->getEntityRuntimeId();
|
||||
$this->item = $in->getSlot();
|
||||
$this->item = ItemStackWrapper::read($in);
|
||||
$this->inventorySlot = $in->getByte();
|
||||
$this->hotbarSlot = $in->getByte();
|
||||
$this->windowId = $in->getByte();
|
||||
@ -62,7 +62,7 @@ class MobEquipmentPacket extends DataPacket implements ClientboundPacket, Server
|
||||
|
||||
protected function encodePayload(PacketSerializer $out) : void{
|
||||
$out->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$out->putSlot($this->item);
|
||||
$this->item->write($out);
|
||||
$out->putByte($this->inventorySlot);
|
||||
$out->putByte($this->hotbarSlot);
|
||||
$out->putByte($this->windowId);
|
||||
|
@ -41,11 +41,11 @@ final class ProtocolInfo{
|
||||
*/
|
||||
|
||||
/** Actual Minecraft: PE protocol version */
|
||||
public const CURRENT_PROTOCOL = 428;
|
||||
public const CURRENT_PROTOCOL = 431;
|
||||
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
|
||||
public const MINECRAFT_VERSION = 'v1.16.210';
|
||||
public const MINECRAFT_VERSION = 'v1.16.220';
|
||||
/** Version number sent to clients in ping responses. */
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.16.210';
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.16.220';
|
||||
|
||||
public const LOGIN_PACKET = 0x01;
|
||||
public const PLAY_STATUS_PACKET = 0x02;
|
||||
|
@ -25,7 +25,9 @@ namespace pocketmine\network\mcpe\protocol\serializer;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||
use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
@ -216,49 +218,83 @@ class PacketSerializer extends BinaryStream{
|
||||
* @throws PacketDecodeException
|
||||
* @throws BinaryDataException
|
||||
*/
|
||||
public function getSlot() : ItemStack{
|
||||
public function getItemStackWithoutStackId() : ItemStack{
|
||||
return $this->getItemStack(function() : void{
|
||||
//NOOP
|
||||
});
|
||||
}
|
||||
|
||||
public function putItemStackWithoutStackId(ItemStack $item) : void{
|
||||
$this->putItemStack($item, function() : void{
|
||||
//NOOP
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param \Closure(PacketSerializer) : void $readExtraCrapInTheMiddle
|
||||
*
|
||||
* @throws PacketDecodeException
|
||||
* @throws BinaryDataException
|
||||
*/
|
||||
public function getItemStack(\Closure $readExtraCrapInTheMiddle) : ItemStack{
|
||||
$id = $this->getVarInt();
|
||||
if($id === 0){
|
||||
return ItemStack::null();
|
||||
}
|
||||
|
||||
$auxValue = $this->getVarInt();
|
||||
$meta = $auxValue >> 8;
|
||||
$count = $auxValue & 0xff;
|
||||
$count = $this->getLShort();
|
||||
$meta = $this->getUnsignedVarInt();
|
||||
|
||||
$nbtLen = $this->getLShort();
|
||||
$readExtraCrapInTheMiddle($this);
|
||||
|
||||
/** @var CompoundTag|null $compound */
|
||||
$compound = null;
|
||||
if($nbtLen === 0xffff){
|
||||
$nbtDataVersion = $this->getByte();
|
||||
if($nbtDataVersion !== 1){
|
||||
throw new PacketDecodeException("Unexpected NBT data version $nbtDataVersion");
|
||||
$blockRuntimeId = $this->getVarInt();
|
||||
$extraData = new PacketSerializer($this->getString());
|
||||
$shieldItemRuntimeId = $this->shieldItemRuntimeId;
|
||||
return (static function() use ($extraData, $id, $meta, $count, $blockRuntimeId, $shieldItemRuntimeId) : ItemStack{
|
||||
$nbtLen = $extraData->getLShort();
|
||||
|
||||
/** @var CompoundTag|null $compound */
|
||||
$compound = null;
|
||||
if($nbtLen === 0xffff){
|
||||
$nbtDataVersion = $extraData->getByte();
|
||||
if($nbtDataVersion !== 1){
|
||||
throw new PacketDecodeException("Unexpected NBT data version $nbtDataVersion");
|
||||
}
|
||||
$offset = $extraData->getOffset();
|
||||
try{
|
||||
$compound = (new LittleEndianNbtSerializer())->read($extraData->getBuffer(), $offset, 512)->mustGetCompoundTag();
|
||||
}catch(NbtDataException $e){
|
||||
throw PacketDecodeException::wrap($e, "Failed decoding NBT root");
|
||||
}finally{
|
||||
$extraData->setOffset($offset);
|
||||
}
|
||||
}elseif($nbtLen !== 0){
|
||||
throw new PacketDecodeException("Unexpected fake NBT length $nbtLen");
|
||||
}
|
||||
$compound = $this->getNbtCompoundRoot();
|
||||
}elseif($nbtLen !== 0){
|
||||
throw new PacketDecodeException("Unexpected fake NBT length $nbtLen");
|
||||
}
|
||||
|
||||
$canPlaceOn = [];
|
||||
for($i = 0, $canPlaceOnCount = $this->getVarInt(); $i < $canPlaceOnCount; ++$i){
|
||||
$canPlaceOn[] = $this->getString();
|
||||
}
|
||||
$canPlaceOn = [];
|
||||
for($i = 0, $canPlaceOnCount = $extraData->getLInt(); $i < $canPlaceOnCount; ++$i){
|
||||
$canPlaceOn[] = $extraData->get($extraData->getLShort());
|
||||
}
|
||||
|
||||
$canDestroy = [];
|
||||
for($i = 0, $canDestroyCount = $this->getVarInt(); $i < $canDestroyCount; ++$i){
|
||||
$canDestroy[] = $this->getString();
|
||||
}
|
||||
$canDestroy = [];
|
||||
for($i = 0, $canDestroyCount = $extraData->getLInt(); $i < $canDestroyCount; ++$i){
|
||||
$canDestroy[] = $extraData->get($extraData->getLShort());
|
||||
}
|
||||
|
||||
$shieldBlockingTick = null;
|
||||
if($id === $this->shieldItemRuntimeId){
|
||||
$shieldBlockingTick = $this->getVarLong();
|
||||
}
|
||||
$shieldBlockingTick = null;
|
||||
if($id === $shieldItemRuntimeId){
|
||||
$shieldBlockingTick = $extraData->getLLong();
|
||||
}
|
||||
|
||||
return new ItemStack($id, $meta, $count, $compound, $canPlaceOn, $canDestroy, $shieldBlockingTick);
|
||||
return new ItemStack($id, $meta, $count, $blockRuntimeId, $compound, $canPlaceOn, $canDestroy, $shieldBlockingTick);
|
||||
})();
|
||||
}
|
||||
|
||||
public function putSlot(ItemStack $item) : void{
|
||||
/**
|
||||
* @phpstan-param \Closure(PacketSerializer) : void $writeExtraCrapInTheMiddle
|
||||
*/
|
||||
public function putItemStack(ItemStack $item, \Closure $writeExtraCrapInTheMiddle) : void{
|
||||
if($item->getId() === 0){
|
||||
$this->putVarInt(0);
|
||||
|
||||
@ -266,31 +302,42 @@ class PacketSerializer extends BinaryStream{
|
||||
}
|
||||
|
||||
$this->putVarInt($item->getId());
|
||||
$auxValue = (($item->getMeta() & 0x7fff) << 8) | $item->getCount();
|
||||
$this->putVarInt($auxValue);
|
||||
$this->putLShort($item->getCount());
|
||||
$this->putUnsignedVarInt($item->getMeta());
|
||||
|
||||
$nbt = $item->getNbt();
|
||||
if($nbt !== null){
|
||||
$this->putLShort(0xffff);
|
||||
$this->putByte(1); //TODO: NBT data version (?)
|
||||
$this->put((new NetworkNbtSerializer())->write(new TreeRoot($nbt)));
|
||||
}else{
|
||||
$this->putLShort(0);
|
||||
}
|
||||
$writeExtraCrapInTheMiddle($this);
|
||||
|
||||
$this->putVarInt(count($item->getCanPlaceOn()));
|
||||
foreach($item->getCanPlaceOn() as $entry){
|
||||
$this->putString($entry);
|
||||
}
|
||||
$this->putVarInt(count($item->getCanDestroy()));
|
||||
foreach($item->getCanDestroy() as $entry){
|
||||
$this->putString($entry);
|
||||
}
|
||||
$this->putVarInt($item->getBlockRuntimeId());
|
||||
$shieldItemRuntimeId = $this->shieldItemRuntimeId;
|
||||
$this->putString((static function() use ($item, $shieldItemRuntimeId) : string{
|
||||
$extraData = new PacketSerializer();
|
||||
|
||||
$blockingTick = $item->getShieldBlockingTick();
|
||||
if($item->getId() === $this->shieldItemRuntimeId){
|
||||
$this->putVarLong($blockingTick ?? 0);
|
||||
}
|
||||
$nbt = $item->getNbt();
|
||||
if($nbt !== null){
|
||||
$extraData->putLShort(0xffff);
|
||||
$extraData->putByte(1); //TODO: NBT data version (?)
|
||||
$extraData->put((new LittleEndianNbtSerializer())->write(new TreeRoot($nbt)));
|
||||
}else{
|
||||
$extraData->putLShort(0);
|
||||
}
|
||||
|
||||
$extraData->putLInt(count($item->getCanPlaceOn()));
|
||||
foreach($item->getCanPlaceOn() as $entry){
|
||||
$extraData->putLShort(strlen($entry));
|
||||
$extraData->put($entry);
|
||||
}
|
||||
$extraData->putLInt(count($item->getCanDestroy()));
|
||||
foreach($item->getCanDestroy() as $entry){
|
||||
$extraData->putLShort(strlen($entry));
|
||||
$extraData->put($entry);
|
||||
}
|
||||
|
||||
$blockingTick = $item->getShieldBlockingTick();
|
||||
if($item->getId() === $shieldItemRuntimeId){
|
||||
$extraData->putLLong($blockingTick ?? 0);
|
||||
}
|
||||
return $extraData->getBuffer();
|
||||
})());
|
||||
}
|
||||
|
||||
public function getRecipeIngredient() : RecipeIngredient{
|
||||
|
@ -43,12 +43,12 @@ final class CreativeContentEntry{
|
||||
|
||||
public static function read(PacketSerializer $in) : self{
|
||||
$entryId = $in->readGenericTypeNetworkId();
|
||||
$item = $in->getSlot();
|
||||
$item = $in->getItemStackWithoutStackId();
|
||||
return new self($entryId, $item);
|
||||
}
|
||||
|
||||
public function write(PacketSerializer $out) : void{
|
||||
$out->writeGenericTypeNetworkId($this->entryId);
|
||||
$out->putSlot($this->item);
|
||||
$out->putItemStackWithoutStackId($this->item);
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ final class ItemStack implements \JsonSerializable{
|
||||
private $meta;
|
||||
/** @var int */
|
||||
private $count;
|
||||
/** @var int */
|
||||
private $blockRuntimeId;
|
||||
/** @var string[] */
|
||||
private $canPlaceOn;
|
||||
/** @var string[] */
|
||||
@ -50,10 +52,11 @@ final class ItemStack implements \JsonSerializable{
|
||||
* @param string[] $canPlaceOn
|
||||
* @param string[] $canDestroy
|
||||
*/
|
||||
public function __construct(int $id, int $meta, int $count, ?CompoundTag $nbt, array $canPlaceOn, array $canDestroy, ?int $shieldBlockingTick = null){
|
||||
public function __construct(int $id, int $meta, int $count, int $blockRuntimeId, ?CompoundTag $nbt, array $canPlaceOn, array $canDestroy, ?int $shieldBlockingTick = null){
|
||||
$this->id = $id;
|
||||
$this->meta = $meta;
|
||||
$this->count = $count;
|
||||
$this->blockRuntimeId = $blockRuntimeId;
|
||||
$this->canPlaceOn = $canPlaceOn;
|
||||
$this->canDestroy = $canDestroy;
|
||||
$this->nbt = $nbt;
|
||||
@ -61,7 +64,7 @@ final class ItemStack implements \JsonSerializable{
|
||||
}
|
||||
|
||||
public static function null() : self{
|
||||
return new self(0, 0, 0, null, [], [], null);
|
||||
return new self(0, 0, 0, 0, null, [], [], null);
|
||||
}
|
||||
|
||||
public function getId() : int{
|
||||
@ -76,6 +79,8 @@ final class ItemStack implements \JsonSerializable{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
public function getBlockRuntimeId() : int{ return $this->blockRuntimeId; }
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
@ -103,6 +108,7 @@ final class ItemStack implements \JsonSerializable{
|
||||
$this->id === $itemStack->id &&
|
||||
$this->meta === $itemStack->meta &&
|
||||
$this->count === $itemStack->count &&
|
||||
$this->blockRuntimeId === $itemStack->blockRuntimeId &&
|
||||
$this->canPlaceOn === $itemStack->canPlaceOn &&
|
||||
$this->canDestroy === $itemStack->canDestroy &&
|
||||
$this->shieldBlockingTick === $itemStack->shieldBlockingTick && (
|
||||
@ -117,6 +123,7 @@ final class ItemStack implements \JsonSerializable{
|
||||
"id" => $this->id,
|
||||
"meta" => $this->meta,
|
||||
"count" => $this->count,
|
||||
"blockRuntimeId" => $this->blockRuntimeId,
|
||||
];
|
||||
if(count($this->canPlaceOn) > 0){
|
||||
$result["canPlaceOn"] = $this->canPlaceOn;
|
||||
|
@ -46,13 +46,22 @@ final class ItemStackWrapper{
|
||||
public function getItemStack() : ItemStack{ return $this->itemStack; }
|
||||
|
||||
public static function read(PacketSerializer $in) : self{
|
||||
$stackId = $in->readGenericTypeNetworkId();
|
||||
$stack = $in->getSlot();
|
||||
$stackId = 0;
|
||||
$stack = $in->getItemStack(function(PacketSerializer $in) use (&$stackId) : void{
|
||||
$hasNetId = $in->getBool();
|
||||
if($hasNetId){
|
||||
$stackId = $in->readGenericTypeNetworkId();
|
||||
}
|
||||
});
|
||||
return new self($stackId, $stack);
|
||||
}
|
||||
|
||||
public function write(PacketSerializer $out) : void{
|
||||
$out->writeGenericTypeNetworkId($this->stackId);
|
||||
$out->putSlot($this->itemStack);
|
||||
$out->putItemStack($this->itemStack, function(PacketSerializer $out) : void{
|
||||
$out->putBool($this->stackId !== 0);
|
||||
if($this->stackId !== 0){
|
||||
$out->writeGenericTypeNetworkId($this->stackId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -72,12 +72,10 @@ class NetworkInventoryAction{
|
||||
public $sourceFlags = 0;
|
||||
/** @var int */
|
||||
public $inventorySlot;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $oldItem;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
public $newItem;
|
||||
/** @var int|null */
|
||||
public $newItemStackId = null;
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
@ -85,7 +83,7 @@ class NetworkInventoryAction{
|
||||
* @throws BinaryDataException
|
||||
* @throws PacketDecodeException
|
||||
*/
|
||||
public function read(PacketSerializer $packet, bool $hasItemStackIds) : NetworkInventoryAction{
|
||||
public function read(PacketSerializer $packet) : NetworkInventoryAction{
|
||||
$this->sourceType = $packet->getUnsignedVarInt();
|
||||
|
||||
switch($this->sourceType){
|
||||
@ -105,11 +103,8 @@ class NetworkInventoryAction{
|
||||
}
|
||||
|
||||
$this->inventorySlot = $packet->getUnsignedVarInt();
|
||||
$this->oldItem = $packet->getSlot();
|
||||
$this->newItem = $packet->getSlot();
|
||||
if($hasItemStackIds){
|
||||
$this->newItemStackId = $packet->readGenericTypeNetworkId();
|
||||
}
|
||||
$this->oldItem = ItemStackWrapper::read($packet);
|
||||
$this->newItem = ItemStackWrapper::read($packet);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -117,7 +112,7 @@ class NetworkInventoryAction{
|
||||
/**
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function write(PacketSerializer $packet, bool $hasItemStackIds) : void{
|
||||
public function write(PacketSerializer $packet) : void{
|
||||
$packet->putUnsignedVarInt($this->sourceType);
|
||||
|
||||
switch($this->sourceType){
|
||||
@ -137,13 +132,7 @@ class NetworkInventoryAction{
|
||||
}
|
||||
|
||||
$packet->putUnsignedVarInt($this->inventorySlot);
|
||||
$packet->putSlot($this->oldItem);
|
||||
$packet->putSlot($this->newItem);
|
||||
if($hasItemStackIds){
|
||||
if($this->newItemStackId === null){
|
||||
throw new \InvalidStateException("Item stack ID for newItem must be provided");
|
||||
}
|
||||
$packet->writeGenericTypeNetworkId($this->newItemStackId);
|
||||
}
|
||||
$this->oldItem->write($packet);
|
||||
$this->newItem->write($packet);
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class ReleaseItemTransactionData extends TransactionData{
|
||||
private $actionType;
|
||||
/** @var int */
|
||||
private $hotbarSlot;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
private $itemInHand;
|
||||
/** @var Vector3 */
|
||||
private $headPos;
|
||||
@ -48,7 +48,7 @@ class ReleaseItemTransactionData extends TransactionData{
|
||||
return $this->hotbarSlot;
|
||||
}
|
||||
|
||||
public function getItemInHand() : ItemStack{
|
||||
public function getItemInHand() : ItemStackWrapper{
|
||||
return $this->itemInHand;
|
||||
}
|
||||
|
||||
@ -63,21 +63,21 @@ class ReleaseItemTransactionData extends TransactionData{
|
||||
protected function decodeData(PacketSerializer $stream) : void{
|
||||
$this->actionType = $stream->getUnsignedVarInt();
|
||||
$this->hotbarSlot = $stream->getVarInt();
|
||||
$this->itemInHand = $stream->getSlot();
|
||||
$this->itemInHand = ItemStackWrapper::read($stream);
|
||||
$this->headPos = $stream->getVector3();
|
||||
}
|
||||
|
||||
protected function encodeData(PacketSerializer $stream) : void{
|
||||
$stream->putUnsignedVarInt($this->actionType);
|
||||
$stream->putVarInt($this->hotbarSlot);
|
||||
$stream->putSlot($this->itemInHand);
|
||||
$this->itemInHand->write($stream);
|
||||
$stream->putVector3($this->headPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NetworkInventoryAction[] $actions
|
||||
*/
|
||||
public static function new(array $actions, int $actionType, int $hotbarSlot, ItemStack $itemInHand, Vector3 $headPos) : self{
|
||||
public static function new(array $actions, int $actionType, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $headPos) : self{
|
||||
$result = new self;
|
||||
$result->actions = $actions;
|
||||
$result->actionType = $actionType;
|
||||
|
@ -45,10 +45,10 @@ abstract class TransactionData{
|
||||
* @throws BinaryDataException
|
||||
* @throws PacketDecodeException
|
||||
*/
|
||||
final public function decode(PacketSerializer $stream, bool $hasItemStackIds) : void{
|
||||
final public function decode(PacketSerializer $stream) : void{
|
||||
$actionCount = $stream->getUnsignedVarInt();
|
||||
for($i = 0; $i < $actionCount; ++$i){
|
||||
$this->actions[] = (new NetworkInventoryAction())->read($stream, $hasItemStackIds);
|
||||
$this->actions[] = (new NetworkInventoryAction())->read($stream);
|
||||
}
|
||||
$this->decodeData($stream);
|
||||
}
|
||||
@ -59,10 +59,10 @@ abstract class TransactionData{
|
||||
*/
|
||||
abstract protected function decodeData(PacketSerializer $stream) : void;
|
||||
|
||||
final public function encode(PacketSerializer $stream, bool $hasItemStackIds) : void{
|
||||
final public function encode(PacketSerializer $stream) : void{
|
||||
$stream->putUnsignedVarInt(count($this->actions));
|
||||
foreach($this->actions as $action){
|
||||
$action->write($stream, $hasItemStackIds);
|
||||
$action->write($stream);
|
||||
}
|
||||
$this->encodeData($stream);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class UseItemOnEntityTransactionData extends TransactionData{
|
||||
private $actionType;
|
||||
/** @var int */
|
||||
private $hotbarSlot;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
private $itemInHand;
|
||||
/** @var Vector3 */
|
||||
private $playerPos;
|
||||
@ -56,7 +56,7 @@ class UseItemOnEntityTransactionData extends TransactionData{
|
||||
return $this->hotbarSlot;
|
||||
}
|
||||
|
||||
public function getItemInHand() : ItemStack{
|
||||
public function getItemInHand() : ItemStackWrapper{
|
||||
return $this->itemInHand;
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ class UseItemOnEntityTransactionData extends TransactionData{
|
||||
$this->entityRuntimeId = $stream->getEntityRuntimeId();
|
||||
$this->actionType = $stream->getUnsignedVarInt();
|
||||
$this->hotbarSlot = $stream->getVarInt();
|
||||
$this->itemInHand = $stream->getSlot();
|
||||
$this->itemInHand = ItemStackWrapper::read($stream);
|
||||
$this->playerPos = $stream->getVector3();
|
||||
$this->clickPos = $stream->getVector3();
|
||||
}
|
||||
@ -85,7 +85,7 @@ class UseItemOnEntityTransactionData extends TransactionData{
|
||||
$stream->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$stream->putUnsignedVarInt($this->actionType);
|
||||
$stream->putVarInt($this->hotbarSlot);
|
||||
$stream->putSlot($this->itemInHand);
|
||||
$this->itemInHand->write($stream);
|
||||
$stream->putVector3($this->playerPos);
|
||||
$stream->putVector3($this->clickPos);
|
||||
}
|
||||
@ -93,7 +93,7 @@ class UseItemOnEntityTransactionData extends TransactionData{
|
||||
/**
|
||||
* @param NetworkInventoryAction[] $actions
|
||||
*/
|
||||
public static function new(array $actions, int $entityRuntimeId, int $actionType, int $hotbarSlot, ItemStack $itemInHand, Vector3 $playerPos, Vector3 $clickPos) : self{
|
||||
public static function new(array $actions, int $entityRuntimeId, int $actionType, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $playerPos, Vector3 $clickPos) : self{
|
||||
$result = new self;
|
||||
$result->actions = $actions;
|
||||
$result->entityRuntimeId = $entityRuntimeId;
|
||||
|
@ -40,7 +40,7 @@ class UseItemTransactionData extends TransactionData{
|
||||
private $face;
|
||||
/** @var int */
|
||||
private $hotbarSlot;
|
||||
/** @var ItemStack */
|
||||
/** @var ItemStackWrapper */
|
||||
private $itemInHand;
|
||||
/** @var Vector3 */
|
||||
private $playerPos;
|
||||
@ -65,7 +65,7 @@ class UseItemTransactionData extends TransactionData{
|
||||
return $this->hotbarSlot;
|
||||
}
|
||||
|
||||
public function getItemInHand() : ItemStack{
|
||||
public function getItemInHand() : ItemStackWrapper{
|
||||
return $this->itemInHand;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ class UseItemTransactionData extends TransactionData{
|
||||
$this->blockPos = new Vector3($x, $y, $z);
|
||||
$this->face = $stream->getVarInt();
|
||||
$this->hotbarSlot = $stream->getVarInt();
|
||||
$this->itemInHand = $stream->getSlot();
|
||||
$this->itemInHand = ItemStackWrapper::read($stream);
|
||||
$this->playerPos = $stream->getVector3();
|
||||
$this->clickPos = $stream->getVector3();
|
||||
$this->blockRuntimeId = $stream->getUnsignedVarInt();
|
||||
@ -103,7 +103,7 @@ class UseItemTransactionData extends TransactionData{
|
||||
$stream->putBlockPosition($this->blockPos->x, $this->blockPos->y, $this->blockPos->z);
|
||||
$stream->putVarInt($this->face);
|
||||
$stream->putVarInt($this->hotbarSlot);
|
||||
$stream->putSlot($this->itemInHand);
|
||||
$this->itemInHand->write($stream);
|
||||
$stream->putVector3($this->playerPos);
|
||||
$stream->putVector3($this->clickPos);
|
||||
$stream->putUnsignedVarInt($this->blockRuntimeId);
|
||||
@ -112,7 +112,7 @@ class UseItemTransactionData extends TransactionData{
|
||||
/**
|
||||
* @param NetworkInventoryAction[] $actions
|
||||
*/
|
||||
public static function new(array $actions, int $actionType, Vector3 $blockPos, int $face, int $hotbarSlot, ItemStack $itemInHand, Vector3 $playerPos, Vector3 $clickPos, int $blockRuntimeId) : self{
|
||||
public static function new(array $actions, int $actionType, Vector3 $blockPos, int $face, int $hotbarSlot, ItemStackWrapper $itemInHand, Vector3 $playerPos, Vector3 $clickPos, int $blockRuntimeId) : self{
|
||||
$result = new self;
|
||||
$result->actions = $actions;
|
||||
$result->actionType = $actionType;
|
||||
|
@ -58,7 +58,7 @@ final class DeprecatedCraftingResultsStackRequestAction extends ItemStackRequest
|
||||
public static function read(PacketSerializer $in) : self{
|
||||
$results = [];
|
||||
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
|
||||
$results[] = $in->getSlot();
|
||||
$results[] = $in->getItemStackWithoutStackId();
|
||||
}
|
||||
$iterations = $in->getByte();
|
||||
return new self($results, $iterations);
|
||||
@ -67,7 +67,7 @@ final class DeprecatedCraftingResultsStackRequestAction extends ItemStackRequest
|
||||
public function write(PacketSerializer $out) : void{
|
||||
$out->putUnsignedVarInt(count($this->results));
|
||||
foreach($this->results as $result){
|
||||
$out->putSlot($result);
|
||||
$out->putItemStackWithoutStackId($result);
|
||||
}
|
||||
$out->putByte($this->iterations);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ final class FurnaceRecipe extends RecipeWithTypeId{
|
||||
if($typeId === CraftingDataPacket::ENTRY_FURNACE_DATA){
|
||||
$inputData = $in->getVarInt();
|
||||
}
|
||||
$output = $in->getSlot();
|
||||
$output = $in->getItemStackWithoutStackId();
|
||||
$block = $in->getString();
|
||||
|
||||
return new self($typeId, $inputId, $inputData, $output, $block);
|
||||
@ -79,7 +79,7 @@ final class FurnaceRecipe extends RecipeWithTypeId{
|
||||
if($this->getTypeId() === CraftingDataPacket::ENTRY_FURNACE_DATA){
|
||||
$out->putVarInt($this->inputMeta);
|
||||
}
|
||||
$out->putSlot($this->result);
|
||||
$out->putItemStackWithoutStackId($this->result);
|
||||
$out->putString($this->blockName);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ final class ShapedRecipe extends RecipeWithTypeId{
|
||||
|
||||
$output = [];
|
||||
for($k = 0, $resultCount = $in->getUnsignedVarInt(); $k < $resultCount; ++$k){
|
||||
$output[] = $in->getSlot();
|
||||
$output[] = $in->getItemStackWithoutStackId();
|
||||
}
|
||||
$uuid = $in->getUUID();
|
||||
$block = $in->getString();
|
||||
@ -149,7 +149,7 @@ final class ShapedRecipe extends RecipeWithTypeId{
|
||||
|
||||
$out->putUnsignedVarInt(count($this->output));
|
||||
foreach($this->output as $item){
|
||||
$out->putSlot($item);
|
||||
$out->putItemStackWithoutStackId($item);
|
||||
}
|
||||
|
||||
$out->putUUID($this->uuid);
|
||||
|
@ -102,7 +102,7 @@ final class ShapelessRecipe extends RecipeWithTypeId{
|
||||
}
|
||||
$output = [];
|
||||
for($k = 0, $resultCount = $in->getUnsignedVarInt(); $k < $resultCount; ++$k){
|
||||
$output[] = $in->getSlot();
|
||||
$output[] = $in->getItemStackWithoutStackId();
|
||||
}
|
||||
$uuid = $in->getUUID();
|
||||
$block = $in->getString();
|
||||
@ -121,7 +121,7 @@ final class ShapelessRecipe extends RecipeWithTypeId{
|
||||
|
||||
$out->putUnsignedVarInt(count($this->outputs));
|
||||
foreach($this->outputs as $item){
|
||||
$out->putSlot($item);
|
||||
$out->putItemStackWithoutStackId($item);
|
||||
}
|
||||
|
||||
$out->putUUID($this->uuid);
|
||||
|
Reference in New Issue
Block a user