pocketmine\Player::handleDataPacket PHP Method

handleDataPacket() public method

WARNING: Do not use this, it's only for internal use. Changes to this function won't be recorded on the version.
public handleDataPacket ( DataPacket $packet )
$packet pocketmine\network\protocol\DataPacket
    public function handleDataPacket(DataPacket $packet)
    {
        if ($this->connected === false) {
            return;
        }
        if ($packet::NETWORK_ID === ProtocolInfo::BATCH_PACKET) {
            /** @var BatchPacket $packet */
            $this->server->getNetwork()->processBatch($packet, $this);
            return;
        }
        $timings = Timings::getReceiveDataPacketTimings($packet);
        $timings->startTiming();
        $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
        if ($ev->isCancelled()) {
            $timings->stopTiming();
            return;
        }
        switch ($packet::NETWORK_ID) {
            case ProtocolInfo::ITEM_FRAME_DROP_ITEM_PACKET:
                $tile = $this->level->getTile($this->temporalVector->setComponents($packet->x, $packet->y, $packet->z));
                if ($tile instanceof ItemFrame) {
                    $block = $this->level->getBlock($tile);
                    $this->server->getPluginManager()->callEvent($ev = new BlockBreakEvent($this, $block, $this->getInventory()->getItemInHand(), true));
                    if (!$ev->isCancelled()) {
                        $item = $tile->getItem();
                        $this->server->getPluginManager()->callEvent($ev = new ItemFrameDropItemEvent($this, $block, $tile, $item));
                        if (!$ev->isCancelled()) {
                            if ($item->getId() !== Item::AIR) {
                                if (mt_rand(0, 10) / 10 < $tile->getItemDropChance()) {
                                    $this->level->dropItem($tile, $item);
                                }
                                $tile->setItem(Item::get(Item::AIR));
                                $tile->setItemRotation(0);
                            }
                        } else {
                            $tile->spawnTo($this);
                        }
                    } else {
                        $tile->spawnTo($this);
                    }
                }
                break;
            case ProtocolInfo::REQUEST_CHUNK_RADIUS_PACKET:
                /*if($this->spawned){
                			$this->viewDistance = $packet->radius ** 2;
                		}*/
                $pk = new ChunkRadiusUpdatedPacket();
                $pk->radius = $this->server->chunkRadius != -1 ? $this->server->chunkRadius : $packet->radius;
                $this->dataPacket($pk);
                break;
            case ProtocolInfo::PLAYER_INPUT_PACKET:
                break;
            case ProtocolInfo::LOGIN_PACKET:
                if ($this->loggedIn) {
                    break;
                }
                $pk = new PlayStatusPacket();
                $pk->status = PlayStatusPacket::LOGIN_SUCCESS;
                $this->dataPacket($pk);
                $this->username = TextFormat::clean($packet->username);
                $this->displayName = $this->username;
                $this->setNameTag($this->username);
                $this->iusername = strtolower($this->username);
                $this->protocol = $packet->protocol;
                if ($this->server->getConfigBoolean("online-mode", false) && $packet->identityPublicKey === null) {
                    $this->kick("disconnectionScreen.notAuthenticated", false);
                    break;
                }
                if (count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)) {
                    break;
                }
                if (!in_array($packet->protocol, ProtocolInfo::ACCEPTED_PROTOCOLS)) {
                    if ($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL) {
                        $message = "disconnectionScreen.outdatedClient";
                        $pk = new PlayStatusPacket();
                        $pk->status = PlayStatusPacket::LOGIN_FAILED_CLIENT;
                        $this->directDataPacket($pk);
                    } else {
                        $message = "disconnectionScreen.outdatedServer";
                        $pk = new PlayStatusPacket();
                        $pk->status = PlayStatusPacket::LOGIN_FAILED_SERVER;
                        $this->directDataPacket($pk);
                    }
                    $this->close("", $message, false);
                    break;
                }
                $this->randomClientId = $packet->clientId;
                $this->uuid = UUID::fromString($packet->clientUUID);
                $this->rawUUID = $this->uuid->toBinary();
                $valid = true;
                $len = strlen($packet->username);
                if ($len > 16 or $len < 3) {
                    $valid = false;
                }
                for ($i = 0; $i < $len and $valid; ++$i) {
                    $c = ord($packet->username[$i]);
                    if ($c >= ord("a") and $c <= ord("z") or $c >= ord("A") and $c <= ord("Z") or $c >= ord("0") and $c <= ord("9") or $c === ord("_")) {
                        continue;
                    }
                    $valid = false;
                    break;
                }
                if (!$valid or $this->iusername === "rcon" or $this->iusername === "console") {
                    $this->close("", "disconnectionScreen.invalidName");
                    break;
                }
                if (strlen($packet->skin) != 64 * 64 * 4 and strlen($packet->skin) != 64 * 32 * 4) {
                    $this->close("", "disconnectionScreen.invalidSkin");
                    break;
                }
                $this->setSkin($packet->skin, $packet->skinId);
                $this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
                if ($ev->isCancelled()) {
                    $this->close("", $ev->getKickMessage());
                    break;
                }
                if ($this->isConnected()) {
                    $this->onPlayerPreLogin();
                }
                break;
            case ProtocolInfo::MOVE_PLAYER_PACKET:
                if ($this->linkedEntity instanceof Entity) {
                    $entity = $this->linkedEntity;
                    if ($entity instanceof Boat) {
                        $entity->setPosition($this->temporalVector->setComponents($packet->x, $packet->y - 0.3, $packet->z));
                    }
                    /*if($entity instanceof Minecart){
                    			$entity->isFreeMoving = true;
                    			$entity->motionX = -sin($packet->yaw / 180 * M_PI);
                    			$entity->motionZ = cos($packet->yaw / 180 * M_PI);
                    		}*/
                }
                $newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
                $revert = false;
                if (!$this->isAlive() or $this->spawned !== true) {
                    $revert = true;
                    $this->forceMovement = new Vector3($this->x, $this->y, $this->z);
                }
                if ($this->teleportPosition !== null or $this->forceMovement instanceof Vector3 and (($dist = $newPos->distanceSquared($this->forceMovement)) > 0.1 or $revert)) {
                    if ($this->forceMovement instanceof Vector3) {
                        $this->sendPosition($this->forceMovement, $packet->yaw, $packet->pitch);
                    }
                } else {
                    $packet->yaw %= 360;
                    $packet->pitch %= 360;
                    if ($packet->yaw < 0) {
                        $packet->yaw += 360;
                    }
                    $this->setRotation($packet->yaw, $packet->pitch);
                    $this->newPosition = $newPos;
                }
                $this->forceMovement = null;
                break;
            case ProtocolInfo::MOB_EQUIPMENT_PACKET:
                if ($this->spawned === false or !$this->isAlive()) {
                    break;
                }
                /**
                 * Handle hotbar slot remapping
                 * This is the only time and place when hotbar mapping should ever be changed.
                 * Changing hotbar slot mapping at will has been deprecated because it causes far too many
                 * issues with Windows 10 Edition Beta.
                 */
                $this->inventory->setHeldItemIndex($packet->selectedSlot, false, $packet->slot);
                $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
                break;
            case ProtocolInfo::USE_ITEM_PACKET:
                if ($this->spawned === false or !$this->isAlive() or $this->blocked) {
                    break;
                }
                $blockVector = new Vector3($packet->x, $packet->y, $packet->z);
                $this->craftingType = self::CRAFTING_SMALL;
                if ($packet->face >= 0 and $packet->face <= 5) {
                    //Use Block, place
                    $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
                    if (!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()) {
                    } elseif ($this->isCreative()) {
                        $item = $this->inventory->getItemInHand();
                        if ($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true) {
                            break;
                        }
                    } elseif (!$this->inventory->getItemInHand()->deepEquals($packet->item)) {
                        $this->inventory->sendHeldItem($this);
                    } else {
                        $item = $this->inventory->getItemInHand();
                        $oldItem = clone $item;
                        if ($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this)) {
                            if (!$item->deepEquals($oldItem) or $item->getCount() !== $oldItem->getCount()) {
                                $this->inventory->setItemInHand($item);
                                $this->inventory->sendHeldItem($this->hasSpawned);
                            }
                            break;
                        }
                    }
                    $this->inventory->sendHeldItem($this);
                    if ($blockVector->distanceSquared($this) > 10000) {
                        break;
                    }
                    $target = $this->level->getBlock($blockVector);
                    $block = $target->getSide($packet->face);
                    $this->level->sendBlocks([$this], [$target, $block], UpdateBlockPacket::FLAG_ALL_PRIORITY);
                    break;
                } elseif ($packet->face === 0xff) {
                    if ($this->isSpectator()) {
                        break;
                    }
                    $aimPos = (new Vector3($packet->x / 32768, $packet->y / 32768, $packet->z / 32768))->normalize();
                    if ($this->isCreative()) {
                        $item = $this->inventory->getItemInHand();
                    } elseif (!$this->inventory->getItemInHand()->deepEquals($packet->item)) {
                        $this->inventory->sendHeldItem($this);
                        break;
                    } else {
                        $item = $this->inventory->getItemInHand();
                    }
                    $ev = new PlayerInteractEvent($this, $item, $aimPos, $packet->face, PlayerInteractEvent::RIGHT_CLICK_AIR);
                    $this->server->getPluginManager()->callEvent($ev);
                    if ($ev->isCancelled()) {
                        $this->inventory->sendHeldItem($this);
                        break;
                    }
                    if ($item->getId() === Item::FISHING_ROD) {
                        if ($this->isFishing()) {
                            $this->server->getPluginManager()->callEvent($ev = new PlayerUseFishingRodEvent($this, PlayerUseFishingRodEvent::ACTION_STOP_FISHING));
                        } else {
                            $this->server->getPluginManager()->callEvent($ev = new PlayerUseFishingRodEvent($this, PlayerUseFishingRodEvent::ACTION_START_FISHING));
                        }
                        if (!$ev->isCancelled()) {
                            if ($this->isFishing()) {
                                $this->setFishingHook();
                            } else {
                                $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)])]);
                                $f = 0.6;
                                $this->fishingHook = new FishingHook($this->chunk, $nbt, $this);
                                $this->fishingHook->setMotion($this->fishingHook->getMotion()->multiply($f));
                                $this->fishingHook->spawnToAll();
                            }
                        }
                    } elseif ($item->getId() === Item::SNOWBALL) {
                        $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)])]);
                        $f = 1.5;
                        $snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this);
                        $snowball->setMotion($snowball->getMotion()->multiply($f));
                        if ($this->isSurvival()) {
                            $item->setCount($item->getCount() - 1);
                            $this->inventory->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
                        }
                        if ($snowball instanceof Projectile) {
                            $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($snowball));
                            if ($projectileEv->isCancelled()) {
                                $snowball->kill();
                            } else {
                                $snowball->spawnToAll();
                                $this->level->addSound(new LaunchSound($this), $this->getViewers());
                            }
                        } else {
                            $snowball->spawnToAll();
                        }
                    } elseif ($item->getId() === Item::EGG) {
                        $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)])]);
                        $f = 1.5;
                        $egg = Entity::createEntity("Egg", $this->chunk, $nbt, $this);
                        $egg->setMotion($egg->getMotion()->multiply($f));
                        if ($this->isSurvival()) {
                            $item->setCount($item->getCount() - 1);
                            $this->inventory->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
                        }
                        if ($egg instanceof Projectile) {
                            $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($egg));
                            if ($projectileEv->isCancelled()) {
                                $egg->kill();
                            } else {
                                $egg->spawnToAll();
                                $this->level->addSound(new LaunchSound($this), $this->getViewers());
                            }
                        } else {
                            $egg->spawnToAll();
                        }
                    } elseif ($item->getId() == Item::ENCHANTING_BOTTLE) {
                        $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)])]);
                        $f = 1.1;
                        $thrownExpBottle = new ThrownExpBottle($this->chunk, $nbt, $this);
                        $thrownExpBottle->setMotion($thrownExpBottle->getMotion()->multiply($f));
                        if ($this->isSurvival()) {
                            $item->setCount($item->getCount() - 1);
                            $this->inventory->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
                        }
                        if ($thrownExpBottle instanceof Projectile) {
                            $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($thrownExpBottle));
                            if ($projectileEv->isCancelled()) {
                                $thrownExpBottle->kill();
                            } else {
                                $thrownExpBottle->spawnToAll();
                                $this->level->addSound(new LaunchSound($this), $this->getViewers());
                            }
                        } else {
                            $thrownExpBottle->spawnToAll();
                        }
                    } elseif ($item->getId() == Item::SPLASH_POTION and $this->server->allowSplashPotion) {
                        $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)]), "PotionId" => new ShortTag("PotionId", $item->getDamage())]);
                        $f = 1.1;
                        $thrownPotion = new ThrownPotion($this->chunk, $nbt, $this);
                        $thrownPotion->setMotion($thrownPotion->getMotion()->multiply($f));
                        if ($this->isSurvival()) {
                            $item->setCount($item->getCount() - 1);
                            $this->inventory->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
                        }
                        if ($thrownPotion instanceof Projectile) {
                            $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($thrownPotion));
                            if ($projectileEv->isCancelled()) {
                                $thrownPotion->kill();
                            } else {
                                $thrownPotion->spawnToAll();
                                $this->level->addSound(new LaunchSound($this), $this->getViewers());
                            }
                        } else {
                            $thrownPotion->spawnToAll();
                        }
                    }
                    $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, true);
                    $this->startAction = $this->server->getTick();
                }
                break;
            case ProtocolInfo::PLAYER_ACTION_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive() and $packet->action !== PlayerActionPacket::ACTION_SPAWN_SAME_DIMENSION and $packet->action !== PlayerActionPacket::ACTION_SPAWN_OVERWORLD) {
                    break;
                }
                $packet->eid = $this->id;
                $pos = new Vector3($packet->x, $packet->y, $packet->z);
                switch ($packet->action) {
                    case PlayerActionPacket::ACTION_START_BREAK:
                        //Fixes fire breaking in creative.
                        if ($pos->distanceSquared($this) > 10000) {
                            break;
                        }
                        $target = $this->level->getBlock($pos);
                        $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, $packet->face, $target->getId() === 0 ? PlayerInteractEvent::LEFT_CLICK_AIR : PlayerInteractEvent::LEFT_CLICK_BLOCK);
                        $this->getServer()->getPluginManager()->callEvent($ev);
                        if (!$ev->isCancelled()) {
                            $side = $target->getSide($packet->face);
                            if ($side instanceof Fire) {
                                $side->getLevel()->setBlock($side, new Air());
                            }
                            $this->lastBreak = microtime(true);
                        } else {
                            $this->inventory->sendHeldItem($this);
                        }
                        break;
                    case PlayerActionPacket::ACTION_ABORT_BREAK:
                        $this->lastBreak = PHP_INT_MAX;
                        break;
                    case PlayerActionPacket::ACTION_RELEASE_ITEM:
                        if ($this->startAction > -1 and $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION)) {
                            if ($this->inventory->getItemInHand()->getId() === Item::BOW) {
                                $bow = $this->inventory->getItemInHand();
                                if ($this->isSurvival() and !$this->inventory->contains(Item::get(Item::ARROW, null))) {
                                    $this->inventory->sendContents($this);
                                    break;
                                }
                                $arrow = false;
                                foreach ($this->inventory->getContents() as $item) {
                                    if ($item->getId() == Item::ARROW) {
                                        $arrow = $item;
                                    }
                                }
                                if ($arrow === false and $this->isCreative()) {
                                    $arrow = Item::get(Item::ARROW, 0, 1);
                                } elseif ($arrow === false) {
                                    break;
                                }
                                $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x), new DoubleTag("", $this->y + $this->getEyeHeight()), new DoubleTag("", $this->z)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new DoubleTag("", -sin($this->pitch / 180 * M_PI)), new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $this->yaw), new FloatTag("", $this->pitch)]), "Fire" => new ShortTag("Fire", $this->isOnFire() ? 45 * 60 : 0), "Potion" => new ShortTag("Potion", $arrow->getDamage())]);
                                $diff = $this->server->getTick() - $this->startAction;
                                $p = $diff / 20;
                                $f = min(($p ** 2 + $p * 2) / 3, 1) * 2;
                                $ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this, $f == 2 ? true : false), $f);
                                if ($f < 0.1 or $diff < 5) {
                                    $ev->setCancelled();
                                }
                                $this->server->getPluginManager()->callEvent($ev);
                                if ($ev->isCancelled()) {
                                    $ev->getProjectile()->kill();
                                    $this->inventory->sendContents($this);
                                } else {
                                    $ev->getProjectile()->setMotion($ev->getProjectile()->getMotion()->multiply($ev->getForce()));
                                    if ($this->isSurvival()) {
                                        $this->inventory->removeItem(Item::get(Item::ARROW, $arrow->getDamage(), 1));
                                        $bow->setDamage($bow->getDamage() + 1);
                                        if ($bow->getDamage() >= 385) {
                                            $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0));
                                        } else {
                                            $this->inventory->setItemInHand($bow);
                                        }
                                    }
                                    if ($ev->getProjectile() instanceof Projectile) {
                                        $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($ev->getProjectile()));
                                        if ($projectileEv->isCancelled()) {
                                            $ev->getProjectile()->kill();
                                        } else {
                                            $ev->getProjectile()->spawnToAll();
                                            $this->level->addSound(new LaunchSound($this), $this->getViewers());
                                        }
                                    } else {
                                        $ev->getProjectile()->spawnToAll();
                                    }
                                }
                            }
                        } elseif ($this->inventory->getItemInHand()->getId() === Item::BUCKET and $this->inventory->getItemInHand()->getDamage() === 1) {
                            //Milk!
                            $this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $this->inventory->getItemInHand()));
                            if ($ev->isCancelled()) {
                                $this->inventory->sendContents($this);
                                break;
                            }
                            $pk = new EntityEventPacket();
                            $pk->eid = $this->getId();
                            $pk->event = EntityEventPacket::USE_ITEM;
                            //$pk;
                            $this->dataPacket($pk);
                            Server::broadcastPacket($this->getViewers(), $pk);
                            if ($this->isSurvival()) {
                                $slot = $this->inventory->getItemInHand();
                                --$slot->count;
                                $this->inventory->setItemInHand($slot);
                                $this->inventory->addItem(Item::get(Item::BUCKET, 0, 1));
                            }
                            $this->removeAllEffects();
                        } else {
                            $this->inventory->sendContents($this);
                        }
                        break;
                    case PlayerActionPacket::ACTION_STOP_SLEEPING:
                        $this->stopSleep();
                        break;
                    case PlayerActionPacket::ACTION_SPAWN_SAME_DIMENSION:
                    case PlayerActionPacket::ACTION_SPAWN_OVERWORLD:
                        if ($this->isAlive() or !$this->isOnline()) {
                            break;
                        }
                        if ($this->server->isHardcore()) {
                            $this->setBanned(true);
                            break;
                        }
                        $this->craftingType = self::CRAFTING_SMALL;
                        if ($this->server->netherEnabled) {
                            if ($this->level == $this->server->netherLevel) {
                                $this->teleport($pos = $this->server->getDefaultLevel()->getSafeSpawn());
                            }
                        }
                        $this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
                        $this->teleport($ev->getRespawnPosition());
                        $this->setSprinting(false);
                        $this->setSneaking(false);
                        $this->extinguish();
                        $this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 300);
                        $this->deadTicks = 0;
                        $this->noDamageTicks = 60;
                        $this->removeAllEffects();
                        $this->setHealth($this->getMaxHealth());
                        $this->setFood(20);
                        $this->starvationTick = 0;
                        $this->foodTick = 0;
                        $this->foodUsageTime = 0;
                        $this->sendData($this);
                        $this->sendSettings();
                        $this->inventory->sendContents($this);
                        $this->inventory->sendArmorContents($this);
                        $this->blocked = false;
                        $this->spawnToAll();
                        $this->scheduleUpdate();
                        break;
                    case PlayerActionPacket::ACTION_START_SPRINT:
                        $ev = new PlayerToggleSprintEvent($this, true);
                        $this->server->getPluginManager()->callEvent($ev);
                        if ($ev->isCancelled()) {
                            $this->sendData($this);
                        } else {
                            $this->setSprinting(true);
                        }
                        break 2;
                    case PlayerActionPacket::ACTION_STOP_SPRINT:
                        $ev = new PlayerToggleSprintEvent($this, false);
                        $this->server->getPluginManager()->callEvent($ev);
                        if ($ev->isCancelled()) {
                            $this->sendData($this);
                        } else {
                            $this->setSprinting(false);
                        }
                        break 2;
                    case PlayerActionPacket::ACTION_START_SNEAK:
                        $ev = new PlayerToggleSneakEvent($this, true);
                        $this->server->getPluginManager()->callEvent($ev);
                        if ($ev->isCancelled()) {
                            $this->sendData($this);
                        } else {
                            $this->setSneaking(true);
                        }
                        break 2;
                    case PlayerActionPacket::ACTION_STOP_SNEAK:
                        $ev = new PlayerToggleSneakEvent($this, false);
                        $this->server->getPluginManager()->callEvent($ev);
                        if ($ev->isCancelled()) {
                            $this->sendData($this);
                        } else {
                            $this->setSneaking(false);
                        }
                        break 2;
                    case PlayerActionPacket::ACTION_JUMP:
                        break 2;
                }
                $this->startAction = -1;
                $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
                break;
            case ProtocolInfo::REMOVE_BLOCK_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                $vector = new Vector3($packet->x, $packet->y, $packet->z);
                $item = $this->inventory->getItemInHand();
                $oldItem = clone $item;
                if ($this->canInteract($vector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 6) and $this->level->useBreakOn($vector, $item, $this, $this->server->destroyBlockParticle)) {
                    if ($this->isSurvival()) {
                        if (!$item->equals($oldItem) or $item->getCount() !== $oldItem->getCount()) {
                            $this->inventory->setItemInHand($item);
                            $this->inventory->sendHeldItem($this);
                        }
                        $this->exhaust(0.025, PlayerExhaustEvent::CAUSE_MINING);
                    }
                    break;
                }
                $this->inventory->sendContents($this);
                $target = $this->level->getBlock($vector);
                $tile = $this->level->getTile($vector);
                $this->level->sendBlocks([$this], [$target], UpdateBlockPacket::FLAG_ALL_PRIORITY);
                $this->inventory->sendHeldItem($this);
                if ($tile instanceof Spawnable) {
                    $tile->spawnTo($this);
                }
                break;
            case ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET:
                //This packet is ignored. Armour changes are also sent by ContainerSetSlotPackets, and are handled there instead.
                break;
            case ProtocolInfo::INTERACT_PACKET:
                if ($this->spawned === false or !$this->isAlive() or $this->blocked) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                $target = $this->level->getEntity($packet->target);
                $cancelled = false;
                if ($target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false) {
                    $cancelled = true;
                }
                if ($target instanceof Boat or $target instanceof Minecart and $target->getType() == Minecart::TYPE_NORMAL) {
                    if ($packet->action === InteractPacket::ACTION_RIGHT_CLICK) {
                        $this->linkEntity($target);
                    } elseif ($packet->action === InteractPacket::ACTION_LEFT_CLICK) {
                        if ($this->linkedEntity == $target) {
                            $target->setLinked(0, $this);
                        }
                        $target->close();
                    } elseif ($packet->action === InteractPacket::ACTION_LEAVE_VEHICLE) {
                        $this->setLinked(0, $target);
                    }
                    return;
                }
                if ($packet->action === InteractPacket::ACTION_RIGHT_CLICK) {
                    if ($target instanceof Animal and $this->getInventory()->getItemInHand()) {
                        //TODO: Feed
                    }
                    break;
                }
                if ($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->isAlive() and $target->isAlive()) {
                    if ($target instanceof DroppedItem or $target instanceof Arrow) {
                        $this->kick("Attempting to attack an invalid entity");
                        $this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidEntity", [$this->getName()]));
                        break;
                    }
                    $item = $this->inventory->getItemInHand();
                    $damage = [EntityDamageEvent::MODIFIER_BASE => $item->getModifyAttackDamage($target)];
                    if (!$this->canInteract($target, 8)) {
                        $cancelled = true;
                    } elseif ($target instanceof Player) {
                        if (($target->getGamemode() & 0x1) > 0) {
                            break;
                        } elseif ($this->server->getConfigBoolean("pvp") !== true or $this->server->getDifficulty() === 0) {
                            $cancelled = true;
                        }
                    }
                    $ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage, 0.4 + $item->getEnchantmentLevel(Enchantment::TYPE_WEAPON_KNOCKBACK) * 0.15);
                    if ($cancelled) {
                        $ev->setCancelled();
                    }
                    if ($target->attack($ev->getFinalDamage(), $ev) === true) {
                        $fireAspectL = $item->getEnchantmentLevel(Enchantment::TYPE_WEAPON_FIRE_ASPECT);
                        if ($fireAspectL > 0) {
                            $fireEv = new EntityCombustByEntityEvent($this, $target, $fireAspectL * 4, $ev->getFireProtectL());
                            Server::getInstance()->getPluginManager()->callEvent($fireEv);
                            if (!$fireEv->isCancelled()) {
                                $target->setOnFire($fireEv->getDuration());
                            }
                        }
                        //Thorns
                        if ($this->isSurvival()) {
                            $ev->createThornsDamage();
                            if ($ev->getThornsDamage() > 0) {
                                $thornsEvent = new EntityDamageByEntityEvent($target, $this, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $ev->getThornsDamage(), 0);
                                if (!$thornsEvent->isCancelled()) {
                                    if ($this->attack($thornsEvent->getFinalDamage(), $thornsEvent) === true) {
                                        $thornsEvent->useArmors();
                                        $ev->setThornsArmorUse();
                                    }
                                }
                            }
                        }
                        $ev->useArmors();
                    }
                    if ($ev->isCancelled()) {
                        if ($item->isTool() and $this->isSurvival()) {
                            $this->inventory->sendContents($this);
                        }
                        break;
                    }
                    if ($this->isSurvival()) {
                        if ($item->isTool()) {
                            if ($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()) {
                                $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
                            } else {
                                $this->inventory->setItemInHand($item);
                            }
                        }
                        $this->exhaust(0.3, PlayerExhaustEvent::CAUSE_ATTACK);
                    }
                }
                break;
            case ProtocolInfo::ANIMATE_PACKET:
                if ($this->spawned === false or !$this->isAlive()) {
                    break;
                }
                $this->server->getPluginManager()->callEvent($ev = new PlayerAnimationEvent($this, $packet->action));
                if ($ev->isCancelled()) {
                    break;
                }
                $pk = new AnimatePacket();
                $pk->eid = $this->getId();
                $pk->action = $ev->getAnimationType();
                Server::broadcastPacket($this->getViewers(), $pk);
                break;
            case ProtocolInfo::SET_HEALTH_PACKET:
                //Not used
                break;
            case ProtocolInfo::ENTITY_EVENT_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
                //TODO: check if this should be true
                switch ($packet->event) {
                    case EntityEventPacket::USE_ITEM:
                        //Eating
                        $slot = $this->inventory->getItemInHand();
                        if ($slot->canBeConsumed()) {
                            $ev = new PlayerItemConsumeEvent($this, $slot);
                            if (!$slot->canBeConsumedBy($this)) {
                                $ev->setCancelled();
                            }
                            $this->server->getPluginManager()->callEvent($ev);
                            if (!$ev->isCancelled()) {
                                $slot->onConsume($this);
                            } else {
                                $this->inventory->sendContents($this);
                            }
                        }
                        break;
                }
                break;
            case ProtocolInfo::DROP_ITEM_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                    break;
                }
                if ($packet->item->getId() === Item::AIR) {
                    /**
                     * This is so stupid it's unreal.
                     * Windows 10 Edition Beta drops the contents of the crafting grid when the inventory closes - including air.
                     */
                    break;
                }
                if ($this->isCreative() and $this->server->limitedCreative) {
                    break;
                }
                $this->getTransactionQueue()->addTransaction(new DropItemTransaction($packet->item));
                break;
            case ProtocolInfo::TEXT_PACKET:
                if ($this->spawned === false or !$this->isAlive()) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                if ($packet->type === TextPacket::TYPE_CHAT) {
                    $packet->message = TextFormat::clean($packet->message, $this->removeFormat);
                    foreach (explode("\n", $packet->message) as $message) {
                        if (trim($message) != "" and strlen($message) <= 255 and $this->messageCounter-- > 0) {
                            $ev = new PlayerCommandPreprocessEvent($this, $message);
                            if (mb_strlen($ev->getMessage(), "UTF-8") > 320) {
                                $ev->setCancelled();
                            }
                            $this->server->getPluginManager()->callEvent($ev);
                            if ($ev->isCancelled()) {
                                break;
                            }
                            if (substr($ev->getMessage(), 0, 1) === "/") {
                                //Command
                                Timings::$playerCommandTimer->startTiming();
                                $this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 1));
                                Timings::$playerCommandTimer->stopTiming();
                            } else {
                                $this->server->getPluginManager()->callEvent($ev = new PlayerChatEvent($this, $ev->getMessage()));
                                if (!$ev->isCancelled()) {
                                    $this->server->broadcastMessage($this->getServer()->getLanguage()->translateString($ev->getFormat(), [$ev->getPlayer()->getDisplayName(), $ev->getMessage()]), $ev->getRecipients());
                                }
                            }
                        }
                    }
                }
                break;
            case ProtocolInfo::CONTAINER_CLOSE_PACKET:
                if ($this->spawned === false or $packet->windowid === 0) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                if (isset($this->windowIndex[$packet->windowid])) {
                    $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this));
                    $this->removeWindow($this->windowIndex[$packet->windowid]);
                }
                /**
                 * Drop anything still left in the crafting inventory
                 * This will usually never be needed since Windows 10 clients will send DropItemPackets
                 * which will cause this to happen anyway, but this is here for when transactions
                 * fail and items end up stuck in the crafting inventory.
                 */
                foreach ($this->getFloatingInventory()->getContents() as $item) {
                    $this->getTransactionQueue()->addTransaction(new DropItemTransaction($item));
                }
                break;
            case ProtocolInfo::CRAFTING_EVENT_PACKET:
                if ($this->spawned === false or !$this->isAlive()) {
                    break;
                }
                /**
                 * For some annoying reason, anvils send window ID 255 when crafting with them instead of the _actual_ anvil window ID
                 * The result of this is anvils immediately closing when used. This is highly unusual, especially since the
                 * container set slot packets send the correct window ID, but... eh
                 */
                /*elseif(!isset($this->windowIndex[$packet->windowId])){
                			$this->inventory->sendContents($this);
                			$pk = new ContainerClosePacket();
                			$pk->windowid = $packet->windowId;
                			$this->dataPacket($pk);
                			break;
                		}*/
                $recipe = $this->server->getCraftingManager()->getRecipe($packet->id);
                if ($this->craftingType === self::CRAFTING_ANVIL) {
                    $anvilInventory = $this->windowIndex[$packet->windowId] ?? null;
                    if ($anvilInventory === null) {
                        foreach ($this->windowIndex as $window) {
                            if ($window instanceof AnvilInventory) {
                                $anvilInventory = $window;
                                break;
                            }
                        }
                        if ($anvilInventory === null) {
                            //If it's _still_ null, then the player doesn't have a valid anvil window, cannot proceed.
                            $this->getServer()->getLogger()->debug("Couldn't find an anvil window for " . $this->getName() . ", exiting");
                            $this->inventory->sendContents($this);
                            break;
                        }
                    }
                    if ($recipe === null) {
                        //Item renamed
                        if (!$anvilInventory->onRename($this, $packet->output[0])) {
                            $this->getServer()->getLogger()->debug($this->getName() . " failed to rename an item in an anvil");
                            $this->inventory->sendContents($this);
                        }
                    } else {
                        //TODO: Anvil crafting recipes
                    }
                    break;
                } elseif (($recipe instanceof BigShapelessRecipe or $recipe instanceof BigShapedRecipe) and $this->craftingType === 0) {
                    $this->server->getLogger()->debug("Received big crafting recipe from " . $this->getName() . " with no crafting table open");
                    $this->inventory->sendContents($this);
                    break;
                } elseif ($recipe === null) {
                    $this->server->getLogger()->debug("Null (unknown) crafting recipe received from " . $this->getName() . " for " . $packet->output[0]);
                    $this->inventory->sendContents($this);
                    break;
                }
                /** @var Item $item */
                foreach ($packet->input as $i => $item) {
                    if ($item->getDamage() === -1 or $item->getDamage() === 0xffff) {
                        $item->setDamage(null);
                    }
                    if ($i < 9 and $item->getId() > 0) {
                        //TODO: Get rid of this hack.
                        $item->setCount(1);
                    }
                }
                $canCraft = true;
                if (count($packet->input) === 0) {
                    /* If the packet "input" field is empty this needs to be handled differently.
                     * "input" is used to tell the server what items to remove from the client's inventory
                     * Because crafting takes the materials in the crafting grid, nothing needs to be taken from the inventory
                     * Instead, we take the materials from the crafting inventory
                     * To know what materials we need to take, we have to guess the crafting recipe used based on the
                     * output item and the materials stored in the crafting items
                     * The reason we have to guess is because Win10 sometimes sends a different recipe UUID
                     * say, if you put the wood for a door in the right hand side of the crafting grid instead of the left
                     * it will send the recipe UUID for a wooden pressure plate. Unknown currently whether this is a client
                     * bug or if there is something wrong with the way the server handles recipes.
                     * TODO: Remove recipe correction and fix desktop crafting recipes properly.
                     * In fact, TODO: Rewrite crafting entirely.
                     */
                    $possibleRecipes = $this->server->getCraftingManager()->getRecipesByResult($packet->output[0]);
                    if (!$packet->output[0]->deepEquals($recipe->getResult())) {
                        $this->server->getLogger()->debug("Mismatched desktop recipe received from player " . $this->getName() . ", expected " . $recipe->getResult() . ", got " . $packet->output[0]);
                    }
                    $recipe = null;
                    foreach ($possibleRecipes as $r) {
                        /* Check the ingredient list and see if it matches the ingredients we've put into the crafting grid
                         * As soon as we find a recipe that we have all the ingredients for, take it and run with it. */
                        //Make a copy of the floating inventory that we can make changes to.
                        $floatingInventory = clone $this->floatingInventory;
                        $ingredients = $r->getIngredientList();
                        //Check we have all the necessary ingredients.
                        foreach ($ingredients as $ingredient) {
                            if (!$floatingInventory->contains($ingredient)) {
                                //We're short on ingredients, try the next recipe
                                $canCraft = false;
                                break;
                            }
                            //This will only be reached if we have the item to take away.
                            $floatingInventory->removeItem($ingredient);
                        }
                        if ($canCraft) {
                            //Found a recipe that works, take it and run with it.
                            $recipe = $r;
                            break;
                        }
                    }
                    if ($recipe !== null) {
                        $this->server->getPluginManager()->callEvent($ev = new CraftItemEvent($this, $ingredients, $recipe));
                        if ($ev->isCancelled()) {
                            $this->inventory->sendContents($this);
                            break;
                        }
                        $this->floatingInventory = $floatingInventory;
                        //Set player crafting inv to the idea one created in this process
                        $this->floatingInventory->addItem(clone $recipe->getResult());
                        //Add the result to our picture of the crafting inventory
                    } else {
                        $this->server->getLogger()->debug("Unmatched desktop crafting recipe " . $packet->id . " from player " . $this->getName());
                        $this->inventory->sendContents($this);
                        break;
                    }
                } else {
                    if ($recipe instanceof ShapedRecipe) {
                        for ($x = 0; $x < 3 and $canCraft; ++$x) {
                            for ($y = 0; $y < 3; ++$y) {
                                $item = $packet->input[$y * 3 + $x];
                                $ingredient = $recipe->getIngredient($x, $y);
                                if ($item->getCount() > 0 and $item->getId() > 0) {
                                    if ($ingredient == null) {
                                        $canCraft = false;
                                        break;
                                    }
                                    if ($ingredient->getId() != 0 and !$ingredient->deepEquals($item, $ingredient->getDamage() !== null, $ingredient->getCompoundTag() !== null)) {
                                        $canCraft = false;
                                        break;
                                    }
                                } elseif ($ingredient !== null and $item->getId() !== 0) {
                                    $canCraft = false;
                                    break;
                                }
                            }
                        }
                    } elseif ($recipe instanceof ShapelessRecipe) {
                        $needed = $recipe->getIngredientList();
                        for ($x = 0; $x < 3 and $canCraft; ++$x) {
                            for ($y = 0; $y < 3; ++$y) {
                                $item = clone $packet->input[$y * 3 + $x];
                                foreach ($needed as $k => $n) {
                                    if ($n->deepEquals($item, $n->getDamage() !== null, $n->getCompoundTag() !== null)) {
                                        $remove = min($n->getCount(), $item->getCount());
                                        $n->setCount($n->getCount() - $remove);
                                        $item->setCount($item->getCount() - $remove);
                                        if ($n->getCount() === 0) {
                                            unset($needed[$k]);
                                        }
                                    }
                                }
                                if ($item->getCount() > 0) {
                                    $canCraft = false;
                                    break;
                                }
                            }
                        }
                        if (count($needed) > 0) {
                            $canCraft = false;
                        }
                    } else {
                        $canCraft = false;
                    }
                    //Nasty hack. TODO: Get rid
                    $canCraft = true;
                    //0.13.1大量物品本地配方出现问题,无法解决,使用极端(唯一)方法修复.
                    /** @var Item[] $ingredients */
                    $ingredients = $packet->input;
                    $result = $packet->output[0];
                    if (!$canCraft or !$recipe->getResult()->deepEquals($result)) {
                        $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": expected " . $recipe->getResult() . ", got " . $result . ", using: " . implode(", ", $ingredients));
                        $this->inventory->sendContents($this);
                        break;
                    }
                    $used = array_fill(0, $this->inventory->getSize(), 0);
                    foreach ($ingredients as $ingredient) {
                        $slot = -1;
                        foreach ($this->inventory->getContents() as $index => $i) {
                            if ($ingredient->getId() !== 0 and $ingredient->deepEquals($i, $ingredient->getDamage() !== null) and $i->getCount() - $used[$index] >= 1) {
                                $slot = $index;
                                $used[$index]++;
                                break;
                            }
                        }
                        if ($ingredient->getId() !== 0 and $slot === -1) {
                            $canCraft = false;
                            break;
                        }
                    }
                    if (!$canCraft) {
                        $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": client does not have enough items, using: " . implode(", ", $ingredients));
                        $this->inventory->sendContents($this);
                        break;
                    }
                    $this->server->getPluginManager()->callEvent($ev = new CraftItemEvent($this, $ingredients, $recipe));
                    if ($ev->isCancelled()) {
                        $this->inventory->sendContents($this);
                        break;
                    }
                    foreach ($used as $slot => $count) {
                        if ($count === 0) {
                            continue;
                        }
                        $item = $this->inventory->getItem($slot);
                        if ($item->getCount() > $count) {
                            $newItem = clone $item;
                            $newItem->setCount($item->getCount() - $count);
                        } else {
                            $newItem = Item::get(Item::AIR, 0, 0);
                        }
                        $this->inventory->setItem($slot, $newItem);
                    }
                    $extraItem = $this->inventory->addItem($recipe->getResult());
                    if (count($extraItem) > 0 and !$this->isCreative()) {
                        //Could not add all the items to our inventory (not enough space)
                        foreach ($extraItem as $item) {
                            $this->level->dropItem($this, $item);
                        }
                    }
                }
                switch ($recipe->getResult()->getId()) {
                    case Item::WORKBENCH:
                        $this->awardAchievement("buildWorkBench");
                        break;
                    case Item::WOODEN_PICKAXE:
                        $this->awardAchievement("buildPickaxe");
                        break;
                    case Item::FURNACE:
                        $this->awardAchievement("buildFurnace");
                        break;
                    case Item::WOODEN_HOE:
                        $this->awardAchievement("buildHoe");
                        break;
                    case Item::BREAD:
                        $this->awardAchievement("makeBread");
                        break;
                    case Item::CAKE:
                        //TODO: detect complex recipes like cake that leave remains
                        $this->awardAchievement("bakeCake");
                        $this->inventory->addItem(Item::get(Item::BUCKET, 0, 3));
                        break;
                    case Item::STONE_PICKAXE:
                    case Item::GOLD_PICKAXE:
                    case Item::IRON_PICKAXE:
                    case Item::DIAMOND_PICKAXE:
                        $this->awardAchievement("buildBetterPickaxe");
                        break;
                    case Item::WOODEN_SWORD:
                        $this->awardAchievement("buildSword");
                        break;
                    case Item::DIAMOND:
                        $this->awardAchievement("diamond");
                        break;
                }
                break;
            case ProtocolInfo::CONTAINER_SET_SLOT_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                    break;
                }
                if ($packet->slot < 0) {
                    break;
                }
                if ($packet->windowid === 0) {
                    //Our inventory
                    if ($packet->slot >= $this->inventory->getSize()) {
                        break;
                    }
                    $transaction = new BaseTransaction($this->inventory, $packet->slot, $packet->item);
                } elseif ($packet->windowid === ContainerSetContentPacket::SPECIAL_ARMOR) {
                    //Our armor
                    if ($packet->slot >= 4) {
                        break;
                    }
                    $transaction = new BaseTransaction($this->inventory, $packet->slot + $this->inventory->getSize(), $packet->item);
                } elseif (isset($this->windowIndex[$packet->windowid])) {
                    //Transaction for non-player-inventory window, such as anvil, chest, etc.
                    $inv = $this->windowIndex[$packet->windowid];
                    $achievements = [];
                    if ($inv instanceof FurnaceInventory and $inv->getItem($packet->slot)->getId() === Item::IRON_INGOT and $packet->slot === FurnaceInventory::RESULT) {
                        $achievements[] = "acquireIron";
                    } elseif ($inv instanceof EnchantInventory and $packet->item->hasEnchantments()) {
                        $inv->onEnchant($this, $inv->getItem($packet->slot), $packet->item);
                    }
                    $transaction = new BaseTransaction($inv, $packet->slot, $packet->item, $achievements);
                } else {
                    //Client sent a transaction for a window which the server doesn't think they have open
                    break;
                }
                $this->getTransactionQueue()->addTransaction($transaction);
                break;
            case ProtocolInfo::BLOCK_ENTITY_DATA_PACKET:
                if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                    break;
                }
                $this->craftingType = self::CRAFTING_SMALL;
                $pos = new Vector3($packet->x, $packet->y, $packet->z);
                if ($pos->distanceSquared($this) > 10000) {
                    break;
                }
                $t = $this->level->getTile($pos);
                if ($t instanceof Sign) {
                    $nbt = new NBT(NBT::LITTLE_ENDIAN);
                    $nbt->read($packet->namedtag);
                    $nbt = $nbt->getData();
                    if ($nbt["id"] !== Tile::SIGN) {
                        $t->spawnTo($this);
                    } else {
                        $ev = new SignChangeEvent($t->getBlock(), $this, [TextFormat::clean($nbt["Text1"], $this->removeFormat), TextFormat::clean($nbt["Text2"], $this->removeFormat), TextFormat::clean($nbt["Text3"], $this->removeFormat), TextFormat::clean($nbt["Text4"], $this->removeFormat)]);
                        if (!isset($t->namedtag->Creator) or $t->namedtag["Creator"] !== $this->getRawUniqueId()) {
                            $ev->setCancelled();
                        }
                        $this->server->getPluginManager()->callEvent($ev);
                        if (!$ev->isCancelled()) {
                            $t->setText($ev->getLine(0), $ev->getLine(1), $ev->getLine(2), $ev->getLine(3));
                        } else {
                            $t->spawnTo($this);
                        }
                    }
                }
                break;
            default:
                break;
        }
        $timings->stopTiming();
    }

Usage Example

Exemplo n.º 1
0
 public function processBatch(BatchPacket $packet, Player $p)
 {
     $str = zlib_decode($packet->payload, 1024 * 1024 * 64);
     //Max 64MB
     $len = strlen($str);
     $offset = 0;
     try {
         while ($offset < $len) {
             $pkLen = Binary::readInt(substr($str, $offset, 4));
             $offset += 4;
             $buf = substr($str, $offset, $pkLen);
             $offset += $pkLen;
             if (($pk = $this->getPacket(ord($buf[1]))) !== null) {
                 if ($pk::NETWORK_ID === Info::BATCH_PACKET) {
                     throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket");
                 }
                 $pk->setBuffer($buf, 2);
                 $pk->decode();
                 $p->handleDataPacket($pk);
                 if ($pk->getOffset() <= 0) {
                     return;
                 }
             }
         }
     } catch (\Throwable $e) {
         if (\pocketmine\DEBUG > 1) {
             $logger = $this->server->getLogger();
             if ($logger instanceof MainLogger) {
                 $logger->debug("BatchPacket " . " 0x" . bin2hex($packet->payload));
                 $logger->logException($e);
             }
         }
     }
 }
All Usage Examples Of pocketmine\Player::handleDataPacket
Player