mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 16:24:05 +00:00
Merge branch 'stable'
This commit is contained in:
commit
1e6d97a157
17
changelogs/3.19.md
Normal file
17
changelogs/3.19.md
Normal file
@ -0,0 +1,17 @@
|
||||
**For Minecraft: Bedrock Edition 1.16.220**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.19.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.16.220.
|
||||
- Removed compatibility with earlier versions.
|
||||
|
||||
## Known issues (please don't open issues for these)
|
||||
- Walls don't connect to each other
|
||||
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
|
||||
- New blocks, items & mobs aren't implemented
|
||||
- Nether doesn't exist
|
@ -52,6 +52,7 @@ use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Limits;
|
||||
@ -428,7 +429,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
||||
$pk->motion = $this->getMotion();
|
||||
$pk->yaw = $this->location->yaw;
|
||||
$pk->pitch = $this->location->pitch;
|
||||
$pk->item = TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand());
|
||||
$pk->item = ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand()));
|
||||
$pk->metadata = $this->getAllNetworkData();
|
||||
$player->getNetworkSession()->sendDataPacket($pk);
|
||||
|
||||
|
@ -35,6 +35,7 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use pocketmine\player\Player;
|
||||
use function max;
|
||||
|
||||
@ -209,7 +210,7 @@ class ItemEntity extends Entity{
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->position = $this->location->asVector3();
|
||||
$pk->motion = $this->getMotion();
|
||||
$pk->item = TypeConverter::getInstance()->coreItemStackToNet($this->getItem());
|
||||
$pk->item = ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getItem()));
|
||||
$pk->metadata = $this->getAllNetworkData();
|
||||
|
||||
$player->getNetworkSession()->sendDataPacket($pk);
|
||||
|
@ -234,7 +234,7 @@ class InventoryManager{
|
||||
if($selected !== $this->clientSelectedHotbarSlot){
|
||||
$this->session->sendDataPacket(MobEquipmentPacket::create(
|
||||
$this->player->getId(),
|
||||
TypeConverter::getInstance()->coreItemStackToNet($this->player->getInventory()->getItemInHand()),
|
||||
ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->player->getInventory()->getItemInHand())),
|
||||
$selected,
|
||||
ContainerIds::INVENTORY
|
||||
));
|
||||
|
@ -91,6 +91,7 @@ use pocketmine\network\mcpe\protocol\types\DimensionIds;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\Attribute as NetworkAttribute;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||
@ -958,7 +959,7 @@ class NetworkSession{
|
||||
public function onMobEquipmentChange(Human $mob) : void{
|
||||
//TODO: we could send zero for slot here because remote players don't need to know which slot was selected
|
||||
$inv = $mob->getInventory();
|
||||
$this->sendDataPacket(MobEquipmentPacket::create($mob->getId(), TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand()), $inv->getHeldItemIndex(), ContainerIds::INVENTORY));
|
||||
$this->sendDataPacket(MobEquipmentPacket::create($mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand())), $inv->getHeldItemIndex(), ContainerIds::INVENTORY));
|
||||
}
|
||||
|
||||
public function onMobArmorChange(Living $mob) : void{
|
||||
@ -966,10 +967,10 @@ class NetworkSession{
|
||||
$converter = TypeConverter::getInstance();
|
||||
$this->sendDataPacket(MobArmorEquipmentPacket::create(
|
||||
$mob->getId(),
|
||||
$converter->coreItemStackToNet($inv->getHelmet()),
|
||||
$converter->coreItemStackToNet($inv->getChestplate()),
|
||||
$converter->coreItemStackToNet($inv->getLeggings()),
|
||||
$converter->coreItemStackToNet($inv->getBoots())
|
||||
ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getHelmet())),
|
||||
ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getChestplate())),
|
||||
ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getLeggings())),
|
||||
ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getBoots()))
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\convert;
|
||||
|
||||
use pocketmine\block\BlockLegacyIds;
|
||||
use pocketmine\block\inventory\AnvilInventory;
|
||||
use pocketmine\block\inventory\EnchantInventory;
|
||||
use pocketmine\crafting\CraftingGrid;
|
||||
@ -54,6 +55,7 @@ class TypeConverter{
|
||||
|
||||
private const DAMAGE_TAG = "Damage"; //TAG_Int
|
||||
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
|
||||
private const PM_META_TAG = "___Meta___";
|
||||
|
||||
/** @var int */
|
||||
private $shieldRuntimeId;
|
||||
@ -136,6 +138,8 @@ class TypeConverter{
|
||||
if($itemStack->hasNamedTag()){
|
||||
$nbt = clone $itemStack->getNamedTag();
|
||||
}
|
||||
|
||||
$block = $itemStack->getBlock();
|
||||
if($itemStack instanceof Durable and $itemStack->getDamage() > 0){
|
||||
if($nbt !== null){
|
||||
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
|
||||
@ -146,13 +150,24 @@ class TypeConverter{
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage());
|
||||
}elseif($block->getId() !== BlockLegacyIds::AIR && $itemStack->getMeta() !== 0){
|
||||
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
|
||||
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
|
||||
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
|
||||
if($nbt === null){
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta());
|
||||
}
|
||||
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId($itemStack->getId(), $itemStack->getMeta());
|
||||
|
||||
$blockRuntimeId = $block->getId() === BlockLegacyIds::AIR ? 0 : RuntimeBlockMapping::getInstance()->toRuntimeId($block->getFullId());
|
||||
|
||||
return new ItemStack(
|
||||
$id,
|
||||
$meta,
|
||||
$itemStack->getCount(),
|
||||
$blockRuntimeId,
|
||||
$nbt,
|
||||
[],
|
||||
[],
|
||||
@ -179,6 +194,15 @@ class TypeConverter{
|
||||
}elseif($compound->count() === 0){
|
||||
$compound = null;
|
||||
}
|
||||
}elseif(($metaTag = $compound->getTag(self::PM_META_TAG)) instanceof IntTag){
|
||||
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
|
||||
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
|
||||
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
|
||||
$meta = $metaTag->getValue();
|
||||
$compound->removeTag(self::PM_META_TAG);
|
||||
if($compound->count() === 0){
|
||||
$compound = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,12 +234,12 @@ class TypeConverter{
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function createInventoryAction(NetworkInventoryAction $action, Player $player) : ?InventoryAction{
|
||||
if($action->oldItem->equals($action->newItem)){
|
||||
if($action->oldItem->getItemStack()->equals($action->newItem->getItemStack())){
|
||||
//filter out useless noise in 1.13
|
||||
return null;
|
||||
}
|
||||
$old = $this->netItemStackToCore($action->oldItem);
|
||||
$new = $this->netItemStackToCore($action->newItem);
|
||||
$old = $this->netItemStackToCore($action->oldItem->getItemStack());
|
||||
$new = $this->netItemStackToCore($action->newItem->getItemStack());
|
||||
switch($action->sourceType){
|
||||
case NetworkInventoryAction::SOURCE_CONTAINER:
|
||||
if($action->windowId === ContainerIds::UI and $action->inventorySlot > 0){
|
||||
|
@ -32,7 +32,7 @@ use function strlen;
|
||||
use function substr;
|
||||
|
||||
class EncryptionContext{
|
||||
private const ENCRYPTION_SCHEME = "AES-256-CFB8";
|
||||
private const ENCRYPTION_SCHEME = "AES-256-GCM";
|
||||
private const CHECKSUM_ALGO = "sha256";
|
||||
|
||||
/** @var bool */
|
||||
@ -52,17 +52,15 @@ class EncryptionContext{
|
||||
private $encryptCounter = 0;
|
||||
|
||||
public function __construct(string $encryptionKey){
|
||||
//TODO: ext/crypto doesn't offer us a way to disable padding. This doesn't matter at the moment because we're
|
||||
//using CFB8, but this might change in the future. This is supposed to be CFB8 no-padding.
|
||||
|
||||
$this->key = $encryptionKey;
|
||||
$iv = substr($this->key, 0, 16);
|
||||
|
||||
$this->decryptCipher = new Cipher(self::ENCRYPTION_SCHEME);
|
||||
$this->decryptCipher->decryptInit($this->key, $iv);
|
||||
$ivLength = $this->decryptCipher->getIVLength();
|
||||
$this->decryptCipher->decryptInit($this->key, substr($this->key, 0, $ivLength));
|
||||
|
||||
$this->encryptCipher = new Cipher(self::ENCRYPTION_SCHEME);
|
||||
$this->encryptCipher->encryptInit($this->key, $iv);
|
||||
$ivLength = $this->encryptCipher->getIVLength();
|
||||
$this->encryptCipher->encryptInit($this->key, substr($this->key, 0, $ivLength));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +253,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
)
|
||||
) or (
|
||||
$this->craftingTransaction !== null &&
|
||||
!$networkInventoryAction->oldItem->equals($networkInventoryAction->newItem) &&
|
||||
!$networkInventoryAction->oldItem->getItemStack()->equals($networkInventoryAction->newItem->getItemStack()) &&
|
||||
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER &&
|
||||
$networkInventoryAction->windowId === ContainerIds::UI &&
|
||||
$networkInventoryAction->inventorySlot === UIInventorySlotOffset::CREATED_ITEM_OUTPUT
|
||||
|
@ -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);
|
||||
|
@ -35,6 +35,7 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use function str_repeat;
|
||||
@ -100,7 +101,7 @@ class FloatingTextParticle implements Particle{
|
||||
$pk->username = $name;
|
||||
$pk->entityRuntimeId = $this->entityId;
|
||||
$pk->position = $pos; //TODO: check offset
|
||||
$pk->item = ItemStack::null();
|
||||
$pk->item = ItemStackWrapper::legacy(ItemStack::null());
|
||||
|
||||
$flags = (
|
||||
1 << EntityMetadataFlags::IMMOBILE
|
||||
|
Loading…
x
Reference in New Issue
Block a user