This commit is contained in:
Dylan K. Taylor 2021-10-23 01:16:45 +01:00
parent c262c2e726
commit c773e43eda
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
54 changed files with 178 additions and 135 deletions

View File

@ -34,7 +34,7 @@
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-protocol": "^3.0.1+bedrock1.17.40",
"pocketmine/bedrock-protocol": "dev-master",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "dev-master",

16
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bc2b425a6f436a01de4e423ea651dc84",
"content-hash": "ddbcdbc7ea7247bea7fcb37e5c42340b",
"packages": [
{
"name": "adhocore/json-comment",
@ -249,16 +249,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "3.0.2+bedrock1.17.40",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "3edb21da787c1ab0f028d35243f87bd7c9038b9e"
"reference": "97fa88e9eff2c9bd5408fa964515504a4d9230bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/3edb21da787c1ab0f028d35243f87bd7c9038b9e",
"reference": "3edb21da787c1ab0f028d35243f87bd7c9038b9e",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/97fa88e9eff2c9bd5408fa964515504a4d9230bf",
"reference": "97fa88e9eff2c9bd5408fa964515504a4d9230bf",
"shasum": ""
},
"require": {
@ -277,6 +277,7 @@
"phpstan/phpstan-strict-rules": "^0.12.10",
"phpunit/phpunit": "^9.5"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@ -290,9 +291,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/3.0.2+bedrock1.17.40"
"source": "https://github.com/pmmp/BedrockProtocol/tree/master"
},
"time": "2021-10-20T18:52:14+00:00"
"time": "2021-10-23T00:06:46+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -3490,6 +3491,7 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"pocketmine/bedrock-protocol": 20,
"pocketmine/classloader": 20,
"pocketmine/spl": 20
},

View File

@ -25,6 +25,7 @@ namespace pocketmine\block\inventory;
use pocketmine\inventory\SimpleInventory;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\world\Position;
use pocketmine\world\sound\ChestCloseSound;
use pocketmine\world\sound\ChestOpenSound;
@ -50,6 +51,6 @@ class ChestInventory extends SimpleInventory implements BlockInventory{
$holder = $this->getHolder();
//event ID is always 1 for a chest
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
}
}

View File

@ -28,6 +28,7 @@ use pocketmine\inventory\DelegateInventory;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\PlayerEnderInventory;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\player\Player;
use pocketmine\world\Position;
use pocketmine\world\sound\EnderChestCloseSound;
@ -74,7 +75,7 @@ class EnderChestInventory extends DelegateInventory implements BlockInventory{
$holder = $this->getHolder();
//event ID is always 1 for a chest
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
}
public function onClose(Player $who) : void{

View File

@ -27,6 +27,7 @@ use pocketmine\block\BlockLegacyIds;
use pocketmine\inventory\SimpleInventory;
use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\world\Position;
use pocketmine\world\sound\ShulkerBoxCloseSound;
use pocketmine\world\sound\ShulkerBoxOpenSound;
@ -59,6 +60,6 @@ class ShulkerBoxInventory extends SimpleInventory implements BlockInventory{
$holder = $this->getHolder();
//event ID is always 1 for a chest
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(1, $isOpen ? 1 : 0, $holder->asVector3()));
$holder->getWorld()->broadcastPacketToViewers($holder, BlockEventPacket::create(BlockPosition::fromVector3($holder), 1, $isOpen ? 1 : 0));
}
}

View File

@ -27,6 +27,7 @@ use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\math\Facing;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
final class Bell extends Spawnable{
@ -81,6 +82,6 @@ final class Bell extends Spawnable{
$nbt->setByte(self::TAG_RINGING, 1);
$nbt->setInt(self::TAG_DIRECTION, BlockDataSerializer::writeLegacyHorizontalFacing($bellHitFace));
$nbt->setInt(self::TAG_TICKS, 0);
return BlockActorDataPacket::create($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ(), new CacheableNbt($nbt));
return BlockActorDataPacket::create(BlockPosition::fromVector3($this->position), new CacheableNbt($nbt));
}
}

View File

