From 287c8c2dd4c4692643c6c0b05cbc24925d39a53c Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Wed, 5 Jun 2019 15:00:08 +0100 Subject: [PATCH] Added static create() functions for many packets There are a few motivations here: 1) Less boilerplate code (this can be written inline) 2) It's possible to provide multiple constructors for different packet variations to reduce the chance of errors. 3) It makes things catch fire on updates in ways that static analysers can understand. --- src/pocketmine/entity/Entity.php | 26 +--- src/pocketmine/entity/Human.php | 10 +- src/pocketmine/entity/object/ItemEntity.php | 5 +- src/pocketmine/entity/projectile/Arrow.php | 5 +- .../inventory/ContainerInventory.php | 21 +-- src/pocketmine/inventory/PlayerInventory.php | 13 +- .../transaction/CraftingTransaction.php | 4 +- .../network/mcpe/ChunkRequestTask.php | 9 +- .../network/mcpe/NetworkSession.php | 143 ++++-------------- .../mcpe/handler/DeathSessionHandler.php | 4 +- .../mcpe/handler/LoginSessionHandler.php | 5 +- .../handler/ResourcePacksSessionHandler.php | 31 ++-- .../network/mcpe/protocol/AnimatePacket.php | 13 ++ .../mcpe/protocol/BlockEntityDataPacket.php | 7 + .../protocol/ChunkRadiusUpdatedPacket.php | 6 + .../mcpe/protocol/ContainerClosePacket.php | 6 + .../mcpe/protocol/ContainerOpenPacket.php | 16 ++ .../mcpe/protocol/ContainerSetDataPacket.php | 8 + .../mcpe/protocol/DisconnectPacket.php | 13 ++ .../mcpe/protocol/EntityEventPacket.php | 8 + .../network/mcpe/protocol/ExplodePacket.php | 16 ++ .../mcpe/protocol/FullChunkDataPacket.php | 8 + .../mcpe/protocol/InventoryContentPacket.php | 14 ++ .../mcpe/protocol/InventorySlotPacket.php | 8 + .../mcpe/protocol/MobArmorEquipmentPacket.php | 10 ++ .../network/mcpe/protocol/MobEffectPacket.php | 19 +++ .../mcpe/protocol/MobEquipmentPacket.php | 10 ++ .../mcpe/protocol/ModalFormRequestPacket.php | 7 + .../NetworkChunkPublisherUpdatePacket.php | 9 ++ .../mcpe/protocol/PlayStatusPacket.php | 6 + .../mcpe/protocol/PlayerListPacket.php | 16 ++ .../mcpe/protocol/RemoveEntityPacket.php | 6 + .../protocol/ResourcePackChunkDataPacket.php | 9 ++ .../protocol/ResourcePackDataInfoPacket.php | 10 ++ .../mcpe/protocol/ResourcePackStackPacket.php | 19 +++ .../mcpe/protocol/ResourcePacksInfoPacket.php | 19 +++ .../network/mcpe/protocol/RespawnPacket.php | 6 + .../ServerToClientHandshakePacket.php | 6 + .../mcpe/protocol/SetEntityDataPacket.php | 7 + .../mcpe/protocol/SetEntityMotionPacket.php | 7 + .../mcpe/protocol/SetPlayerGameTypePacket.php | 6 + .../mcpe/protocol/SetSpawnPositionPacket.php | 15 ++ .../network/mcpe/protocol/SetTimePacket.php | 6 + .../mcpe/protocol/TakeItemEntityPacket.php | 7 + .../network/mcpe/protocol/TextPacket.php | 59 ++++++++ .../network/mcpe/protocol/TransferPacket.php | 7 + .../mcpe/protocol/UpdateAttributesPacket.php | 14 ++ .../mcpe/protocol/UpdateBlockPacket.php | 8 + src/pocketmine/world/Explosion.php | 6 +- src/pocketmine/world/World.php | 20 +-- .../world/particle/FloatingTextParticle.php | 15 +- 51 files changed, 481 insertions(+), 247 deletions(-) diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 6040a2abf..ee58ad42e 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -874,11 +874,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } protected function broadcastMotion() : void{ - $pk = new SetEntityMotionPacket(); - $pk->entityRuntimeId = $this->id; - $pk->motion = $this->getMotion(); - - $this->world->broadcastPacketToViewers($this, $pk); + $this->world->broadcastPacketToViewers($this, SetEntityMotionPacket::create($this->id, $this->getMotion())); } public function hasGravity() : bool{ @@ -1649,9 +1645,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $id = spl_object_id($player); if(isset($this->hasSpawned[$id])){ if($send){ - $pk = new RemoveEntityPacket(); - $pk->entityUniqueId = $this->id; - $player->sendDataPacket($pk); + $player->sendDataPacket(RemoveEntityPacket::create($this->id)); } unset($this->hasSpawned[$id]); } @@ -1778,9 +1772,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $player = [$player]; } - $pk = new SetEntityDataPacket(); - $pk->entityRuntimeId = $this->getId(); - $pk->metadata = $data ?? $this->propertyManager->getAll(); + $pk = SetEntityDataPacket::create($this->getId(), $data ?? $this->propertyManager->getAll()); foreach($player as $p){ if($p === $this){ @@ -1795,19 +1787,11 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{ - $pk = new EntityEventPacket(); - $pk->entityRuntimeId = $this->id; - $pk->event = $eventId; - $pk->data = $eventData ?? 0; - - $this->server->broadcastPacket($players ?? $this->getViewers(), $pk); + $this->server->broadcastPacket($players ?? $this->getViewers(), EntityEventPacket::create($this->id, $eventId, $eventData ?? 0)); } public function broadcastAnimation(?array $players, int $animationId) : void{ - $pk = new AnimatePacket(); - $pk->entityRuntimeId = $this->id; - $pk->action = $animationId; - $this->server->broadcastPacket($players ?? $this->getViewers(), $pk); + $this->server->broadcastPacket($players ?? $this->getViewers(), AnimatePacket::create($this->id, $animationId)); } public function __destruct(){ diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index edca17db8..03150df89 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -829,10 +829,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ protected function sendSpawnPacket(Player $player) : void{ if(!($this instanceof Player)){ /* we don't use Server->updatePlayerListData() because that uses batches, which could cause race conditions in async compression mode */ - $pk = new PlayerListPacket(); - $pk->type = PlayerListPacket::TYPE_ADD; - $pk->entries = [PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), $this->skin)]; - $player->sendDataPacket($pk); + $player->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), $this->skin)])); } $pk = new AddPlayerPacket(); @@ -853,10 +850,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $player->getNetworkSession()->onMobArmorChange($this); if(!($this instanceof Player)){ - $pk = new PlayerListPacket(); - $pk->type = PlayerListPacket::TYPE_REMOVE; - $pk->entries = [PlayerListEntry::createRemovalEntry($this->uuid)]; - $player->sendDataPacket($pk); + $player->sendDataPacket(PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($this->uuid)])); } } diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index 0dadfdd23..d2a14732a 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -268,10 +268,7 @@ class ItemEntity extends Entity{ $player->awardAchievement("diamond"); } - $pk = new TakeItemEntityPacket(); - $pk->eid = $player->getId(); - $pk->target = $this->getId(); - $this->server->broadcastPacket($this->getViewers(), $pk); + $this->server->broadcastPacket($this->getViewers(), TakeItemEntityPacket::create($player->getId(), $this->getId())); $playerInventory->addItem(clone $item); $this->flagForDespawn(); diff --git a/src/pocketmine/entity/projectile/Arrow.php b/src/pocketmine/entity/projectile/Arrow.php index 0dde2ed11..f3c6c6a2a 100644 --- a/src/pocketmine/entity/projectile/Arrow.php +++ b/src/pocketmine/entity/projectile/Arrow.php @@ -194,10 +194,7 @@ class Arrow extends Projectile{ return; } - $pk = new TakeItemEntityPacket(); - $pk->eid = $player->getId(); - $pk->target = $this->getId(); - $this->server->broadcastPacket($this->getViewers(), $pk); + $this->server->broadcastPacket($this->getViewers(), TakeItemEntityPacket::create($player->getId(), $this->getId())); $playerInventory->addItem(clone $item); $this->flagForDespawn(); diff --git a/src/pocketmine/inventory/ContainerInventory.php b/src/pocketmine/inventory/ContainerInventory.php index 8a41a73a4..bc827dd76 100644 --- a/src/pocketmine/inventory/ContainerInventory.php +++ b/src/pocketmine/inventory/ContainerInventory.php @@ -40,31 +40,20 @@ abstract class ContainerInventory extends BaseInventory{ protected function onOpen(Player $who) : void{ parent::onOpen($who); - $pk = new ContainerOpenPacket(); - $pk->windowId = $who->getWindowId($this); - $pk->type = $this->getNetworkType(); + + $windowId = $who->getWindowId($this); $holder = $this->getHolder(); - - $pk->x = $pk->y = $pk->z = 0; - $pk->entityUniqueId = -1; - if($holder instanceof Entity){ - $pk->entityUniqueId = $holder->getId(); + $who->sendDataPacket(ContainerOpenPacket::entityInv($windowId, $this->getNetworkType(), $holder->getId())); }elseif($holder instanceof Vector3){ - $pk->x = $holder->getFloorX(); - $pk->y = $holder->getFloorY(); - $pk->z = $holder->getFloorZ(); + $who->sendDataPacket(ContainerOpenPacket::blockInv($windowId, $this->getNetworkType(), $holder->getFloorX(), $holder->getFloorY(), $holder->getFloorZ())); } - $who->sendDataPacket($pk); - $this->sendContents($who); } protected function onClose(Player $who) : void{ - $pk = new ContainerClosePacket(); - $pk->windowId = $who->getWindowId($this); - $who->sendDataPacket($pk); + $who->sendDataPacket(ContainerClosePacket::create($who->getWindowId($this))); parent::onClose($who); } diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index 8d91a5c15..4224923b7 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -133,11 +133,7 @@ class PlayerInventory extends BaseInventory{ public function sendHeldItem($target) : void{ $item = $this->getItemInHand(); - $pk = new MobEquipmentPacket(); - $pk->entityRuntimeId = $this->getHolder()->getId(); - $pk->item = $item; - $pk->inventorySlot = $pk->hotbarSlot = $this->getHeldItemIndex(); - $pk->windowId = ContainerIds::INVENTORY; + $pk = MobEquipmentPacket::create($this->getHolder()->getId(), $item, $this->getHeldItemIndex(), ContainerIds::INVENTORY); if(!is_array($target)){ $target->sendDataPacket($pk); @@ -166,16 +162,15 @@ class PlayerInventory extends BaseInventory{ if(!($holder instanceof Player)){ throw new \LogicException("Cannot send creative inventory contents to non-player inventory holder"); } - $pk = new InventoryContentPacket(); - $pk->windowId = ContainerIds::CREATIVE; + $items = []; if(!$holder->isSpectator()){ //fill it for all gamemodes except spectator foreach(Item::getCreativeItems() as $i => $item){ - $pk->items[$i] = clone $item; + $items[$i] = clone $item; } } - $holder->sendDataPacket($pk); + $holder->sendDataPacket(InventoryContentPacket::create(ContainerIds::CREATIVE, $items)); } /** diff --git a/src/pocketmine/inventory/transaction/CraftingTransaction.php b/src/pocketmine/inventory/transaction/CraftingTransaction.php index e01926ad1..e208ae70d 100644 --- a/src/pocketmine/inventory/transaction/CraftingTransaction.php +++ b/src/pocketmine/inventory/transaction/CraftingTransaction.php @@ -152,9 +152,7 @@ class CraftingTransaction extends InventoryTransaction{ * So people don't whine about messy desync issues when someone cancels CraftItemEvent, or when a crafting * transaction goes wrong. */ - $pk = new ContainerClosePacket(); - $pk->windowId = ContainerIds::NONE; - $this->source->sendDataPacket($pk); + $this->source->sendDataPacket(ContainerClosePacket::create(ContainerIds::NONE)); } public function execute() : bool{ diff --git a/src/pocketmine/network/mcpe/ChunkRequestTask.php b/src/pocketmine/network/mcpe/ChunkRequestTask.php index 635348367..cc5ec7d7f 100644 --- a/src/pocketmine/network/mcpe/ChunkRequestTask.php +++ b/src/pocketmine/network/mcpe/ChunkRequestTask.php @@ -23,9 +23,9 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; -use pocketmine\world\format\Chunk; use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\scheduler\AsyncTask; +use pocketmine\world\format\Chunk; class ChunkRequestTask extends AsyncTask{ private const TLS_KEY_PROMISE = "promise"; @@ -52,12 +52,7 @@ class ChunkRequestTask extends AsyncTask{ } public function onRun() : void{ - $pk = new FullChunkDataPacket(); - $pk->chunkX = $this->chunkX; - $pk->chunkZ = $this->chunkZ; - $pk->data = $this->chunk; - - $this->setResult(NetworkCompression::compress(PacketBatch::fromPackets($pk)->getBuffer(), $this->compressionLevel)); + $this->setResult(NetworkCompression::compress(PacketBatch::fromPackets(FullChunkDataPacket::create($this->chunkX, $this->chunkZ, $this->chunk))->getBuffer(), $this->compressionLevel)); } public function onError() : void{ diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index 064fb374c..46dfd06f3 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -79,6 +79,7 @@ use pocketmine\timings\Timings; use pocketmine\utils\BinaryDataException; use pocketmine\utils\Utils; use pocketmine\world\Position; +use function array_map; use function bin2hex; use function count; use function get_class; @@ -460,10 +461,7 @@ class NetworkSession{ */ public function transfer(string $ip, int $port, string $reason = "transfer") : void{ $this->tryDisconnect(function() use($ip, $port, $reason){ - $pk = new TransferPacket(); - $pk->address = $ip; - $pk->port = $port; - $this->sendDataPacket($pk, true); + $this->sendDataPacket(TransferPacket::create($ip, $port), true); $this->disconnect($reason, false); if($this->player !== null){ $this->player->disconnect($reason, null, false); @@ -492,10 +490,7 @@ class NetworkSession{ */ private function doServerDisconnect(string $reason, bool $notify = true) : void{ if($notify){ - $pk = new DisconnectPacket(); - $pk->message = $reason; - $pk->hideDisconnectionScreen = $reason === ""; - $this->sendDataPacket($pk, true); + $this->sendDataPacket($reason === "" ? DisconnectPacket::silent() : DisconnectPacket::message($reason), true); } $this->interface->close($this, $notify ? $reason : ""); @@ -544,9 +539,7 @@ class NetworkSession{ } public function enableEncryption(string $encryptionKey, string $handshakeJwt) : void{ - $pk = new ServerToClientHandshakePacket(); - $pk->jwt = $handshakeJwt; - $this->sendDataPacket($pk, true); //make sure this gets sent before encryption is enabled + $this->sendDataPacket(ServerToClientHandshakePacket::create($handshakeJwt), true); //make sure this gets sent before encryption is enabled $this->cipher = new NetworkCipher($encryptionKey); @@ -557,9 +550,7 @@ class NetworkSession{ public function onLoginSuccess() : void{ $this->loggedIn = true; - $pk = new PlayStatusPacket(); - $pk->status = PlayStatusPacket::LOGIN_SUCCESS; - $this->sendDataPacket($pk); + $this->sendDataPacket(PlayStatusPacket::create(PlayStatusPacket::LOGIN_SUCCESS)); $this->setHandler(new ResourcePacksSessionHandler($this, $this->server->getResourcePackManager())); } @@ -571,9 +562,7 @@ class NetworkSession{ } public function onTerrainReady() : void{ - $pk = new PlayStatusPacket(); - $pk->status = PlayStatusPacket::PLAYER_SPAWN; - $this->sendDataPacket($pk); + $this->sendDataPacket(PlayStatusPacket::create(PlayStatusPacket::PLAYER_SPAWN)); } public function onSpawn() : void{ @@ -604,34 +593,19 @@ class NetworkSession{ } public function syncViewAreaRadius(int $distance) : void{ - $pk = new ChunkRadiusUpdatedPacket(); - $pk->radius = $distance; - $this->sendDataPacket($pk); + $this->sendDataPacket(ChunkRadiusUpdatedPacket::create($distance)); } public function syncViewAreaCenterPoint(Vector3 $newPos, int $viewDistance) : void{ - $pk = new NetworkChunkPublisherUpdatePacket(); - $pk->x = $newPos->getFloorX(); - $pk->y = $newPos->getFloorY(); - $pk->z = $newPos->getFloorZ(); - $pk->radius = $viewDistance * 16; //blocks, not chunks >.> - $this->sendDataPacket($pk); + $this->sendDataPacket(NetworkChunkPublisherUpdatePacket::create($newPos->getFloorX(), $newPos->getFloorY(), $newPos->getFloorZ(), $viewDistance * 16)); //blocks, not chunks >.> } public function syncPlayerSpawnPoint(Position $newSpawn) : void{ - $pk = new SetSpawnPositionPacket(); - $pk->x = $newSpawn->getFloorX(); - $pk->y = $newSpawn->getFloorY(); - $pk->z = $newSpawn->getFloorZ(); - $pk->spawnType = SetSpawnPositionPacket::TYPE_PLAYER_SPAWN; - $pk->spawnForced = false; - $this->sendDataPacket($pk); + $this->sendDataPacket(SetSpawnPositionPacket::playerSpawn($newSpawn->getFloorX(), $newSpawn->getFloorY(), $newSpawn->getFloorZ(), false)); //TODO: spawn forced } public function syncGameMode(GameMode $mode) : void{ - $pk = new SetPlayerGameTypePacket(); - $pk->gamemode = self::getClientFriendlyGamemode($mode); - $this->sendDataPacket($pk); + $this->sendDataPacket(SetPlayerGameTypePacket::create(self::getClientFriendlyGamemode($mode))); } /** @@ -661,10 +635,7 @@ class NetworkSession{ public function syncAttributes(Living $entity, bool $sendAll = false){ $entries = $sendAll ? $entity->getAttributeMap()->getAll() : $entity->getAttributeMap()->needSend(); if(count($entries) > 0){ - $pk = new UpdateAttributesPacket(); - $pk->entityRuntimeId = $entity->getId(); - $pk->entries = $entries; - $this->sendDataPacket($pk); + $this->sendDataPacket(UpdateAttributesPacket::create($entity->getId(), $entries)); foreach($entries as $entry){ $entry->markSynchronized(); } @@ -672,24 +643,11 @@ class NetworkSession{ } public function onEntityEffectAdded(Living $entity, EffectInstance $effect, bool $replacesOldEffect) : void{ - $pk = new MobEffectPacket(); - $pk->entityRuntimeId = $entity->getId(); - $pk->eventId = $replacesOldEffect ? MobEffectPacket::EVENT_MODIFY : MobEffectPacket::EVENT_ADD; - $pk->effectId = $effect->getId(); - $pk->amplifier = $effect->getAmplifier(); - $pk->particles = $effect->isVisible(); - $pk->duration = $effect->getDuration(); - - $this->sendDataPacket($pk); + $this->sendDataPacket(MobEffectPacket::add($entity->getId(), $replacesOldEffect, $effect->getId(), $effect->getAmplifier(), $effect->isVisible(), $effect->getDuration())); } public function onEntityEffectRemoved(Living $entity, EffectInstance $effect) : void{ - $pk = new MobEffectPacket(); - $pk->entityRuntimeId = $entity->getId(); - $pk->eventId = MobEffectPacket::EVENT_REMOVE; - $pk->effectId = $effect->getId(); - - $this->sendDataPacket($pk); + $this->sendDataPacket(MobEffectPacket::remove($entity->getId(), $effect->getId())); } public function syncAvailableCommands() : void{ @@ -730,43 +688,27 @@ class NetworkSession{ } public function onRawChatMessage(string $message) : void{ - $pk = new TextPacket(); - $pk->type = TextPacket::TYPE_RAW; - $pk->message = $message; - $this->sendDataPacket($pk); + $this->sendDataPacket(TextPacket::raw($message)); } public function onTranslatedChatMessage(string $key, array $parameters) : void{ - $pk = new TextPacket(); - $pk->type = TextPacket::TYPE_TRANSLATION; - $pk->needsTranslation = true; - $pk->message = $key; - $pk->parameters = $parameters; - $this->sendDataPacket($pk); + $this->sendDataPacket(TextPacket::translation($key, $parameters)); } public function onPopup(string $message) : void{ - $pk = new TextPacket(); - $pk->type = TextPacket::TYPE_POPUP; - $pk->message = $message; - $this->sendDataPacket($pk); + $this->sendDataPacket(TextPacket::popup($message)); } public function onTip(string $message) : void{ - $pk = new TextPacket(); - $pk->type = TextPacket::TYPE_TIP; - $pk->message = $message; - $this->sendDataPacket($pk); + $this->sendDataPacket(TextPacket::tip($message)); } public function onFormSent(int $id, Form $form) : bool{ - $pk = new ModalFormRequestPacket(); - $pk->formId = $id; - $pk->formData = json_encode($form); - if($pk->formData === false){ + $formData = json_encode($form); + if($formData === false){ throw new \InvalidArgumentException("Failed to encode form JSON: " . json_last_error_msg()); } - return $this->sendDataPacket($pk); + return $this->sendDataPacket(ModalFormRequestPacket::create($id, $formData)); } /** @@ -803,21 +745,14 @@ class NetworkSession{ public function syncInventorySlot(Inventory $inventory, int $slot) : void{ $windowId = $this->player->getWindowId($inventory); if($windowId !== ContainerIds::NONE){ - $pk = new InventorySlotPacket(); - $pk->inventorySlot = $slot; - $pk->item = $inventory->getItem($slot); - $pk->windowId = $windowId; - $this->sendDataPacket($pk); + $this->sendDataPacket(InventorySlotPacket::create($windowId, $slot, $inventory->getItem($slot))); } } public function syncInventoryContents(Inventory $inventory) : void{ $windowId = $this->player->getWindowId($inventory); if($windowId !== ContainerIds::NONE){ - $pk = new InventoryContentPacket(); - $pk->items = $inventory->getContents(true); - $pk->windowId = $windowId; - $this->sendDataPacket($pk); + $this->sendDataPacket(InventoryContentPacket::create($windowId, $inventory->getContents(true))); } } @@ -830,48 +765,28 @@ class NetworkSession{ public function syncInventoryData(Inventory $inventory, int $propertyId, int $value) : void{ $windowId = $this->player->getWindowId($inventory); if($windowId !== ContainerIds::NONE){ - $pk = new ContainerSetDataPacket(); - $pk->property = $propertyId; - $pk->value = $value; - $pk->windowId = $windowId; - $this->sendDataPacket($pk); + $this->sendDataPacket(ContainerSetDataPacket::create($windowId, $propertyId, $value)); } } public function onMobArmorChange(Living $mob) : void{ - $pk = new MobArmorEquipmentPacket(); - $pk->entityRuntimeId = $mob->getId(); $inv = $mob->getArmorInventory(); - $pk->head = $inv->getHelmet(); - $pk->chest = $inv->getChestplate(); - $pk->legs = $inv->getLeggings(); - $pk->feet = $inv->getBoots(); - $this->sendDataPacket($pk); + $this->sendDataPacket(MobArmorEquipmentPacket::create($mob->getId(), $inv->getHelmet(), $inv->getChestplate(), $inv->getLeggings(), $inv->getBoots())); } public function syncPlayerList() : void{ - $pk = new PlayerListPacket(); - $pk->type = PlayerListPacket::TYPE_ADD; - foreach($this->server->getOnlinePlayers() as $player){ - $pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid()); - } - - $this->sendDataPacket($pk); + $this->sendDataPacket(PlayerListPacket::add(array_map(function(Player $player){ + return PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid()); + }, $this->server->getOnlinePlayers()))); } public function onPlayerAdded(Player $p) : void{ - $pk = new PlayerListPacket(); - $pk->type = PlayerListPacket::TYPE_ADD; - $pk->entries[] = PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getName(), $p->getSkin(), $p->getXuid()); - $this->sendDataPacket($pk); + $this->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getName(), $p->getSkin(), $p->getXuid())])); } public function onPlayerRemoved(Player $p) : void{ if($p !== $this->player){ - $pk = new PlayerListPacket(); - $pk->type = PlayerListPacket::TYPE_REMOVE; - $pk->entries[] = PlayerListEntry::createRemovalEntry($p->getUniqueId()); - $this->sendDataPacket($pk); + $this->sendDataPacket(PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($p->getUniqueId())])); } } diff --git a/src/pocketmine/network/mcpe/handler/DeathSessionHandler.php b/src/pocketmine/network/mcpe/handler/DeathSessionHandler.php index 0333fb7f1..e7096d0ac 100644 --- a/src/pocketmine/network/mcpe/handler/DeathSessionHandler.php +++ b/src/pocketmine/network/mcpe/handler/DeathSessionHandler.php @@ -41,9 +41,7 @@ class DeathSessionHandler extends SessionHandler{ } public function setUp() : void{ - $pk = new RespawnPacket(); - $pk->position = $this->player->getOffsetPosition($this->player->getSpawn()); - $this->session->sendDataPacket($pk); + $this->session->sendDataPacket(RespawnPacket::create($this->player->getOffsetPosition($this->player->getSpawn()))); } public function handlePlayerAction(PlayerActionPacket $packet) : bool{ diff --git a/src/pocketmine/network/mcpe/handler/LoginSessionHandler.php b/src/pocketmine/network/mcpe/handler/LoginSessionHandler.php index e9416f68b..203e0f77a 100644 --- a/src/pocketmine/network/mcpe/handler/LoginSessionHandler.php +++ b/src/pocketmine/network/mcpe/handler/LoginSessionHandler.php @@ -55,10 +55,7 @@ class LoginSessionHandler extends SessionHandler{ public function handleLogin(LoginPacket $packet) : bool{ if(!$this->isCompatibleProtocol($packet->protocol)){ - $pk = new PlayStatusPacket(); - $pk->status = $packet->protocol < ProtocolInfo::CURRENT_PROTOCOL ? - PlayStatusPacket::LOGIN_FAILED_CLIENT : PlayStatusPacket::LOGIN_FAILED_SERVER; - $this->session->sendDataPacket($pk, true); + $this->session->sendDataPacket(PlayStatusPacket::create($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL ? PlayStatusPacket::LOGIN_FAILED_CLIENT : PlayStatusPacket::LOGIN_FAILED_SERVER), true); //This pocketmine disconnect message will only be seen by the console (PlayStatusPacket causes the messages to be shown for the client) $this->session->disconnect( diff --git a/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php b/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php index be6dd90e1..877efcfc5 100644 --- a/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php +++ b/src/pocketmine/network/mcpe/handler/ResourcePacksSessionHandler.php @@ -59,10 +59,7 @@ class ResourcePacksSessionHandler extends SessionHandler{ } public function setUp() : void{ - $pk = new ResourcePacksInfoPacket(); - $pk->resourcePackEntries = $this->resourcePackManager->getResourceStack(); - $pk->mustAccept = $this->resourcePackManager->resourcePacksRequired(); - $this->session->sendDataPacket($pk); + $this->session->sendDataPacket(ResourcePacksInfoPacket::create($this->resourcePackManager->getResourceStack(), [], $this->resourcePackManager->resourcePacksRequired(), false)); } private function disconnectWithError(string $error) : void{ @@ -91,21 +88,18 @@ class ResourcePacksSessionHandler extends SessionHandler{ return false; } - $pk = new ResourcePackDataInfoPacket(); - $pk->packId = $pack->getPackId(); - $pk->maxChunkSize = self::PACK_CHUNK_SIZE; //1MB - $pk->chunkCount = (int) ceil($pack->getPackSize() / self::PACK_CHUNK_SIZE); - $pk->compressedPackSize = $pack->getPackSize(); - $pk->sha256 = $pack->getSha256(); - $this->session->sendDataPacket($pk); + $this->session->sendDataPacket(ResourcePackDataInfoPacket::create( + $pack->getPackId(), + self::PACK_CHUNK_SIZE, + (int) ceil($pack->getPackSize() / self::PACK_CHUNK_SIZE), + $pack->getPackSize(), + $pack->getSha256() + )); } break; case ResourcePackClientResponsePacket::STATUS_HAVE_ALL_PACKS: - $pk = new ResourcePackStackPacket(); - $pk->resourcePackStack = $this->resourcePackManager->getResourceStack(); - $pk->mustAccept = $this->resourcePackManager->resourcePacksRequired(); - $this->session->sendDataPacket($pk); + $this->session->sendDataPacket(ResourcePackStackPacket::create($this->resourcePackManager->getResourceStack(), [], $this->resourcePackManager->resourcePacksRequired(), false)); break; case ResourcePackClientResponsePacket::STATUS_COMPLETED: $this->session->onResourcePacksDone(); @@ -143,12 +137,7 @@ class ResourcePacksSessionHandler extends SessionHandler{ $this->downloadedChunks[$packId][$packet->chunkIndex] = true; } - $pk = new ResourcePackChunkDataPacket(); - $pk->packId = $packId; - $pk->chunkIndex = $packet->chunkIndex; - $pk->data = $pack->getPackChunk($offset, self::PACK_CHUNK_SIZE); - $pk->progress = $offset; - $this->session->sendDataPacket($pk); + $this->session->sendDataPacket(ResourcePackChunkDataPacket::create($packId, $packet->chunkIndex, $offset, $pack->getPackChunk($offset, self::PACK_CHUNK_SIZE))); return true; } diff --git a/src/pocketmine/network/mcpe/protocol/AnimatePacket.php b/src/pocketmine/network/mcpe/protocol/AnimatePacket.php index 49f9c59bc..86fc70124 100644 --- a/src/pocketmine/network/mcpe/protocol/AnimatePacket.php +++ b/src/pocketmine/network/mcpe/protocol/AnimatePacket.php @@ -43,6 +43,19 @@ class AnimatePacket extends DataPacket implements ClientboundPacket, Serverbound /** @var float */ public $float = 0.0; //TODO (Boat rowing time?) + public static function create(int $entityRuntimeId, int $actionId) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->action = $actionId; + return $result; + } + + public static function boatHack(int $entityRuntimeId, int $actionId, float $data) : self{ + $result = self::create($entityRuntimeId, $actionId); + $result->float = $data; + return $result; + } + protected function decodePayload() : void{ $this->action = $this->getVarInt(); $this->entityRuntimeId = $this->getEntityRuntimeId(); diff --git a/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php index 663c24227..c60faaca5 100644 --- a/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php @@ -40,6 +40,13 @@ class BlockEntityDataPacket extends DataPacket implements ClientboundPacket, Ser /** @var string */ public $namedtag; + public static function create(int $x, int $y, int $z, string $nbt) : self{ + $result = new self; + [$result->x, $result->y, $result->z] = [$x, $y, $z]; + $result->namedtag = $nbt; + return $result; + } + protected function decodePayload() : void{ $this->getBlockPosition($this->x, $this->y, $this->z); $this->namedtag = $this->getRemaining(); diff --git a/src/pocketmine/network/mcpe/protocol/ChunkRadiusUpdatedPacket.php b/src/pocketmine/network/mcpe/protocol/ChunkRadiusUpdatedPacket.php index 7fe8c056b..8dfd37080 100644 --- a/src/pocketmine/network/mcpe/protocol/ChunkRadiusUpdatedPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ChunkRadiusUpdatedPacket.php @@ -34,6 +34,12 @@ class ChunkRadiusUpdatedPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $radius; + public static function create(int $radius) : self{ + $result = new self; + $result->radius = $radius; + return $result; + } + protected function decodePayload() : void{ $this->radius = $this->getVarInt(); } diff --git a/src/pocketmine/network/mcpe/protocol/ContainerClosePacket.php b/src/pocketmine/network/mcpe/protocol/ContainerClosePacket.php index 55132bf99..5cc935168 100644 --- a/src/pocketmine/network/mcpe/protocol/ContainerClosePacket.php +++ b/src/pocketmine/network/mcpe/protocol/ContainerClosePacket.php @@ -34,6 +34,12 @@ class ContainerClosePacket extends DataPacket implements ClientboundPacket, Serv /** @var int */ public $windowId; + public static function create(int $windowId) : self{ + $result = new self; + $result->windowId = $windowId; + return $result; + } + protected function decodePayload() : void{ $this->windowId = $this->getByte(); } diff --git a/src/pocketmine/network/mcpe/protocol/ContainerOpenPacket.php b/src/pocketmine/network/mcpe/protocol/ContainerOpenPacket.php index eb7b893a4..de24c6055 100644 --- a/src/pocketmine/network/mcpe/protocol/ContainerOpenPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ContainerOpenPacket.php @@ -44,6 +44,22 @@ class ContainerOpenPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $entityUniqueId = -1; + public static function blockInv(int $windowId, int $windowType, int $x, int $y, int $z) : self{ + $result = new self; + $result->windowId = $windowId; + $result->type = $windowType; + [$result->x, $result->y, $result->z] = [$x, $y, $z]; + return $result; + } + + public static function entityInv(int $windowId, int $windowType, int $entityUniqueId) : self{ + $result = new self; + $result->windowId = $windowId; + $result->type = $windowType; + $result->entityUniqueId = $entityUniqueId; + return $result; + } + protected function decodePayload() : void{ $this->windowId = $this->getByte(); $this->type = $this->getByte(); diff --git a/src/pocketmine/network/mcpe/protocol/ContainerSetDataPacket.php b/src/pocketmine/network/mcpe/protocol/ContainerSetDataPacket.php index 54f9fcb34..93c5473e2 100644 --- a/src/pocketmine/network/mcpe/protocol/ContainerSetDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ContainerSetDataPacket.php @@ -48,6 +48,14 @@ class ContainerSetDataPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $value; + public static function create(int $windowId, int $propertyId, int $value) : self{ + $result = new self; + $result->property = $propertyId; + $result->value = $value; + $result->windowId = $windowId; + return $result; + } + protected function decodePayload() : void{ $this->windowId = $this->getByte(); $this->property = $this->getVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/DisconnectPacket.php b/src/pocketmine/network/mcpe/protocol/DisconnectPacket.php index 437ec6b90..513f8f8ec 100644 --- a/src/pocketmine/network/mcpe/protocol/DisconnectPacket.php +++ b/src/pocketmine/network/mcpe/protocol/DisconnectPacket.php @@ -36,6 +36,19 @@ class DisconnectPacket extends DataPacket implements ClientboundPacket, Serverbo /** @var string */ public $message = ""; + public static function silent() : self{ + $result = new self; + $result->hideDisconnectionScreen = true; + return $result; + } + + public static function message(string $message) : self{ + $result = new self; + $result->hideDisconnectionScreen = false; + $result->message = $message; + return $result; + } + public function canBeSentBeforeLogin() : bool{ return true; } diff --git a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php b/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php index 8a87b490a..86e33d3be 100644 --- a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php +++ b/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php @@ -90,6 +90,14 @@ class EntityEventPacket extends DataPacket implements ClientboundPacket, Serverb /** @var int */ public $data = 0; + public static function create(int $entityRuntimeId, int $eventId, int $eventData) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->event = $eventId; + $result->data = $eventData; + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->event = $this->getByte(); diff --git a/src/pocketmine/network/mcpe/protocol/ExplodePacket.php b/src/pocketmine/network/mcpe/protocol/ExplodePacket.php index 17a2141be..fada68783 100644 --- a/src/pocketmine/network/mcpe/protocol/ExplodePacket.php +++ b/src/pocketmine/network/mcpe/protocol/ExplodePacket.php @@ -40,6 +40,22 @@ class ExplodePacket extends DataPacket implements ClientboundPacket{ /** @var Vector3[] */ public $records = []; + /** + * @param Vector3 $center + * @param float $radius + * @param Vector3[] $records + * + * @return ExplodePacket + */ + public static function create(Vector3 $center, float $radius, array $records) : self{ + (function(Vector3 ...$_){})($records); + $result = new self; + $result->position = $center; + $result->radius = $radius; + $result->records = $records; + return $result; + } + protected function decodePayload() : void{ $this->position = $this->getVector3(); $this->radius = (float) ($this->getVarInt() / 32); diff --git a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php b/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php index 2503772c8..abe1c936a 100644 --- a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php @@ -38,6 +38,14 @@ class FullChunkDataPacket extends DataPacket implements ClientboundPacket{ /** @var string */ public $data; + public static function create(int $chunkX, int $chunkZ, string $payload) : self{ + $result = new self; + $result->chunkX = $chunkX; + $result->chunkZ = $chunkZ; + $result->data = $payload; + return $result; + } + protected function decodePayload() : void{ $this->chunkX = $this->getVarInt(); $this->chunkZ = $this->getVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/InventoryContentPacket.php b/src/pocketmine/network/mcpe/protocol/InventoryContentPacket.php index 4e82aacea..bf5bab448 100644 --- a/src/pocketmine/network/mcpe/protocol/InventoryContentPacket.php +++ b/src/pocketmine/network/mcpe/protocol/InventoryContentPacket.php @@ -37,6 +37,20 @@ class InventoryContentPacket extends DataPacket implements ClientboundPacket{ /** @var Item[] */ public $items = []; + /** + * @param int $windowId + * @param Item[] $items + * + * @return InventoryContentPacket + */ + public static function create(int $windowId, array $items) : self{ + (function(Item ...$items){})(...$items); //type check + $result = new self; + $result->windowId = $windowId; + $result->items = $items; + return $result; + } + protected function decodePayload() : void{ $this->windowId = $this->getUnsignedVarInt(); $count = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/InventorySlotPacket.php b/src/pocketmine/network/mcpe/protocol/InventorySlotPacket.php index 4f21e7526..e34adbeba 100644 --- a/src/pocketmine/network/mcpe/protocol/InventorySlotPacket.php +++ b/src/pocketmine/network/mcpe/protocol/InventorySlotPacket.php @@ -38,6 +38,14 @@ class InventorySlotPacket extends DataPacket implements ClientboundPacket{ /** @var Item */ public $item; + public static function create(int $windowId, int $slot, Item $item) : self{ + $result = new self; + $result->inventorySlot = $slot; + $result->item = $item; + $result->windowId = $windowId; + return $result; + } + protected function decodePayload() : void{ $this->windowId = $this->getUnsignedVarInt(); $this->inventorySlot = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php b/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php index 99b3923c5..0888c9f2f 100644 --- a/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MobArmorEquipmentPacket.php @@ -46,6 +46,16 @@ class MobArmorEquipmentPacket extends DataPacket implements ClientboundPacket, S /** @var Item */ public $feet; + public static function create(int $entityRuntimeId, Item $head, Item $chest, Item $legs, Item $feet) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->head = $head; + $result->chest = $chest; + $result->legs = $legs; + $result->feet = $feet; + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->head = $this->getSlot(); diff --git a/src/pocketmine/network/mcpe/protocol/MobEffectPacket.php b/src/pocketmine/network/mcpe/protocol/MobEffectPacket.php index c40509edb..108b57ad7 100644 --- a/src/pocketmine/network/mcpe/protocol/MobEffectPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MobEffectPacket.php @@ -48,6 +48,25 @@ class MobEffectPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $duration = 0; + public static function add(int $entityRuntimeId, bool $replace, int $effectId, int $amplifier, bool $particles, int $duration) : self{ + $result = new self; + $result->eventId = $replace ? self::EVENT_MODIFY : self::EVENT_ADD; + $result->entityRuntimeId = $entityRuntimeId; + $result->effectId = $effectId; + $result->amplifier = $amplifier; + $result->particles = $particles; + $result->duration = $duration; + return $result; + } + + public static function remove(int $entityRuntimeId, int $effectId) : self{ + $pk = new self; + $pk->eventId = self::EVENT_REMOVE; + $pk->entityRuntimeId = $entityRuntimeId; + $pk->effectId = $effectId; + return $pk; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->eventId = $this->getByte(); diff --git a/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php b/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php index 6ea86df84..9676e966f 100644 --- a/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MobEquipmentPacket.php @@ -43,6 +43,16 @@ class MobEquipmentPacket extends DataPacket implements ClientboundPacket, Server /** @var int */ public $windowId = 0; + public static function create(int $entityRuntimeId, Item $item, int $inventorySlot, int $windowId) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->item = $item; + $result->inventorySlot = $inventorySlot; + $result->hotbarSlot = $inventorySlot; + $result->windowId = $windowId; + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->item = $this->getSlot(); diff --git a/src/pocketmine/network/mcpe/protocol/ModalFormRequestPacket.php b/src/pocketmine/network/mcpe/protocol/ModalFormRequestPacket.php index 09a65c4f1..cd1c9d42a 100644 --- a/src/pocketmine/network/mcpe/protocol/ModalFormRequestPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ModalFormRequestPacket.php @@ -35,6 +35,13 @@ class ModalFormRequestPacket extends DataPacket implements ClientboundPacket{ /** @var string */ public $formData; //json + public static function create(int $formId, string $formData) : self{ + $result = new self; + $result->formId = $formId; + $result->formData = $formData; + return $result; + } + protected function decodePayload() : void{ $this->formId = $this->getUnsignedVarInt(); $this->formData = $this->getString(); diff --git a/src/pocketmine/network/mcpe/protocol/NetworkChunkPublisherUpdatePacket.php b/src/pocketmine/network/mcpe/protocol/NetworkChunkPublisherUpdatePacket.php index 7075d0dfa..1d39454d6 100644 --- a/src/pocketmine/network/mcpe/protocol/NetworkChunkPublisherUpdatePacket.php +++ b/src/pocketmine/network/mcpe/protocol/NetworkChunkPublisherUpdatePacket.php @@ -39,6 +39,15 @@ class NetworkChunkPublisherUpdatePacket extends DataPacket implements Clientboun /** @var int */ public $radius; + public static function create(int $x, int $y, int $z, int $blockRadius) : self{ + $result = new self; + $result->x = $x; + $result->y = $y; + $result->z = $z; + $result->radius = $blockRadius; + return $result; + } + protected function decodePayload() : void{ $this->getSignedBlockPosition($this->x, $this->y, $this->z); $this->radius = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php b/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php index 83ca723c8..f2c435461 100644 --- a/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PlayStatusPacket.php @@ -43,6 +43,12 @@ class PlayStatusPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $status; + public static function create(int $status) : self{ + $result = new self; + $result->status = $status; + return $result; + } + protected function decodePayload() : void{ $this->status = $this->getInt(); } diff --git a/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php b/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php index ec4f1af24..8910b7323 100644 --- a/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PlayerListPacket.php @@ -43,6 +43,22 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $type; + public static function add(array $entries) : self{ + (function(PlayerListEntry ...$_){})($entries); + $result = new self; + $result->type = self::TYPE_ADD; + $result->entries = $entries; + return $result; + } + + public static function remove(array $entries) : self{ + (function(PlayerListEntry ...$_){})($entries); + $result = new self; + $result->type = self::TYPE_REMOVE; + $result->entries = $entries; + return $result; + } + protected function decodePayload() : void{ $this->type = $this->getByte(); $count = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php index 7aad4b7bc..e9b1c32cc 100644 --- a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php @@ -34,6 +34,12 @@ class RemoveEntityPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $entityUniqueId; + public static function create(int $entityUniqueId) : self{ + $result = new self; + $result->entityUniqueId = $entityUniqueId; + return $result; + } + protected function decodePayload() : void{ $this->entityUniqueId = $this->getEntityUniqueId(); } diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php index 0e6c3ab01..f51384d7f 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePackChunkDataPacket.php @@ -42,6 +42,15 @@ class ResourcePackChunkDataPacket extends DataPacket implements ClientboundPacke /** @var string */ public $data; + public static function create(string $packId, int $chunkIndex, int $chunkOffset, string $data) : self{ + $result = new self; + $result->packId = $packId; + $result->chunkIndex = $chunkIndex; + $result->progress = $chunkOffset; + $result->data = $data; + return $result; + } + protected function decodePayload() : void{ $this->packId = $this->getString(); $this->chunkIndex = $this->getLInt(); diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php index 26882732f..e28abefb7 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php @@ -43,6 +43,16 @@ class ResourcePackDataInfoPacket extends DataPacket implements ClientboundPacket /** @var string */ public $sha256; + public static function create(string $packId, int $maxChunkSize, int $chunkCount, int $compressedPackSize, string $sha256sum) : self{ + $result = new self; + $result->packId = $packId; + $result->maxChunkSize = $maxChunkSize; + $result->chunkCount = $chunkCount; + $result->compressedPackSize = $compressedPackSize; + $result->sha256 = $sha256sum; + return $result; + } + protected function decodePayload() : void{ $this->packId = $this->getString(); $this->maxChunkSize = $this->getLInt(); diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackStackPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackStackPacket.php index 95fe5078e..eed28a945 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePackStackPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePackStackPacket.php @@ -45,6 +45,25 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{ /** @var bool */ public $isExperimental = false; + /** + * @param ResourcePack[] $resourcePacks + * @param ResourcePack[] $behaviorPacks + * @param bool $mustAccept + * @param bool $isExperimental + * + * @return ResourcePackStackPacket + */ + public static function create(array $resourcePacks, array $behaviorPacks, bool $mustAccept, bool $isExperimental = false) : self{ + (function(ResourcePack ...$_){})($resourcePacks); + (function(ResourcePack ...$_){})($behaviorPacks); + $result = new self; + $result->mustAccept = $mustAccept; + $result->resourcePackStack = $resourcePacks; + $result->behaviorPackStack = $behaviorPacks; + $result->isExperimental = $isExperimental; + return $result; + } + protected function decodePayload() : void{ $this->mustAccept = $this->getBool(); $behaviorPackCount = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php index ebd00b40b..bf55daf45 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePacksInfoPacket.php @@ -42,6 +42,25 @@ class ResourcePacksInfoPacket extends DataPacket implements ClientboundPacket{ /** @var ResourcePack[] */ public $resourcePackEntries = []; + /** + * @param ResourcePack[] $resourcePacks + * @param ResourcePack[] $behaviorPacks + * @param bool $mustAccept + * @param bool $hasScripts + * + * @return ResourcePacksInfoPacket + */ + public static function create(array $resourcePacks, array $behaviorPacks, bool $mustAccept, bool $hasScripts = false) : self{ + (function(ResourcePack ...$_){})($resourcePacks); + (function(ResourcePack ...$_){})($behaviorPacks); + $result = new self; + $result->mustAccept = $mustAccept; + $result->hasScripts = $hasScripts; + $result->resourcePackEntries = $resourcePacks; + $result->behaviorPackEntries = $behaviorPacks; + return $result; + } + protected function decodePayload() : void{ $this->mustAccept = $this->getBool(); $this->hasScripts = $this->getBool(); diff --git a/src/pocketmine/network/mcpe/protocol/RespawnPacket.php b/src/pocketmine/network/mcpe/protocol/RespawnPacket.php index ad7b29540..b4f79446a 100644 --- a/src/pocketmine/network/mcpe/protocol/RespawnPacket.php +++ b/src/pocketmine/network/mcpe/protocol/RespawnPacket.php @@ -35,6 +35,12 @@ class RespawnPacket extends DataPacket implements ClientboundPacket{ /** @var Vector3 */ public $position; + public static function create(Vector3 $position) : self{ + $result = new self; + $result->position = $position->asVector3(); + return $result; + } + protected function decodePayload() : void{ $this->position = $this->getVector3(); } diff --git a/src/pocketmine/network/mcpe/protocol/ServerToClientHandshakePacket.php b/src/pocketmine/network/mcpe/protocol/ServerToClientHandshakePacket.php index 9a223f18a..1759999ea 100644 --- a/src/pocketmine/network/mcpe/protocol/ServerToClientHandshakePacket.php +++ b/src/pocketmine/network/mcpe/protocol/ServerToClientHandshakePacket.php @@ -37,6 +37,12 @@ class ServerToClientHandshakePacket extends DataPacket implements ClientboundPac */ public $jwt; + public static function create(string $jwt) : self{ + $result = new self; + $result->jwt = $jwt; + return $result; + } + public function canBeSentBeforeLogin() : bool{ return true; } diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php index 500453955..d92cb057a 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php @@ -36,6 +36,13 @@ class SetEntityDataPacket extends DataPacket implements ClientboundPacket, Serve /** @var array */ public $metadata; + public static function create(int $entityRuntimeId, array $metadata) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->metadata = $metadata; + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->metadata = $this->getEntityMetadata(); diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php b/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php index d0576a052..7f4a863c6 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php @@ -37,6 +37,13 @@ class SetEntityMotionPacket extends DataPacket implements ClientboundPacket{ /** @var Vector3 */ public $motion; + public static function create(int $entityRuntimeId, Vector3 $motion) : self{ + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->motion = $motion->asVector3(); + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->motion = $this->getVector3(); diff --git a/src/pocketmine/network/mcpe/protocol/SetPlayerGameTypePacket.php b/src/pocketmine/network/mcpe/protocol/SetPlayerGameTypePacket.php index 6ca085859..6e1652773 100644 --- a/src/pocketmine/network/mcpe/protocol/SetPlayerGameTypePacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetPlayerGameTypePacket.php @@ -34,6 +34,12 @@ class SetPlayerGameTypePacket extends DataPacket implements ClientboundPacket, S /** @var int */ public $gamemode; + public static function create(int $gamemode) : self{ + $pk = new self; + $pk->gamemode = $gamemode; + return $pk; + } + protected function decodePayload() : void{ $this->gamemode = $this->getVarInt(); } diff --git a/src/pocketmine/network/mcpe/protocol/SetSpawnPositionPacket.php b/src/pocketmine/network/mcpe/protocol/SetSpawnPositionPacket.php index 21240dd57..8c1231cdf 100644 --- a/src/pocketmine/network/mcpe/protocol/SetSpawnPositionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetSpawnPositionPacket.php @@ -45,6 +45,21 @@ class SetSpawnPositionPacket extends DataPacket implements ClientboundPacket{ /** @var bool */ public $spawnForced; + public static function playerSpawn(int $x, int $y, int $z, bool $forced) : self{ + $result = new self; + $result->spawnType = self::TYPE_PLAYER_SPAWN; + [$result->x, $result->y, $result->z] = [$x, $y, $z]; + $result->spawnForced = $forced; + return $result; + } + + public static function worldSpawn(int $x, int $y, int $z) : self{ + $result = new self; + $result->spawnType = self::TYPE_WORLD_SPAWN; + [$result->x, $result->y, $result->z] = [$x, $y, $z]; + return $result; + } + protected function decodePayload() : void{ $this->spawnType = $this->getVarInt(); $this->getBlockPosition($this->x, $this->y, $this->z); diff --git a/src/pocketmine/network/mcpe/protocol/SetTimePacket.php b/src/pocketmine/network/mcpe/protocol/SetTimePacket.php index b3cd6845a..80acfeebb 100644 --- a/src/pocketmine/network/mcpe/protocol/SetTimePacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetTimePacket.php @@ -33,6 +33,12 @@ class SetTimePacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $time; + public static function create(int $time) : self{ + $result = new self; + $result->time = $time; + return $result; + } + protected function decodePayload() : void{ $this->time = $this->getVarInt(); } diff --git a/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php b/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php index 05c14f4d3..27911c09b 100644 --- a/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php @@ -36,6 +36,13 @@ class TakeItemEntityPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $eid; + public static function create(int $takerEntityRuntimeId, int $itemEntityRuntimeId) : self{ + $result = new self; + $result->target = $takerEntityRuntimeId; + $result->eid = $itemEntityRuntimeId; + return $result; + } + protected function decodePayload() : void{ $this->target = $this->getEntityRuntimeId(); $this->eid = $this->getEntityRuntimeId(); diff --git a/src/pocketmine/network/mcpe/protocol/TextPacket.php b/src/pocketmine/network/mcpe/protocol/TextPacket.php index 2d7ff0fb7..6d372522a 100644 --- a/src/pocketmine/network/mcpe/protocol/TextPacket.php +++ b/src/pocketmine/network/mcpe/protocol/TextPacket.php @@ -58,6 +58,65 @@ class TextPacket extends DataPacket implements ClientboundPacket, ServerboundPac /** @var string */ public $platformChatId = ""; + private static function messageOnly(int $type, string $message) : self{ + $result = new self; + $result->type = $type; + $result->message = $message; + return $result; + } + + private static function baseTranslation(int $type, string $key, array $parameters) : self{ + (function(string ...$_){})(...$parameters); + $result = new self; + $result->type = $type; + $result->needsTranslation = true; + $result->message = $key; + $result->parameters = $parameters; + return $result; + } + + public static function raw(string $message) : self{ + return self::messageOnly(self::TYPE_RAW, $message); + } + + /** + * @param string $key + * @param string[] $parameters + * + * @return TextPacket + */ + public static function translation(string $key, array $parameters = []) : self{ + return self::baseTranslation(self::TYPE_TRANSLATION, $key, $parameters); + } + + public static function popup(string $message) : self{ + return self::messageOnly(self::TYPE_POPUP, $message); + } + + /** + * @param string $key + * @param string[] $parameters + * + * @return TextPacket + */ + public static function translatedPopup(string $key, array $parameters = []) : self{ + return self::baseTranslation(self::TYPE_POPUP, $key, $parameters); + } + + /** + * @param string $key + * @param string[] $parameters + * + * @return TextPacket + */ + public static function jukeboxPopup(string $key, array $parameters = []) : self{ + return self::baseTranslation(self::TYPE_JUKEBOX_POPUP, $key, $parameters); + } + + public static function tip(string $message) : self{ + return self::messageOnly(self::TYPE_TIP, $message); + } + protected function decodePayload() : void{ $this->type = $this->getByte(); $this->needsTranslation = $this->getBool(); diff --git a/src/pocketmine/network/mcpe/protocol/TransferPacket.php b/src/pocketmine/network/mcpe/protocol/TransferPacket.php index c32da8c9f..c1cadb556 100644 --- a/src/pocketmine/network/mcpe/protocol/TransferPacket.php +++ b/src/pocketmine/network/mcpe/protocol/TransferPacket.php @@ -35,6 +35,13 @@ class TransferPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $port = 19132; + public static function create(string $address, int $port) : self{ + $result = new self; + $result->address = $address; + $result->port = $port; + return $result; + } + protected function decodePayload() : void{ $this->address = $this->getString(); $this->port = $this->getLShort(); diff --git a/src/pocketmine/network/mcpe/protocol/UpdateAttributesPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateAttributesPacket.php index 92ebc6b23..c40c99295 100644 --- a/src/pocketmine/network/mcpe/protocol/UpdateAttributesPacket.php +++ b/src/pocketmine/network/mcpe/protocol/UpdateAttributesPacket.php @@ -38,6 +38,20 @@ class UpdateAttributesPacket extends DataPacket implements ClientboundPacket{ /** @var Attribute[] */ public $entries = []; + /** + * @param int $entityRuntimeId + * @param Attribute[] $attributes + * + * @return UpdateAttributesPacket + */ + public static function create(int $entityRuntimeId, array $attributes) : self{ + (function(Attribute ...$attributes){})(...$attributes); + $result = new self; + $result->entityRuntimeId = $entityRuntimeId; + $result->entries = $attributes; + return $result; + } + protected function decodePayload() : void{ $this->entityRuntimeId = $this->getEntityRuntimeId(); $this->entries = $this->getAttributeList(); diff --git a/src/pocketmine/network/mcpe/protocol/UpdateBlockPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateBlockPacket.php index 62e13f711..dbad6185f 100644 --- a/src/pocketmine/network/mcpe/protocol/UpdateBlockPacket.php +++ b/src/pocketmine/network/mcpe/protocol/UpdateBlockPacket.php @@ -51,6 +51,14 @@ class UpdateBlockPacket extends DataPacket implements ClientboundPacket{ /** @var int */ public $dataLayerId = self::DATA_LAYER_NORMAL; + public static function create(int $x, int $y, int $z, int $blockRuntimeId, int $dataLayerId = self::DATA_LAYER_NORMAL) : self{ + $result = new self; + [$result->x, $result->y, $result->z] = [$x, $y, $z]; + $result->blockRuntimeId = $blockRuntimeId; + $result->dataLayerId = $dataLayerId; + return $result; + } + protected function decodePayload() : void{ $this->getBlockPosition($this->x, $this->y, $this->z); $this->blockRuntimeId = $this->getUnsignedVarInt(); diff --git a/src/pocketmine/world/Explosion.php b/src/pocketmine/world/Explosion.php index ee0b86c9e..a7d19bdb1 100644 --- a/src/pocketmine/world/Explosion.php +++ b/src/pocketmine/world/Explosion.php @@ -240,11 +240,7 @@ class Explosion{ $send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z); } - $pk = new ExplodePacket(); - $pk->position = $this->source->asVector3(); - $pk->radius = $this->size; - $pk->records = $send; - $this->world->broadcastPacketToViewers($source, $pk); + $this->world->broadcastPacketToViewers($source, ExplodePacket::create($this->source->asVector3(), $this->size, $send)); $this->world->addParticle($source, new HugeExplodeSeedParticle()); $this->world->addSound($source, new ExplodeSound()); diff --git a/src/pocketmine/world/World.php b/src/pocketmine/world/World.php index f826650c1..9183e525a 100644 --- a/src/pocketmine/world/World.php +++ b/src/pocketmine/world/World.php @@ -715,8 +715,7 @@ class World implements ChunkManager, Metadatable{ * @param Player ...$targets If empty, will send to all players in the world. */ public function sendTime(Player ...$targets){ - $pk = new SetTimePacket(); - $pk->time = $this->time & 0xffffffff; //avoid overflowing the field, since the packet uses an int32 + $pk = SetTimePacket::create($this->time & 0xffffffff); //avoid overflowing the field, since the packet uses an int32 if(empty($targets)){ $this->broadcastGlobalPacket($pk); @@ -934,28 +933,17 @@ class World implements ChunkManager, Metadatable{ if(!($b instanceof Vector3)){ throw new \TypeError("Expected Vector3 in blocks array, got " . (is_object($b) ? get_class($b) : gettype($b))); } - $pk = new UpdateBlockPacket(); - - $pk->x = $b->x; - $pk->y = $b->y; - $pk->z = $b->z; if($b instanceof Block){ - $pk->blockRuntimeId = $b->getRuntimeId(); + $packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, $b->getRuntimeId()); }else{ $fullBlock = $this->getFullBlock($b->x, $b->y, $b->z); - $pk->blockRuntimeId = RuntimeBlockMapping::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf); + $packets[] = UpdateBlockPacket::create($b->x, $b->y, $b->z, RuntimeBlockMapping::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf)); } - $packets[] = $pk; $tile = $this->getTileAt($b->x, $b->y, $b->z); if($tile instanceof Spawnable){ - $tilepk = new BlockEntityDataPacket(); - $tilepk->x = $tile->x; - $tilepk->y = $tile->y; - $tilepk->z = $tile->z; - $tilepk->namedtag = $tile->getSerializedSpawnCompound(); - $packets[] = $tilepk; + $packets[] = BlockEntityDataPacket::create($tile->x, $tile->y, $tile->z, $tile->getSerializedSpawnCompound()); } } diff --git a/src/pocketmine/world/particle/FloatingTextParticle.php b/src/pocketmine/world/particle/FloatingTextParticle.php index d8efe445b..02ea68a3f 100644 --- a/src/pocketmine/world/particle/FloatingTextParticle.php +++ b/src/pocketmine/world/particle/FloatingTextParticle.php @@ -84,20 +84,14 @@ class FloatingTextParticle implements Particle{ if($this->entityId === null){ $this->entityId = EntityFactory::nextRuntimeId(); }else{ - $pk0 = new RemoveEntityPacket(); - $pk0->entityUniqueId = $this->entityId; - - $p[] = $pk0; + $p[] = RemoveEntityPacket::create($this->entityId); } if(!$this->invisible){ $uuid = UUID::fromRandom(); $name = $this->title . ($this->text !== "" ? "\n" . $this->text : ""); - $add = new PlayerListPacket(); - $add->type = PlayerListPacket::TYPE_ADD; - $add->entries = [PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, new Skin("Standard_Custom", str_repeat("\x00", 8192)))]; - $p[] = $add; + $p[] = PlayerListPacket::add([PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, new Skin("Standard_Custom", str_repeat("\x00", 8192)))]); $pk = new AddPlayerPacket(); $pk->uuid = $uuid; @@ -116,10 +110,7 @@ class FloatingTextParticle implements Particle{ $p[] = $pk; - $remove = new PlayerListPacket(); - $remove->type = PlayerListPacket::TYPE_REMOVE; - $remove->entries = [PlayerListEntry::createRemovalEntry($uuid)]; - $p[] = $remove; + $p[] = PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($uuid)]); } return $p;