@ -1419,7 +1419,7 @@ abstract class Entity{
*/
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->actorRuntimeId = $this->getId();
$pk->type = static::getNetworkTypeId();
$pk->position = $this->location->asVector3();
$pk->motion = $this->getMotion();

View File

@ -145,7 +145,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
*/
public function sendSkin(?array $targets = null) : void{
$this->server->broadcastPackets($targets ?? $this->hasSpawned, [
PlayerSkinPacket::create($this->getUniqueId(), SkinAdapterSingleton::get()->toSkinData($this->skin))
PlayerSkinPacket::create($this->getUniqueId(), "", "", SkinAdapterSingleton::get()->toSkinData($this->skin))
]);
}
@ -447,7 +447,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$pk = new AddPlayerPacket();
$pk->uuid = $this->getUniqueId();
$pk->username = $this->getName();
$pk->entityRuntimeId = $this->getId();
$pk->actorRuntimeId = $this->getId();
$pk->position = $this->location->asVector3();
$pk->motion = $this->getMotion();
$pk->yaw = $this->location->yaw;

View File

@ -207,7 +207,7 @@ class ItemEntity extends Entity{
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddItemActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->actorRuntimeId = $this->getId();
$pk->position = $this->location->asVector3();
$pk->motion = $this->getMotion();
$pk->item = ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getItem()));

View File

@ -150,7 +150,7 @@ class Painting extends Entity{
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddPaintingPacket();
$pk->entityRuntimeId = $this->getId();
$pk->actorRuntimeId = $this->getId();
$pk->position = new Vector3(
($this->boundingBox->minX + $this->boundingBox->maxX) / 2,
($this->boundingBox->minY + $this->boundingBox->maxY) / 2,

View File

@ -45,6 +45,7 @@ use pocketmine\network\mcpe\protocol\CreativeContentPacket;
use pocketmine\network\mcpe\protocol\InventoryContentPacket;
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
use pocketmine\network\mcpe\protocol\types\inventory\CreativeContentEntry;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
@ -164,26 +165,27 @@ class InventoryManager{
//TODO: we should be using some kind of tagging system to identify the types. Instanceof is flaky especially
//if the class isn't final, not to mention being inflexible.
if($inv instanceof BlockInventory){
$blockPosition = BlockPosition::fromVector3($inv->getHolder());
switch(true){
case $inv instanceof LoomInventory:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::LOOM, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::LOOM, $blockPosition)];
case $inv instanceof FurnaceInventory:
return match($inv->getFurnaceType()->id()){
FurnaceType::FURNACE()->id() => [ContainerOpenPacket::blockInvVec3($id, WindowTypes::FURNACE, $inv->getHolder())],
FurnaceType::BLAST_FURNACE()->id() => [ContainerOpenPacket::blockInvVec3($id, WindowTypes::BLAST_FURNACE, $inv->getHolder())],
FurnaceType::SMOKER()->id() => [ContainerOpenPacket::blockInvVec3($id, WindowTypes::SMOKER, $inv->getHolder())],
FurnaceType::FURNACE()->id() => [ContainerOpenPacket::blockInv($id, WindowTypes::FURNACE, $blockPosition)],
FurnaceType::BLAST_FURNACE()->id() => [ContainerOpenPacket::blockInv($id, WindowTypes::BLAST_FURNACE, $blockPosition)],
FurnaceType::SMOKER()->id() => [ContainerOpenPacket::blockInv($id, WindowTypes::SMOKER, $blockPosition)],
default => throw new AssumptionFailedError("Unreachable")
};
case $inv instanceof EnchantInventory:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::ENCHANTMENT, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::ENCHANTMENT, $blockPosition)];
case $inv instanceof BrewingStandInventory:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::BREWING_STAND, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::BREWING_STAND, $blockPosition)];
case $inv instanceof AnvilInventory:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::ANVIL, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::ANVIL, $blockPosition)];
case $inv instanceof HopperInventory:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::HOPPER, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::HOPPER, $blockPosition)];
default:
return [ContainerOpenPacket::blockInvVec3($id, WindowTypes::CONTAINER, $inv->getHolder())];
return [ContainerOpenPacket::blockInv($id, WindowTypes::CONTAINER, $blockPosition)];
}
}
return null;
@ -279,6 +281,7 @@ class InventoryManager{
$this->player->getId(),
ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->player->getInventory()->getItemInHand())),
$selected,
$selected,
ContainerIds::INVENTORY
));
$this->clientSelectedHotbarSlot = $selected;

View File

@ -88,6 +88,7 @@ use pocketmine\network\mcpe\protocol\SetTitlePacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\command\CommandData;
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
@ -727,7 +728,7 @@ class NetworkSession{
$pitch = $pitch ?? $location->getPitch();
$pk = new MovePlayerPacket();
$pk->entityRuntimeId = $this->player->getId();
$pk->actorRuntimeId = $this->player->getId();
$pk->position = $this->player->getOffsetPosition($pos);
$pk->pitch = $pitch;
$pk->headYaw = $yaw;
@ -748,16 +749,17 @@ class NetworkSession{
}
public function syncViewAreaCenterPoint(Vector3 $newPos, int $viewDistance) : void{
$this->sendDataPacket(NetworkChunkPublisherUpdatePacket::create($newPos->getFloorX(), $newPos->getFloorY(), $newPos->getFloorZ(), $viewDistance * 16)); //blocks, not chunks >.>
$this->sendDataPacket(NetworkChunkPublisherUpdatePacket::create(BlockPosition::fromVector3($newPos), $viewDistance * 16)); //blocks, not chunks >.>
}
public function syncPlayerSpawnPoint(Position $newSpawn) : void{
[$x, $y, $z] = [$newSpawn->getFloorX(), $newSpawn->getFloorY(), $newSpawn->getFloorZ()];
$this->sendDataPacket(SetSpawnPositionPacket::playerSpawn($x, $y, $z, DimensionIds::OVERWORLD, $x, $y, $z));
$newSpawnBlockPosition = BlockPosition::fromVector3($newSpawn);
//TODO: respawn causing block position (bed, respawn anchor)
$this->sendDataPacket(SetSpawnPositionPacket::playerSpawn($newSpawnBlockPosition, DimensionIds::OVERWORLD, $newSpawnBlockPosition));
}
public function syncWorldSpawnPoint(Position $newSpawn) : void{
$this->sendDataPacket(SetSpawnPositionPacket::worldSpawn($newSpawn->getFloorX(), $newSpawn->getFloorY(), $newSpawn->getFloorZ(), DimensionIds::OVERWORLD));
$this->sendDataPacket(SetSpawnPositionPacket::worldSpawn(BlockPosition::fromVector3($newSpawn), DimensionIds::OVERWORLD));
}
public function syncGameMode(GameMode $mode, bool $isRollback = false) : void{
@ -788,7 +790,7 @@ class NetworkSession{
$isOp = $for->hasPermission(DefaultPermissions::ROOT_OPERATOR);
$pk->commandPermission = ($isOp ? AdventureSettingsPacket::PERMISSION_OPERATOR : AdventureSettingsPacket::PERMISSION_NORMAL);
$pk->playerPermission = ($isOp ? PlayerPermissions::OPERATOR : PlayerPermissions::MEMBER);
$pk->entityUniqueId = $for->getId();
$pk->targetActorUniqueId = $for->getId();
$this->sendDataPacket($pk);
}
@ -966,12 +968,12 @@ class NetworkSession{
public function onMobMainHandItemChange(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(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand())), $inv->getHeldItemIndex(), ContainerIds::INVENTORY));
$this->sendDataPacket(MobEquipmentPacket::create($mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand())), $inv->getHeldItemIndex(), $inv->getHeldItemIndex(), ContainerIds::INVENTORY));
}
public function onMobOffHandItemChange(Human $mob) : void{
$inv = $mob->getOffHandInventory();
$this->sendDataPacket(MobEquipmentPacket::create($mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItem(0))), 0, ContainerIds::OFFHAND));
$this->sendDataPacket(MobEquipmentPacket::create($mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItem(0))), 0, 0, ContainerIds::OFFHAND));
}
public function onMobArmorChange(Living $mob) : void{

View File

@ -79,7 +79,7 @@ final class CraftingDataCache{
$converter = TypeConverter::getInstance();
foreach($manager->getShapelessRecipes() as $list){
foreach($list as $recipe){
$pk->entries[] = new ProtocolShapelessRecipe(
$pk->recipesWithTypeIds[] = new ProtocolShapelessRecipe(
CraftingDataPacket::ENTRY_SHAPELESS,
Binary::writeInt(++$counter),
array_map(function(Item $item) use ($converter) : RecipeIngredient{
@ -104,7 +104,7 @@ final class CraftingDataCache{
$inputs[$row][$column] = $converter->coreItemStackToRecipeIngredient($recipe->getIngredient($column, $row));
}
}
$pk->entries[] = $r = new ProtocolShapedRecipe(
$pk->recipesWithTypeIds[] = $r = new ProtocolShapedRecipe(
CraftingDataPacket::ENTRY_SHAPED,
Binary::writeInt(++$counter),
$inputs,
@ -128,7 +128,7 @@ final class CraftingDataCache{
};
foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
$input = $converter->coreItemStackToNet($recipe->getInput());
$pk->entries[] = new ProtocolFurnaceRecipe(
$pk->recipesWithTypeIds[] = new ProtocolFurnaceRecipe(
CraftingDataPacket::ENTRY_FURNACE_DATA,
$input->getId(),
$input->getMeta(),

View File

@ -199,13 +199,13 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleActorEvent(ActorEventPacket $packet) : bool{
if($packet->entityRuntimeId !== $this->player->getId()){
if($packet->actorRuntimeId !== $this->player->getId()){
//TODO HACK: EATING_ITEM is sent back to the server when the server sends it for other players (1.14 bug, maybe earlier)
return $packet->event === ActorEventPacket::EATING_ITEM;
return $packet->actorRuntimeId === ActorEventPacket::EATING_ITEM;
}
$this->player->doCloseInventory();
switch($packet->event){
switch($packet->eventId){
case ActorEventPacket::EATING_ITEM: //TODO: ignore this and handle it server-side
$item = $this->player->getInventory()->getItemInHand();
if($item->isNull()){
@ -356,12 +356,12 @@ class InGamePacketHandler extends PacketHandler{
switch($data->getActionType()){
case UseItemTransactionData::ACTION_CLICK_BLOCK:
//TODO: start hack for client spam bug
$clickPos = $data->getClickPos();
$clickPos = $data->getClickPosition();
$spamBug = ($this->lastRightClickData !== null and
microtime(true) - $this->lastRightClickTime < 0.1 and //100ms
$this->lastRightClickData->getPlayerPos()->distanceSquared($data->getPlayerPos()) < 0.00001 and
$this->lastRightClickData->getBlockPos()->equals($data->getBlockPos()) and
$this->lastRightClickData->getClickPos()->distanceSquared($clickPos) < 0.00001 //signature spam bug has 0 distance, but allow some error
$this->lastRightClickData->getPlayerPosition()->distanceSquared($data->getPlayerPosition()) < 0.00001 and
$this->lastRightClickData->getBlockPosition()->equals($data->getBlockPosition()) and
$this->lastRightClickData->getClickPosition()->distanceSquared($clickPos) < 0.00001 //signature spam bug has 0 distance, but allow some error
);
//get rid of continued spam if the player clicks and holds right-click
$this->lastRightClickData = $data;
@ -371,9 +371,10 @@ class InGamePacketHandler extends PacketHandler{
}
//TODO: end hack for client spam bug
$blockPos = $data->getBlockPos();
if(!$this->player->interactBlock($blockPos, $data->getFace(), $clickPos)){
$this->onFailedBlockAction($blockPos, $data->getFace());
$blockPos = $data->getBlockPosition();
$vBlockPos = new Vector3($blockPos->getX(), $blockPos->getY(), $blockPos->getZ());
if(!$this->player->interactBlock($vBlockPos, $data->getFace(), $clickPos)){
$this->onFailedBlockAction($vBlockPos, $data->getFace());
}elseif(
!array_key_exists($windowId = InventoryManager::HARDCODED_CRAFTING_GRID_WINDOW_ID, $this->openHardcodedWindows) &&
$this->player->getCraftingGrid()->getGridWidth() === CraftingGrid::SIZE_BIG
@ -381,7 +382,7 @@ class InGamePacketHandler extends PacketHandler{
//TODO: HACK! crafting grid doesn't fit very well into the current PM container system, so this hack
//allows it to carry on working approximately the same way as it did in 1.14
$this->openHardcodedWindows[$windowId] = true;
$this->session->sendDataPacket(ContainerOpenPacket::blockInvVec3(
$this->session->sendDataPacket(ContainerOpenPacket::blockInv(
InventoryManager::HARDCODED_CRAFTING_GRID_WINDOW_ID,
WindowTypes::WORKBENCH,
$blockPos
@ -389,9 +390,10 @@ class InGamePacketHandler extends PacketHandler{
}
return true;
case UseItemTransactionData::ACTION_BREAK_BLOCK:
$blockPos = $data->getBlockPos();
if(!$this->player->breakBlock($blockPos)){
$this->onFailedBlockAction($blockPos, null);
$blockPos = $data->getBlockPosition();
$vBlockPos = new Vector3($blockPos->getX(), $blockPos->getY(), $blockPos->getZ());
if(!$this->player->breakBlock($vBlockPos)){
$this->onFailedBlockAction($vBlockPos, null);
}
return true;
case UseItemTransactionData::ACTION_CLICK_AIR:
@ -432,7 +434,7 @@ class InGamePacketHandler extends PacketHandler{
}
private function handleUseItemOnEntityTransaction(UseItemOnEntityTransactionData $data) : bool{
$target = $this->player->getWorld()->getEntity($data->getEntityRuntimeId());
$target = $this->player->getWorld()->getEntity($data->getActorRuntimeId());
if($target === null){
return false;
}
@ -442,7 +444,7 @@ class InGamePacketHandler extends PacketHandler{
//TODO: use transactiondata for rollbacks here
switch($data->getActionType()){
case UseItemOnEntityTransactionData::ACTION_INTERACT:
if(!$this->player->interactEntity($target, $data->getClickPos())){
if(!$this->player->interactEntity($target, $data->getClickPosition())){
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
}
return true;
@ -498,7 +500,7 @@ class InGamePacketHandler extends PacketHandler{
//TODO: implement handling for this where it matters
return true;
}
$target = $this->player->getWorld()->getEntity($packet->target);
$target = $this->player->getWorld()->getEntity($packet->targetActorRuntimeId);
if($target === null){
return false;
}
@ -521,7 +523,7 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{
return $this->player->pickBlock(new Vector3($packet->blockX, $packet->blockY, $packet->blockZ), $packet->addUserData);
return $this->player->pickBlock(new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ()), $packet->addUserData);
}
public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
@ -529,7 +531,7 @@ class InGamePacketHandler extends PacketHandler{
}
public function handlePlayerAction(PlayerActionPacket $packet) : bool{
$pos = new Vector3($packet->x, $packet->y, $packet->z);
$pos = new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ());
switch($packet->action){
case PlayerActionPacket::ACTION_START_BREAK:
@ -628,7 +630,7 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleAdventureSettings(AdventureSettingsPacket $packet) : bool{
if($packet->entityUniqueId !== $this->player->getId()){
if($packet->targetActorUniqueId !== $this->player->getId()){
return false; //TODO: operators can change other people's permissions using this
}
@ -648,13 +650,13 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
$pos = new Vector3($packet->x, $packet->y, $packet->z);
$pos = new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ());
if($pos->distanceSquared($this->player->getLocation()) > 10000){
return false;
}
$block = $this->player->getLocation()->getWorld()->getBlock($pos);
$nbt = $packet->namedtag->getRoot();
$nbt = $packet->nbt->getRoot();
if(!($nbt instanceof CompoundTag)) throw new AssumptionFailedError("PHPStan should ensure this is a CompoundTag"); //for phpstorm's benefit
if($block instanceof BaseSign){
@ -678,7 +680,7 @@ class InGamePacketHandler extends PacketHandler{
return true;
}
$this->session->getLogger()->debug("Invalid sign update data: " . base64_encode($packet->namedtag->getEncodedNbt()));
$this->session->getLogger()->debug("Invalid sign update data: " . base64_encode($packet->nbt->getEncodedNbt()));
}
return false;
@ -712,9 +714,10 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleItemFrameDropItem(ItemFrameDropItemPacket $packet) : bool{
$block = $this->player->getWorld()->getBlockAt($packet->x, $packet->y, $packet->z);
$blockPosition = $packet->blockPosition;
$block = $this->player->getWorld()->getBlockAt($blockPosition->getX(), $blockPosition->getY(), $blockPosition->getZ());
if($block instanceof ItemFrame and $block->getFramedItem() !== null){
return $this->player->attackBlock(new Vector3($packet->x, $packet->y, $packet->z), $block->getFacing());
return $this->player->attackBlock(new Vector3($blockPosition->getX(), $blockPosition->getY(), $blockPosition->getZ()), $block->getFacing());
}
return false;
}

View File

@ -31,9 +31,11 @@ use pocketmine\network\mcpe\InventoryManager;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
use pocketmine\network\mcpe\protocol\StartGamePacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\BoolGameRule;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\LevelSettings;
use pocketmine\network\mcpe\protocol\types\PlayerMovementSettings;
use pocketmine\network\mcpe\protocol\types\PlayerMovementType;
use pocketmine\network\mcpe\protocol\types\SpawnSettings;
@ -64,39 +66,46 @@ class PreSpawnPacketHandler extends PacketHandler{
}
public function setUp() : void{
$spawnPosition = $this->player->getSpawn();
$location = $this->player->getLocation();
$pk = new StartGamePacket();
$pk->entityUniqueId = $this->player->getId();
$pk->entityRuntimeId = $this->player->getId();
$pk->playerGamemode = TypeConverter::getInstance()->coreGameModeToProtocol($this->player->getGamemode());
$pk->playerPosition = $this->player->getOffsetPosition($location);
$pk->pitch = $location->pitch;
$pk->yaw = $location->yaw;
$pk->seed = -1;
$pk->spawnSettings = new SpawnSettings(SpawnSettings::BIOME_TYPE_DEFAULT, "", DimensionIds::OVERWORLD); //TODO: implement this properly
$pk->worldGamemode = TypeConverter::getInstance()->coreGameModeToProtocol($this->server->getGamemode());
$pk->difficulty = $location->getWorld()->getDifficulty();
$pk->spawnX = $spawnPosition->getFloorX();
$pk->spawnY = $spawnPosition->getFloorY();
$pk->spawnZ = $spawnPosition->getFloorZ();
$pk->hasAchievementsDisabled = true;
$pk->time = $location->getWorld()->getTime();
$pk->eduEditionOffer = 0;
$pk->rainLevel = 0; //TODO: implement these properly
$pk->lightningLevel = 0;
$pk->commandsEnabled = true;
$pk->gameRules = [
$levelSettings = new LevelSettings();
$levelSettings->seed = -1;
$levelSettings->spawnSettings = new SpawnSettings(SpawnSettings::BIOME_TYPE_DEFAULT, "", DimensionIds::OVERWORLD); //TODO: implement this properly
$levelSettings->worldGamemode = TypeConverter::getInstance()->coreGameModeToProtocol($this->server->getGamemode());
$levelSettings->difficulty = $location->getWorld()->getDifficulty();
$levelSettings->spawnPosition = BlockPosition::fromVector3($location->getWorld()->getSpawnLocation());
$levelSettings->hasAchievementsDisabled = true;
$levelSettings->time = $location->getWorld()->getTime();
$levelSettings->eduEditionOffer = 0;
$levelSettings->rainLevel = 0; //TODO: implement these properly
$levelSettings->lightningLevel = 0;
$levelSettings->commandsEnabled = true;
$levelSettings->gameRules = [
"naturalregeneration" => new BoolGameRule(false, false) //Hack for client side regeneration
];
$pk->experiments = new Experiments([], false);
$pk->levelId = "";
$pk->worldName = $this->server->getMotd();
$pk->itemTable = GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries(); //TODO: check if this is actually needed
$pk->playerMovementSettings = new PlayerMovementSettings(PlayerMovementType::LEGACY, 0, false);
$pk->serverSoftwareVersion = sprintf("%s %s", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true));
$this->session->sendDataPacket($pk);
$levelSettings->experiments = new Experiments([], false);
$this->session->sendDataPacket(StartGamePacket::create(
$this->player->getId(),
$this->player->getId(),
TypeConverter::getInstance()->coreGameModeToProtocol($this->player->getGamemode()),
$this->player->getOffsetPosition($location),
$location->pitch,
$location->yaw,
$levelSettings,
"",
$this->server->getMotd(),
"",
false,
new PlayerMovementSettings(PlayerMovementType::LEGACY, 0, false),
0,
0,
"",
false,
sprintf("%s %s", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true)),
[],
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries()
));
$this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers());
$this->session->sendDataPacket(StaticPacketCache::getInstance()->getBiomeDefs());

View File

@ -25,6 +25,7 @@ namespace pocketmine\network\mcpe\handler;
use pocketmine\lang\KnownTranslationKeys;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\ResourcePackChunkDataPacket;
use pocketmine\network\mcpe\protocol\ResourcePackChunkRequestPacket;
use pocketmine\network\mcpe\protocol\ResourcePackClientResponsePacket;
@ -34,6 +35,7 @@ use pocketmine\network\mcpe\protocol\ResourcePackStackPacket;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackInfoEntry;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackStackEntry;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackType;
use pocketmine\resourcepacks\ResourcePack;
use pocketmine\resourcepacks\ResourcePackManager;
use function array_map;
@ -113,7 +115,9 @@ class ResourcePacksPacketHandler extends PacketHandler{
self::PACK_CHUNK_SIZE,
(int) ceil($pack->getPackSize() / self::PACK_CHUNK_SIZE),
$pack->getPackSize(),
$pack->getSha256()
$pack->getSha256(),
false,
ResourcePackType::ADDON //TODO: this might be an addon (not behaviour pack), needed to properly support client-side custom items
));
}
$this->session->getLogger()->debug("Player requested download of " . count($packet->packIds) . " resource packs");
@ -130,7 +134,7 @@ class ResourcePacksPacketHandler extends PacketHandler{
//we don't force here, because it doesn't have user-facing effects
//but it does have an annoying side-effect when true: it makes
//the client remove its own non-server-supplied resource packs.
$this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, new Experiments([], false)));
$this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, ProtocolInfo::MINECRAFT_VERSION_NETWORK, new Experiments([], false)));
$this->session->getLogger()->debug("Applying resource pack stack");
break;
case ResourcePackClientResponsePacket::STATUS_COMPLETED:

View File

@ -97,6 +97,7 @@ use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
@ -2183,7 +2184,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$properties->setGenericFlag(EntityMetadataFlags::ACTION, $this->startAction > -1);
$properties->setPlayerFlag(PlayerMetadataFlags::SLEEP, $this->sleeping !== null);
$properties->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, $this->sleeping ?? new Vector3(0, 0, 0));
$properties->setBlockPos(EntityMetadataProperties::PLAYER_BED_POSITION, $this->sleeping !== null ? BlockPosition::fromVector3($this->sleeping) : new BlockPosition(0, 0, 0));
}
public function sendData(?array $targets, ?array $data = null) : void{

View File

@ -63,6 +63,7 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\player\Player;
use pocketmine\scheduler\AsyncPool;
@ -952,11 +953,17 @@ class World implements ChunkManager{
}
$fullBlock = $this->getBlockAt($b->x, $b->y, $b->z);
$packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, RuntimeBlockMapping::getInstance()->toRuntimeId($fullBlock->getFullId()));
$blockPosition = BlockPosition::fromVector3($b);
$packets[] = UpdateBlockPacket::create(
$blockPosition,
RuntimeBlockMapping::getInstance()->toRuntimeId($fullBlock->getFullId()),
UpdateBlockPacket::FLAG_NETWORK,
UpdateBlockPacket::DATA_LAYER_NORMAL
);
$tile = $this->getTileAt($b->x, $b->y, $b->z);
if($tile instanceof Spawnable){
$packets[] = BlockActorDataPacket::create($b->x, $b->y, $b->z, $tile->getSerializedSpawnCompound());
$packets[] = BlockActorDataPacket::create($blockPosition, $tile->getSerializedSpawnCompound());
}
}

View File

@ -99,7 +99,7 @@ class FloatingTextParticle implements Particle{
$pk = new AddPlayerPacket();
$pk->uuid = $uuid;
$pk->username = $name;
$pk->entityRuntimeId = $this->entityId;
$pk->actorRuntimeId = $this->entityId;
$pk->position = $pos; //TODO: check offset
$pk->item = ItemStackWrapper::legacy(ItemStack::null());

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ArrowHitSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BOW_HIT, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BOW_HIT, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BarrelCloseSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BLOCK_BARREL_CLOSE, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BLOCK_BARREL_CLOSE, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BarrelOpenSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BLOCK_BARREL_OPEN, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BLOCK_BARREL_OPEN, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
final class BellRingSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BLOCK_BELL_HIT, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BLOCK_BELL_HIT, $pos, false)];
}
}

View File

@ -38,6 +38,6 @@ class BlockBreakSound implements Sound{
}
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BREAK, $pos, RuntimeBlockMapping::getInstance()->toRuntimeId($this->block->getFullId()))];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BREAK, $pos, false, RuntimeBlockMapping::getInstance()->toRuntimeId($this->block->getFullId()))];
}
}

View File

@ -38,6 +38,6 @@ class BlockPlaceSound implements Sound{
}
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_PLACE, $pos, RuntimeBlockMapping::getInstance()->toRuntimeId($this->block->getFullId()))];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_PLACE, $pos, false, RuntimeBlockMapping::getInstance()->toRuntimeId($this->block->getFullId()))];
}
}

View File

@ -41,9 +41,10 @@ class BlockPunchSound implements Sound{
}
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(
return [LevelSoundEventPacket::nonActorSound(
LevelSoundEventPacket::SOUND_HIT,
$pos,
false,
RuntimeBlockMapping::getInstance()->toRuntimeId($this->block->getFullId())
)];
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BowShootSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BOW, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BOW, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BucketEmptyLavaSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BUCKET_EMPTY_LAVA, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BUCKET_EMPTY_LAVA, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BucketEmptyWaterSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BUCKET_EMPTY_WATER, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BUCKET_EMPTY_WATER, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BucketFillLavaSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BUCKET_FILL_LAVA, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BUCKET_FILL_LAVA, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class BucketFillWaterSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BUCKET_FILL_WATER, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BUCKET_FILL_WATER, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ChestCloseSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_CHEST_CLOSED, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_CHEST_CLOSED, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ChestOpenSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_CHEST_OPEN, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_CHEST_OPEN, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class EnderChestCloseSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_ENDERCHEST_CLOSED, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_ENDERCHEST_CLOSED, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class EnderChestOpenSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_ENDERCHEST_OPEN, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_ENDERCHEST_OPEN, $pos, false)];
}
}

View File

@ -36,7 +36,9 @@ class EntityAttackNoDamageSound implements Sound{
LevelSoundEventPacket::SOUND_ATTACK_NODAMAGE,
$pos,
-1,
"minecraft:player"
"minecraft:player",
false,
false
)];
}
}

View File

@ -36,7 +36,9 @@ class EntityAttackSound implements Sound{
LevelSoundEventPacket::SOUND_ATTACK_STRONG, //TODO: seems like ATTACK is dysfunctional
$pos,
-1,
"minecraft:player"
"minecraft:player",
false,
false
)];
}
}

View File

@ -49,8 +49,9 @@ class EntityLandSound implements Sound{
LevelSoundEventPacket::SOUND_LAND,
$pos,
RuntimeBlockMapping::getInstance()->toRuntimeId($this->blockLandedOn->getFullId()),
$this->entity::getNetworkTypeId()
//TODO: does isBaby have any relevance here?
$this->entity::getNetworkTypeId(),
false, //TODO: does isBaby have any relevance here?
false
)];
}
}

View File

@ -45,8 +45,9 @@ class EntityLongFallSound implements Sound{
LevelSoundEventPacket::SOUND_FALL_BIG,
$pos,
-1,
$this->entity::getNetworkTypeId()
//TODO: is isBaby relevant here?
$this->entity::getNetworkTypeId(),
false, //TODO: is isBaby relevant here?
false
)];
}
}

View File

@ -44,8 +44,9 @@ class EntityShortFallSound implements Sound{
LevelSoundEventPacket::SOUND_FALL_SMALL,
$pos,
-1,
$this->entity::getNetworkTypeId()
//TODO: does isBaby have any relevance here?
$this->entity::getNetworkTypeId(),
false, //TODO: does isBaby have any relevance here?
false
)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ExplodeSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_EXPLODE, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_EXPLODE, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
final class FireExtinguishSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_EXTINGUISH_FIRE, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_EXTINGUISH_FIRE, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class FlintSteelSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_IGNITE, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_IGNITE, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ItemBreakSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_BREAK, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_BREAK, $pos, false)];
}
}

View File

@ -42,6 +42,6 @@ class NoteSound implements Sound{
}
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_NOTE, $pos, ($this->instrument->getMagicNumber() << 8) | $this->note)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_NOTE, $pos, false, ($this->instrument->getMagicNumber() << 8) | $this->note)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class PotionSplashSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_GLASS, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_GLASS, $pos, false)];
}
}

View File

@ -37,6 +37,6 @@ class RecordSound implements Sound{
}
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create($this->recordType->getSoundId(), $pos)];
return [LevelSoundEventPacket::nonActorSound($this->recordType->getSoundId(), $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class RecordStopSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_STOP_RECORD, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_STOP_RECORD, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class RedstonePowerOffSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_POWER_OFF, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_POWER_OFF, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class RedstonePowerOnSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_POWER_ON, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_POWER_ON, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ShulkerBoxCloseSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_SHULKERBOX_CLOSED, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_SHULKERBOX_CLOSED, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ShulkerBoxOpenSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_SHULKERBOX_OPEN, $pos)];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_SHULKERBOX_OPEN, $pos, false)];
}
}

View File

@ -29,6 +29,6 @@ use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
class ThrowSound implements Sound{
public function encode(?Vector3 $pos) : array{
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_THROW, $pos, -1, "minecraft:player")];
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_THROW, $pos, -1, "minecraft:player", false, false)];
}
}

View File

@ -44,6 +44,6 @@ class XpLevelUpSound implements Sound{
public function encode(?Vector3 $pos) : array{
//No idea why such odd numbers, but this works...
//TODO: check arbitrary volume
return [LevelSoundEventPacket::create(LevelSoundEventPacket::SOUND_LEVELUP, $pos, 0x10000000 * intdiv(min(30, $this->xpLevel), 5))];
return [LevelSoundEventPacket::nonActorSound(LevelSoundEventPacket::SOUND_LEVELUP, $pos, false, 0x10000000 * intdiv(min(30, $this->xpLevel), 5))];
}
}