createEntity() public static method

public static createEntity ( integer | string $type, pocketmine\level\format\FullChunk $chunk, CompoundTag $nbt, $args ) : Entity | Projectile
$type integer | string
$chunk pocketmine\level\format\FullChunk
$nbt pocketmine\nbt\tag\CompoundTag
$args
return Entity | Projectile
Example #1
5
 public function burstArrow(Player $player)
 {
     if ($player->getInventory()->getItemInHand()->getId() === Item::BOW) {
         $bow = $player->getInventory()->getItemInHand();
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $player->x), new Double("", $player->y + $player->getEyeHeight()), new Double("", $player->z)]), "Motion" => new Enum("Motion", [new Double("", -\sin($player->yaw / 180 * M_PI) * \cos($player->pitch / 180 * M_PI)), new Double("", -\sin($player->pitch / 180 * M_PI)), new Double("", \cos($player->yaw / 180 * M_PI) * \cos($player->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $player->yaw), new Float("", $player->pitch)])]);
         $ev = new EntityShootBowEvent($player, $bow, Entity::createEntity("Arrow", $player->chunk, $nbt, $player), 1.5);
         $this->getServer()->getPluginManager()->callEvent($ev);
         if ($ev->isCancelled()) {
             $ev->getProjectile()->kill();
         } else {
             $ev->getProjectile()->setMotion($ev->getProjectile()->getMotion()->multiply($ev->getForce()));
             if ($ev->getProjectile() instanceof Projectile) {
                 $this->getServer()->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($ev->getProjectile()));
                 if ($projectileEv->isCancelled()) {
                     $ev->getProjectile()->kill();
                 } else {
                     $this->object_hash[spl_object_hash($ev->getProjectile())] = 1;
                     $ev->getProjectile()->spawnToAll();
                 }
             } else {
                 $this->object_hash[spl_object_hash($ev->getProjectile())] = 1;
                 $ev->getProjectile()->spawnToAll();
             }
         }
     }
 }
Example #2
1
 public function attackEntity(Entity $player)
 {
     if ($this->attackDelay > 25 && mt_rand(1, 12) < 3 && $this->distanceSquared($player) <= 40) {
         $this->attackDelay = 0;
         $f = 1.5;
         $yaw = $this->yaw + mt_rand(-180, 180) / 10;
         $pitch = $this->pitch + mt_rand(-90, 90) / 10;
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + 1.62), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * $f), new Double("", -sin($pitch / 180 * M_PI) * $f), new Double("", cos($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * $f)]), "Rotation" => new Enum("Rotation", [new Float("", $yaw), new Float("", $pitch)])]);
         /** @var Projectile $arrow */
         $arrow = Entity::createEntity("Arrow", $this->chunk, $nbt, $this);
         $ev = new EntityShootBowEvent($this, Item::get(Item::ARROW, 0, 1), $arrow, $f);
         $this->server->getPluginManager()->callEvent($ev);
         $projectile = $ev->getProjectile();
         if ($ev->isCancelled()) {
             $ev->getProjectile()->kill();
         } elseif ($projectile instanceof Projectile) {
             $this->server->getPluginManager()->callEvent($launch = new ProjectileLaunchEvent($projectile));
             if ($launch->isCancelled()) {
                 $projectile->kill();
             } else {
                 $projectile->spawnToAll();
                 $this->level->addSound(new LaunchSound($this), $this->getViewers());
             }
         }
     }
 }
Example #3
1
 public function attackEntity(Entity $player)
 {
     if ($this->attackDelay > 30 && mt_rand(1, 32) < 4 && $this->distanceSquared($player) <= 200) {
         $this->attackDelay = 0;
         $f = 2;
         $yaw = $this->yaw + mt_rand(-220, 220) / 10;
         $pitch = $this->pitch + mt_rand(-120, 120) / 10;
         $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + -sin($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * 2), new DoubleTag("", $this->y + 2), new DoubleTag("", $this->z + cos($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * 2)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI)), new DoubleTag("", -sin($pitch / 180 * M_PI) * $f), new DoubleTag("", cos($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $yaw), new FloatTag("", $pitch)])]);
         $fireball = Entity::createEntity("FireBall", $this->chunk, $nbt, $this);
         if ($fireball instanceof FireBall) {
             $fireball->setExplode(true);
         }
         $fireball->setMotion($fireball->getMotion()->multiply($f));
         $ev = new EntityShootBowEvent($this, Item::get(Item::ARROW, 0, 1), $fireball, $f);
         $this->server->getPluginManager()->callEvent($ev);
         $projectile = $ev->getProjectile();
         if ($ev->isCancelled()) {
             $projectile->kill();
         } elseif ($projectile instanceof Projectile) {
             $this->server->getPluginManager()->callEvent($launch = new ProjectileLaunchEvent($projectile));
             if ($launch->isCancelled()) {
                 $projectile->kill();
             } else {
                 $projectile->spawnToAll();
                 $this->level->addSound(new LaunchSound($this), $this->getViewers());
             }
         }
     }
 }
 public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz)
 {
     $entity = null;
     $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4);
     if (!$chunk instanceof FullChunk) {
         return false;
     }
     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $block->getX() + 0.5), new Double("", $block->getY()), new Double("", $block->getZ() + 0.5)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", lcg_value() * 360), new Float("", 0)])]);
     $entity = Entity::createEntity($this->meta, $chunk, $nbt);
     if ($entity instanceof Entity) {
         if ($player->isSurvival()) {
             --$this->count;
         }
         $entity->spawnToAll();
         return true;
     }
     return false;
 }
Example #5
0
 public function onBreak(Item $item)
 {
     if ($this->getRandomExperience($item) > 0) {
         Entity::createEntity("ExperienceOrb", $this->level->getChunk($this->x >> 4, $this->z >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)])]))->spawnToAll();
     }
     return parent::onBreak($item);
 }
Example #6
0
 public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz)
 {
     if ($target->getId() == Block::MONSTER_SPAWNER) {
         return true;
     } else {
         $entity = null;
         $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4);
         if (!$chunk instanceof FullChunk) {
             return false;
         }
         $nbt = new CompoundTag("", ["Pos" => new EnumTag("Pos", [new DoubleTag("", $block->getX() + 0.5), new DoubleTag("", $block->getY()), new DoubleTag("", $block->getZ() + 0.5)]), "Motion" => new EnumTag("Motion", [new DoubleTag("", 0), new DoubleTag("", 0), new DoubleTag("", 0)]), "Rotation" => new EnumTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)])]);
         if ($this->hasCustomName()) {
             $nbt->CustomName = new StringTag("CustomName", $this->getCustomName());
         }
         $entity = Entity::createEntity($this->meta, $chunk, $nbt);
         if ($entity instanceof Entity) {
             if ($player->isSurvival()) {
                 --$this->count;
             }
             $entity->spawnToAll();
             return true;
         }
     }
     return false;
 }
Example #7
0
 public function attackEntity(Entity $player)
 {
     if ($this->attackDelay > 23 && mt_rand(1, 32) < 4 && $this->distanceSquared($player) <= 55) {
         $this->attackDelay = 0;
         $f = 1.2;
         $yaw = $this->yaw + mt_rand(-220, 220) / 10;
         $pitch = $this->pitch + mt_rand(-120, 120) / 10;
         $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + -sin($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * 0.5), new DoubleTag("", $this->y + 1), new DoubleTag("", $this->z + cos($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI) * 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI)), new DoubleTag("", -sin($pitch / 180 * M_PI)), new DoubleTag("", cos($yaw / 180 * M_PI) * cos($pitch / 180 * M_PI))]), "Rotation" => new ListTag("Rotation", [new FloatTag("", $yaw), new FloatTag("", $pitch)])]);
         /** @var Projectile $snowball */
         $snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this);
         $snowball->setMotion($snowball->getMotion()->multiply($f));
         $property = (new \ReflectionClass($snowball))->getProperty("damage");
         $property->setAccessible(true);
         $property->setValue($snowball, 2);
         $ev = new EntityShootBowEvent($this, Item::get(Item::ARROW, 0, 1), $snowball, $f);
         $this->server->getPluginManager()->callEvent($ev);
         $projectile = $ev->getProjectile();
         if ($ev->isCancelled()) {
             $projectile->kill();
         } elseif ($projectile instanceof Projectile) {
             $this->server->getPluginManager()->callEvent($launch = new ProjectileLaunchEvent($projectile));
             if ($launch->isCancelled()) {
                 $projectile->kill();
             } else {
                 $projectile->spawnToAll();
                 $this->level->addSound(new LaunchSound($this), $this->getViewers());
             }
         }
     }
 }
 public function prime()
 {
     $this->meta = 1;
     $mot = (new Random())->nextSignedFloat() * M_PI * 2;
     $tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + 0.5), new DoubleTag("", $this->y), new DoubleTag("", $this->z + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($mot) * 0.02), new DoubleTag("", 0.2), new DoubleTag("", -cos($mot) * 0.02)]), "Rotation" => new ListTag("Rotation", [new FloatTag("", 0), new FloatTag("", 0)]), "Fuse" => new ByteTag("Fuse", 80)]));
     $tnt->spawnToAll();
     $this->level->addSound(new TNTPrimeSound($this));
 }
Example #9
0
 public static function dropExpOrb__api200(Position $source, $exp = 1, Vector3 $motion = \null, $delay = 40)
 {
     $motion = $motion === \null ? new Vector3(\lcg_value() * 0.2 - 0.1, 0.4, \lcg_value() * 0.2 - 0.1) : $motion;
     $entity = Entity::createEntity("ExperienceOrb", $source->getLevel()->getChunk($source->getX() >> 4, $source->getZ() >> 4, \true), new \pocketmine\nbt\tag\CompoundTag("", ["Pos" => new \pocketmine\nbt\tag\ListTag("Pos", [new \pocketmine\nbt\tag\DoubleTag("", $source->getX()), new \pocketmine\nbt\tag\DoubleTag("", $source->getY()), new \pocketmine\nbt\tag\DoubleTag("", $source->getZ())]), "Motion" => new \pocketmine\nbt\tag\ListTag("Motion", [new \pocketmine\nbt\tag\DoubleTag("", $motion->x), new \pocketmine\nbt\tag\DoubleTag("", $motion->y), new \pocketmine\nbt\tag\DoubleTag("", $motion->z)]), "Rotation" => new \pocketmine\nbt\tag\ListTag("Rotation", [new \pocketmine\nbt\tag\FloatTag("", \lcg_value() * 360), new \pocketmine\nbt\tag\FloatTag("", 0)]), "Health" => new \pocketmine\nbt\tag\ShortTag("Health", 20), "PickupDelay" => new \pocketmine\nbt\tag\ShortTag("PickupDelay", $delay)]));
     if ($entity instanceof ExperienceOrb) {
         $entity->setExp($exp);
     }
     $entity->spawnToAll();
 }
 public function onUpdate($type)
 {
     if ($type === Level::BLOCK_UPDATE_NORMAL) {
         $down = $this->getSide(Vector3::SIDE_DOWN);
         if ($down->getId() === self::AIR or $down instanceof Liquid) {
             $fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x + 0.5), new Double("", $this->y), new Double("", $this->z + 0.5)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "TileID" => new Int("TileID", $this->getId()), "Data" => new Byte("Data", $this->getDamage())]));
             $fall->spawnToAll();
         }
     }
 }
Example #11
0
 public function onActivate(Item $item, Player $player = null)
 {
     if ($item->getId() === Item::FLINT_STEEL) {
         $item->useOn($this);
         $this->getLevel()->setBlock($this, new Air(), true);
         $mot = (new Random())->nextSignedFloat() * M_PI * 2;
         $tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + 0.5), new DoubleTag("", $this->y), new DoubleTag("", $this->z + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($mot) * 0.02), new DoubleTag("", 0.2), new DoubleTag("", -cos($mot) * 0.02)]), "Rotation" => new ListTag("Rotation", [new FloatTag("", 0), new FloatTag("", 0)]), "Fuse" => new ByteTag("Fuse", 80)]));
         $tnt->spawnToAll();
         return true;
     }
     return false;
 }
Example #12
0
 public function prime(Player $player = null)
 {
     $this->meta = 1;
     if ($player != null and $player->isCreative()) {
         $dropItem = false;
     } else {
         $dropItem = true;
     }
     $mot = (new Random())->nextSignedFloat() * M_PI * 2;
     $tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + 0.5), new DoubleTag("", $this->y), new DoubleTag("", $this->z + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", -sin($mot) * 0.02), new DoubleTag("", 0.2), new DoubleTag("", -cos($mot) * 0.02)]), "Rotation" => new ListTag("Rotation", [new FloatTag("", 0), new FloatTag("", 0)]), "Fuse" => new ByteTag("Fuse", 80)]), $dropItem);
     $tnt->spawnToAll();
     $this->level->addSound(new TNTPrimeSound($this));
 }
Example #13
0
 public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz)
 {
     $realPos = $block->getSide($face);
     $boat = Entity::createEntity("Boat", $player->getLevel()->getChunk($realPos->x >> 4, $realPos->z >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $realPos->x), new Double("", $realPos->y), new Double("", $realPos->z)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)])]));
     $boat->spawnToAll();
     --$this->count;
     if ($this->count <= 0) {
         $player->getInventory()->setItemInHand(Item::get(Item::AIR));
         return true;
     }
     $player->getInventory()->setItemInHand($this);
     return true;
 }
Example #14
0
 public function place(BlockPlaceEvent $place)
 {
     $block = $place->getBlock();
     $player = $place->getPlayer();
     if ($block->getId() === 46) {
         $place->setCancelled();
         $mot = (new Random())->nextSignedFloat() * M_PI * 2;
         $tnt = Entity::createEntity("PrimedTNT", $block->getLevel()->getChunk($block->x >> 4, $block->z >> 4), new Compound("", ["Pos" => new EnumTag("Pos", [new DoubleTag("", $block->x + 0.5), new DoubleTag("", $block->y), new DoubleTag("", $block->z + 0.5)]), "Motion" => new EnumTag("Motion", [new DoubleTag("", -sin($mot) * 0.02), new DoubleTag("", 0.2), new DoubleTag("", -cos($mot) * 0.02)]), "Rotation" => new EnumTag("Rotation", [new FloatTag("", 0), new FloatTag("", 0)]), "Fuse" => new ByteTag("Fuse", 100)]));
         $tnt->spawnToAll();
         $player->getLevel()->addSound(new AnviluseSound($player), array($player));
         return true;
     }
 }
Example #15
0
 public function launch(Player $player)
 {
     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $player->x), new Double("", $player->y + $player->getEyeHeight()), new Double("", $player->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($player->yaw / 180 * M_PI) * cos($player->pitch / 180 * M_PI)), new Double("", -sin($player->pitch / 180 * M_PI)), new Double("", cos($player->yaw / 180 * M_PI) * cos($player->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $player->yaw), new Float("", $player->pitch)]), "Data" => new Byte("Data", $this->getDamage())]);
     $f = $this->f;
     $launched = Entity::createEntity($this->getEntityName(), $player->chunk, $nbt, $player);
     $launched->setMotion($launched->getMotion()->multiply($f));
     if ($launched instanceof Projectile) {
         $player->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($launched));
         if ($projectileEv->isCancelled()) {
             $launched->kill();
         } else {
             $launched->spawnToAll();
             $player->level->addSound(new LaunchSound($player), $player->getViewers());
         }
     } else {
         $launched->spawnToAll();
     }
     return true;
 }
Example #16
0
 public function launch(Player $player)
 {
     $dir = $player->getDirectionVector();
     $frontPos = $player->add($dir->multiply(1.1));
     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $frontPos->x), new Double("", $frontPos->y + $player->getEyeHeight()), new Double("", $frontPos->z)]), "Motion" => new Enum("Motion", [new Double("", $dir->x), new Double("", $dir->y), new Double("", $dir->z)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)])]);
     $f = $this->f;
     $launched = Entity::createEntity($this->getEntityName(), $player->chunk, $nbt);
     $launched->setMotion($launched->getMotion()->multiply($f));
     if ($launched instanceof Projectile) {
         $player->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($launched));
         if ($projectileEv->isCancelled()) {
             $launched->kill();
         } else {
             $launched->spawnToAll();
             $player->level->addSound(new LaunchSound($player), $player->getViewers());
         }
     } else {
         $launched->spawnToAll();
     }
 }
Example #17
0
 /**
  * Handles a Minecraft packet
  * TODO: Separate all of this in handlers
  *
  * WARNING: Do not use this, it's only for internal use.
  * Changes to this function won't be recorded on the version.
  *
  * @param DataPacket $packet
  */
 public function handleDataPacket(DataPacket $packet)
 {
     if ($this->connected === false) {
         return;
     }
     $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
     if ($ev->isCancelled()) {
         return;
     }
     switch ($packet->pid()) {
         case ProtocolInfo::LOGIN_PACKET:
             if ($this->loggedIn === true) {
                 break;
             }
             $this->username = TextFormat::clean($packet->username);
             $this->displayName = $this->username;
             $this->nameTag = $this->username;
             $this->iusername = strtolower($this->username);
             $this->loginData = ["clientId" => $packet->clientId, "loginData" => $packet->loginData];
             if (count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers()) {
                 if ($this->kick("server full") === true) {
                     return;
                 }
             }
             if ($packet->protocol1 !== ProtocolInfo::CURRENT_PROTOCOL) {
                 if ($packet->protocol1 < ProtocolInfo::CURRENT_PROTOCOL) {
                     $pk = new LoginStatusPacket();
                     $pk->status = 1;
                     $this->dataPacket($pk);
                 } else {
                     $pk = new LoginStatusPacket();
                     $pk->status = 2;
                     $this->dataPacket($pk);
                 }
                 $this->close("", "Incorrect protocol #" . $packet->protocol1, false);
                 return;
             }
             if (strpos($packet->username, "") !== false or preg_match('#^[a-zA-Z0-9_]{3,16}$#', $packet->username) == 0 or $this->username === "" or $this->iusername === "rcon" or $this->iusername === "console" or strlen($packet->username) > 16 or strlen($packet->username) < 3) {
                 $this->close("", "Bad username");
                 return;
             }
             $this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
             if ($ev->isCancelled()) {
                 $this->close("", $ev->getKickMessage());
                 return;
             }
             if (!$this->server->isWhitelisted(strtolower($this->getName()))) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "Server is white-listed");
                 return;
             } elseif ($this->server->getNameBans()->isBanned(strtolower($this->getName())) or $this->server->getIPBans()->isBanned($this->getAddress())) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "You are banned");
                 return;
             }
             if ($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)) {
                 $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
             }
             if ($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)) {
                 $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
             }
             foreach ($this->server->getOnlinePlayers() as $p) {
                 if ($p !== $this and strtolower($p->getName()) === strtolower($this->getName())) {
                     if ($p->kick("logged in from another location") === false) {
                         $this->close(TextFormat::YELLOW . $this->getName() . " has left the game", "Logged in from another location");
                         return;
                     } else {
                         break;
                     }
                 }
             }
             $nbt = $this->server->getOfflinePlayerData($this->username);
             if (!isset($nbt->NameTag)) {
                 $nbt->NameTag = new String("NameTag", $this->username);
             } else {
                 $nbt["NameTag"] = $this->username;
             }
             $this->gamemode = $nbt["playerGameType"] & 0x3;
             if ($this->server->getForceGamemode()) {
                 $this->gamemode = $this->server->getGamemode();
                 $nbt->playerGameType = new Int("playerGameType", $this->gamemode);
             }
             if (($level = $this->server->getLevelByName($nbt["Level"])) === null) {
                 $this->setLevel($this->server->getDefaultLevel(), true);
                 $nbt["Level"] = $this->level->getName();
                 $nbt["Pos"][0] = $this->level->getSpawnLocation()->x;
                 $nbt["Pos"][1] = $this->level->getSpawnLocation()->y;
                 $nbt["Pos"][2] = $this->level->getSpawnLocation()->z;
             } else {
                 $this->setLevel($level, true);
             }
             if (!$nbt instanceof Compound) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "Invalid data");
                 return;
             }
             $this->achievements = [];
             /** @var Byte $achievement */
             foreach ($nbt->Achievements as $achievement) {
                 $this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
             }
             $nbt["lastPlayed"] = floor(microtime(true) * 1000);
             $this->server->saveOfflinePlayerData($this->username, $nbt);
             parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt);
             $this->loggedIn = true;
             $this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
             if ($ev->isCancelled()) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", $ev->getKickMessage());
                 return;
             }
             if ($this->isCreative()) {
                 $this->inventory->setHeldItemSlot(0);
             } else {
                 $this->inventory->setHeldItemSlot(0);
             }
             $pk = new LoginStatusPacket();
             $pk->status = 0;
             $this->dataPacket($pk);
             if ($this->spawnPosition === null and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level) {
                 $this->spawnPosition = new Position($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
             }
             $spawnPosition = $this->getSpawn();
             $this->dead = false;
             $pk = new StartGamePacket();
             $pk->seed = $this->level->getSeed();
             $pk->x = $this->x;
             $pk->y = $this->y;
             $pk->z = $this->z;
             $pk->spawnX = (int) $spawnPosition->x;
             $pk->spawnY = (int) $spawnPosition->y;
             $pk->spawnZ = (int) $spawnPosition->z;
             $pk->generator = 1;
             //0 old, 1 infinite, 2 flat
             $pk->gamemode = $this->gamemode & 0x1;
             $pk->eid = 0;
             //Always use EntityID as zero for the actual player
             $this->dataPacket($pk);
             $pk = new SetTimePacket();
             $pk->time = $this->level->getTime();
             $pk->started = $this->level->stopTime == false;
             $this->dataPacket($pk);
             $pk = new SetSpawnPositionPacket();
             $pk->x = (int) $spawnPosition->x;
             $pk->y = (int) $spawnPosition->y;
             $pk->z = (int) $spawnPosition->z;
             $this->dataPacket($pk);
             $pk = new SetHealthPacket();
             $pk->health = $this->getHealth();
             $this->dataPacket($pk);
             if ($this->getHealth() <= 0) {
                 $this->dead = true;
             }
             $pk = new SetDifficultyPacket();
             $pk->difficulty = $this->server->getDifficulty();
             $this->dataPacket($pk);
             $this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->level->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
             $this->orderChunks();
             $this->sendNextChunk();
             break;
         case ProtocolInfo::ROTATE_HEAD_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 break;
             }
             $this->setRotation($packet->yaw, $this->pitch);
             break;
         case ProtocolInfo::MOVE_PLAYER_PACKET:
             $newPos = new Vector3($packet->x, $packet->y, $packet->z);
             $revert = false;
             if ($this->dead === true or $this->spawned !== true) {
                 $revert = true;
                 $this->forceMovement = new Vector3($this->x, $this->y, $this->z);
             }
             if ($this->forceMovement instanceof Vector3 and ($revert or $newPos->distanceSquared($this->forceMovement) > 0.04)) {
                 $pk = new MovePlayerPacket();
                 $pk->eid = 0;
                 $pk->x = $this->forceMovement->x;
                 $pk->y = $this->forceMovement->y + $this->getEyeHeight();
                 $pk->z = $this->forceMovement->z;
                 $pk->bodyYaw = $packet->bodyYaw;
                 $pk->pitch = $packet->pitch;
                 $pk->yaw = $packet->yaw;
                 $pk->teleport = true;
                 $this->directDataPacket($pk);
             } 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::PLAYER_EQUIPMENT_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 break;
             }
             if ($packet->slot === 0x28 or $packet->slot === 0 or $packet->slot === 255) {
                 //0 for 0.8.0 compatibility
                 $packet->slot = -1;
                 //Air
             } else {
                 $packet->slot -= 9;
                 //Get real block slot
             }
             if ($this->isCreative()) {
                 //Creative mode match
                 $item = Item::get($packet->item, $packet->meta, 1);
                 $slot = $this->getCreativeBlock($item);
             } else {
                 $item = $this->inventory->getItem($packet->slot);
                 $slot = $packet->slot;
             }
             if ($packet->slot === -1) {
                 //Air
                 if ($this->isCreative()) {
                     $found = false;
                     for ($i = 0; $i < $this->inventory->getHotbarSize(); ++$i) {
                         if ($this->inventory->getHotbarSlotIndex($i) === -1) {
                             $this->inventory->setHeldItemIndex($i);
                             $found = true;
                             break;
                         }
                     }
                     if (!$found) {
                         //couldn't find a empty slot (error)
                         $this->inventory->sendContents($this);
                         break;
                     }
                 } else {
                     $this->inventory->setHeldItemSlot($packet->slot);
                     //set Air
                 }
             } elseif (!isset($item) or $slot === -1 or $item->getId() !== $packet->item or $item->getDamage() !== $packet->meta) {
                 // packet error or not implemented
                 $this->inventory->sendContents($this);
                 break;
             } elseif ($this->isCreative()) {
                 $item = Item::get(Block::$creative[$slot][0], Block::$creative[$slot][1], 1);
                 $this->inventory->setHeldItemIndex($packet->slot);
             } else {
                 $this->inventory->setHeldItemSlot($slot);
             }
             $this->inventory->sendHeldItem($this->hasSpawned);
             if ($this->inAction === true) {
                 $this->inAction = false;
                 $this->sendMetadata($this->getViewers());
             }
             break;
         case ProtocolInfo::USE_ITEM_PACKET:
             if ($this->spawned === false or $this->dead === true or $this->blocked) {
                 break;
             }
             $blockVector = new Vector3($packet->x, $packet->y, $packet->z);
             $this->craftingType = 0;
             $packet->eid = $this->id;
             if ($packet->face >= 0 and $packet->face <= 5) {
                 //Use Block, place
                 if ($this->inAction === true) {
                     $this->inAction = false;
                     $this->sendMetadata($this->getViewers());
                 }
                 if ($blockVector->distance($this) > 10) {
                 } 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()->getId() !== $packet->item or ($damage = $this->inventory->getItemInHand()->getDamage()) !== $packet->meta and $damage !== null) {
                     $this->inventory->sendHeldItem($this);
                 } else {
                     $item = $this->inventory->getItemInHand();
                     $oldItem = clone $item;
                     //TODO: Implement adventure mode checks
                     if ($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true) {
                         if (!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()) {
                             $this->inventory->setItemInHand($item, $this);
                             $this->inventory->sendHeldItem($this->hasSpawned);
                         }
                         break;
                     }
                 }
                 $target = $this->level->getBlock($blockVector);
                 $block = $target->getSide($packet->face);
                 $pk = new UpdateBlockPacket();
                 $pk->x = $target->x;
                 $pk->y = $target->y;
                 $pk->z = $target->z;
                 $pk->block = $target->getId();
                 $pk->meta = $target->getDamage();
                 $this->dataPacket($pk);
                 $pk = new UpdateBlockPacket();
                 $pk->x = $block->x;
                 $pk->y = $block->y;
                 $pk->z = $block->z;
                 $pk->block = $block->getId();
                 $pk->meta = $block->getDamage();
                 $this->dataPacket($pk);
                 break;
             } elseif ($packet->face === 0xff) {
                 if ($this->isCreative()) {
                     $item = $this->inventory->getItemInHand();
                 } elseif ($this->inventory->getItemInHand()->getId() !== $packet->item or ($damage = $this->inventory->getItemInHand()->getDamage()) !== $packet->meta and $damage !== null) {
                     $this->inventory->sendHeldItem($this);
                     break;
                 } else {
                     $item = $this->inventory->getItemInHand();
                 }
                 $target = $this->level->getBlock($blockVector);
                 $ev = new PlayerInteractEvent($this, $item, $target, $packet->face);
                 $this->server->getPluginManager()->callEvent($ev);
                 if ($ev->isCancelled()) {
                     $this->inventory->sendHeldItem($this);
                     break;
                 }
                 if ($item->getId() === Item::SNOWBALL) {
                     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new Double("", -sin($this->pitch / 180 * M_PI)), new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $this->pitch)])]);
                     $f = 1.5;
                     $snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this);
                     $snowball->setMotion($snowball->getMotion()->multiply($f));
                     if ($this->isSurvival()) {
                         $this->inventory->removeItem(Item::get(Item::SNOWBALL, 0, 1), $this);
                     }
                     if ($snowball instanceof Projectile) {
                         $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($snowball));
                         if ($projectileEv->isCancelled()) {
                             $snowball->kill();
                         } else {
                             $snowball->spawnToAll();
                         }
                     } else {
                         $snowball->spawnToAll();
                     }
                 }
                 $this->inAction = true;
                 $this->startAction = microtime(true);
                 $this->sendMetadata($this->getViewers());
             }
             break;
         case ProtocolInfo::PLAYER_ACTION_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $packet->eid = $this->id;
             switch ($packet->action) {
                 case 5:
                     //Shot arrow
                     if ($this->inventory->getItemInHand()->getId() === Item::BOW) {
                         $bow = $this->inventory->getItemInHand();
                         if ($this->isSurvival()) {
                             if (!$this->inventory->contains(Item::get(Item::ARROW, 0, 1))) {
                                 $this->inventory->sendContents($this);
                                 return;
                             }
                         }
                         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new Double("", -sin($this->pitch / 180 * M_PI)), new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $this->pitch)])]);
                         $f = 1.5;
                         $ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this), $f);
                         $this->server->getPluginManager()->callEvent($ev);
                         if ($ev->isCancelled()) {
                             $ev->getProjectile()->kill();
                         } else {
                             $ev->getProjectile()->setMotion($ev->getProjectile()->getMotion()->multiply($ev->getForce()));
                             if ($this->isSurvival()) {
                                 $this->inventory->removeItem(Item::get(Item::ARROW, 0, 1), $this);
                                 $bow->setDamage($bow->getDamage() + 1);
                                 $this->inventory->setItemInHand($bow, $this);
                                 if ($bow->getDamage() >= 385) {
                                     $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0), $this);
                                 }
                             }
                             if ($ev->getProjectile() instanceof Projectile) {
                                 $this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($ev->getProjectile()));
                                 if ($projectileEv->isCancelled()) {
                                     $ev->getProjectile()->kill();
                                 } else {
                                     $ev->getProjectile()->spawnToAll();
                                 }
                             } else {
                                 $ev->getProjectile()->spawnToAll();
                             }
                         }
                     }
                     $this->startAction = false;
                     $this->inAction = false;
                     $this->sendMetadata($this->getViewers());
                     break;
                 case 6:
                     //get out of the bed
                     $this->stopSleep();
                     break;
             }
             break;
         case ProtocolInfo::REMOVE_BLOCK_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $vector = new Vector3($packet->x, $packet->y, $packet->z);
             if ($this->isCreative()) {
                 $item = $this->inventory->getItemInHand();
             } else {
                 $item = $this->inventory->getItemInHand();
             }
             $oldItem = clone $item;
             if ($this->level->useBreakOn($vector, $item, $this) === true) {
                 if ($this->isSurvival()) {
                     if (!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()) {
                         $this->inventory->setItemInHand($item, $this);
                         $this->inventory->sendHeldItem($this->hasSpawned);
                     }
                 }
                 break;
             }
             $this->inventory->sendContents($this);
             $target = $this->level->getBlock($vector);
             $tile = $this->level->getTile($vector);
             $pk = new UpdateBlockPacket();
             $pk->x = $target->x;
             $pk->y = $target->y;
             $pk->z = $target->z;
             $pk->block = $target->getId();
             $pk->meta = $target->getDamage();
             $this->dataPacket($pk);
             if ($tile instanceof Spawnable) {
                 $tile->spawnTo($this);
             }
             break;
         case ProtocolInfo::PLAYER_ARMOR_EQUIPMENT_PACKET:
             break;
         case ProtocolInfo::INTERACT_PACKET:
             if ($this->spawned === false or $this->dead === true or $this->blocked) {
                 break;
             }
             $this->craftingType = 0;
             $target = $this->level->getEntity($packet->target);
             $cancelled = false;
             if ($target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false) {
                 $cancelled = true;
             }
             if ($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->dead !== true and $target->dead !== true) {
                 if ($target instanceof DroppedItem or $target instanceof Arrow) {
                     $this->kick("Attempting to attack an invalid entity");
                     $this->server->getLogger()->warning("Player " . $this->getName() . " tried to attack an invalid entity");
                     return;
                 }
                 $item = $this->inventory->getItemInHand();
                 $damageTable = [Item::WOODEN_SWORD => 4, Item::GOLD_SWORD => 4, Item::STONE_SWORD => 5, Item::IRON_SWORD => 6, Item::DIAMOND_SWORD => 7, Item::WOODEN_AXE => 3, Item::GOLD_AXE => 3, Item::STONE_AXE => 3, Item::IRON_AXE => 5, Item::DIAMOND_AXE => 6, Item::WOODEN_PICKAXE => 2, Item::GOLD_PICKAXE => 2, Item::STONE_PICKAXE => 3, Item::IRON_PICKAXE => 4, Item::DIAMOND_PICKAXE => 5, Item::WOODEN_SHOVEL => 1, Item::GOLD_SHOVEL => 1, Item::STONE_SHOVEL => 2, Item::IRON_SHOVEL => 3, Item::DIAMOND_SHOVEL => 4];
                 $damage = [EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1];
                 if ($this->distance($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;
                     }
                     $armorValues = [Item::LEATHER_CAP => 1, Item::LEATHER_TUNIC => 3, Item::LEATHER_PANTS => 2, Item::LEATHER_BOOTS => 1, Item::CHAIN_HELMET => 1, Item::CHAIN_CHESTPLATE => 5, Item::CHAIN_LEGGINGS => 4, Item::CHAIN_BOOTS => 1, Item::GOLD_HELMET => 1, Item::GOLD_CHESTPLATE => 5, Item::GOLD_LEGGINGS => 3, Item::GOLD_BOOTS => 1, Item::IRON_HELMET => 2, Item::IRON_CHESTPLATE => 6, Item::IRON_LEGGINGS => 5, Item::IRON_BOOTS => 2, Item::DIAMOND_HELMET => 3, Item::DIAMOND_CHESTPLATE => 8, Item::DIAMOND_LEGGINGS => 6, Item::DIAMOND_BOOTS => 3];
                     $points = 0;
                     foreach ($target->getInventory()->getArmorContents() as $index => $i) {
                         if (isset($armorValues[$i->getId()])) {
                             $points += $armorValues[$i->getId()];
                         }
                     }
                     $damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
                 }
                 $ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
                 if ($cancelled) {
                     $ev->setCancelled();
                 }
                 $target->attack($ev->getFinalDamage(), $ev);
                 if ($ev->isCancelled()) {
                     if ($item->isTool() and $this->isSurvival()) {
                         $this->inventory->sendContents($this);
                     }
                     break;
                 }
                 if ($item->isTool() and $this->isSurvival()) {
                     if ($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()) {
                         $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1), $this);
                     } else {
                         $this->inventory->setItemInHand($item, $this);
                     }
                 }
             }
             break;
         case ProtocolInfo::ANIMATE_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 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::RESPAWN_PACKET:
             if ($this->spawned === false or $this->dead === false) {
                 break;
             }
             $this->craftingType = 0;
             $this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
             $this->teleport($ev->getRespawnPosition());
             $this->fireTicks = 0;
             $this->airTicks = 300;
             $this->deadTicks = 0;
             $this->setHealth(20);
             $this->dead = false;
             $this->sendMetadata($this->getViewers());
             $this->sendMetadata($this);
             $this->sendSettings();
             $this->inventory->sendContents($this);
             $this->inventory->sendArmorContents($this);
             $this->blocked = false;
             $this->spawnToAll();
             $this->scheduleUpdate();
             break;
         case ProtocolInfo::SET_HEALTH_PACKET:
             //Not used
             break;
         case ProtocolInfo::ENTITY_EVENT_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             if ($this->inAction === true) {
                 $this->inAction = false;
                 $this->sendMetadata($this->getViewers());
             }
             switch ($packet->event) {
                 case 9:
                     //Eating
                     $items = [Item::APPLE => 4, Item::MUSHROOM_STEW => 10, Item::BEETROOT_SOUP => 10, Item::BREAD => 5, Item::RAW_PORKCHOP => 3, Item::COOKED_PORKCHOP => 8, Item::RAW_BEEF => 3, Item::STEAK => 8, Item::COOKED_CHICKEN => 6, Item::RAW_CHICKEN => 2, Item::MELON_SLICE => 2, Item::GOLDEN_APPLE => 10, Item::PUMPKIN_PIE => 8, Item::CARROT => 4, Item::POTATO => 1, Item::BAKED_POTATO => 6];
                     $slot = $this->inventory->getItemInHand();
                     if ($this->getHealth() < 20 and isset($items[$slot->getId()])) {
                         $this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
                         if ($ev->isCancelled()) {
                             $this->inventory->sendContents($this);
                             break;
                         }
                         $pk = new EntityEventPacket();
                         $pk->eid = 0;
                         $pk->event = 9;
                         $this->dataPacket($pk);
                         $pk->eid = $this->getId();
                         Server::broadcastPacket($this->getViewers(), $pk);
                         $amount = $items[$slot->getId()];
                         $this->server->getPluginManager()->callEvent($ev = new EntityRegainHealthEvent($this, $amount, EntityRegainHealthEvent::CAUSE_EATING));
                         if (!$ev->isCancelled()) {
                             $this->heal($ev->getAmount(), $ev);
                         }
                         --$slot->count;
                         $this->inventory->setItemInHand($slot, $this);
                         if ($slot->getId() === Item::MUSHROOM_STEW or $slot->getId() === Item::BEETROOT_SOUP) {
                             $this->inventory->addItem(Item::get(Item::BOWL, 0, 1), $this);
                         }
                     }
                     break;
             }
             break;
         case ProtocolInfo::DROP_ITEM_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $packet->eid = $this->id;
             $item = $this->inventory->getItemInHand();
             $ev = new PlayerDropItemEvent($this, $item);
             $this->server->getPluginManager()->callEvent($ev);
             if ($ev->isCancelled()) {
                 $this->inventory->sendContents($this);
                 break;
             }
             $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1), $this);
             $motion = $this->getDirectionVector()->multiply(0.4);
             $this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
             if ($this->inAction === true) {
                 $this->inAction = false;
                 $this->sendMetadata($this->getViewers());
             }
             break;
         case ProtocolInfo::MESSAGE_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $packet->message = TextFormat::clean($packet->message);
             if (trim($packet->message) != "" and strlen($packet->message) <= 255) {
                 $message = $packet->message;
                 $this->server->getPluginManager()->callEvent($ev = new PlayerCommandPreprocessEvent($this, $message));
                 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(sprintf($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 = 0;
             $this->currentTransaction = null;
             if (isset($this->windowIndex[$packet->windowid])) {
                 $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this));
                 $this->removeWindow($this->windowIndex[$packet->windowid]);
             } else {
                 unset($this->windowIndex[$packet->windowid]);
             }
             break;
         case ProtocolInfo::CONTAINER_SET_SLOT_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             if ($packet->slot < 0) {
                 break;
             }
             if ($packet->windowid === 0) {
                 //Our inventory
                 if ($packet->slot >= $this->inventory->getSize()) {
                     break;
                 }
                 if ($this->isCreative()) {
                     if ($this->getCreativeBlock($packet->item) !== -1) {
                         $this->inventory->setItem($packet->slot, $packet->item);
                         $this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot);
                         //links $hotbar[$packet->slot] to $slots[$packet->slot]
                     }
                 }
                 $transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
             } elseif ($packet->windowid === 0x78) {
                 //Our armor
                 if ($packet->slot >= 4) {
                     break;
                 }
                 $transaction = new BaseTransaction($this->inventory, $packet->slot + $this->inventory->getSize(), $this->inventory->getArmorItem($packet->slot), $packet->item);
             } elseif (isset($this->windowIndex[$packet->windowid])) {
                 $this->craftingType = 0;
                 $inv = $this->windowIndex[$packet->windowid];
                 $transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item);
             } else {
                 break;
             }
             if ($transaction->getSourceItem()->equals($transaction->getTargetItem(), true) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()) {
                 //No changes!
                 //No changes, just a local inventory update sent by the server
                 break;
             }
             if ($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < microtime(true) - 0.5) {
                 if ($this->currentTransaction instanceof SimpleTransactionGroup) {
                     foreach ($this->currentTransaction->getInventories() as $inventory) {
                         if ($inventory instanceof PlayerInventory) {
                             $inventory->sendArmorContents($this);
                         }
                         $inventory->sendContents($this);
                     }
                 }
                 $this->currentTransaction = new SimpleTransactionGroup($this);
             }
             $this->currentTransaction->addTransaction($transaction);
             if ($this->currentTransaction->canExecute()) {
                 if (!$this->currentTransaction->execute()) {
                     $this->currentTransaction = null;
                     break;
                 }
                 foreach ($this->currentTransaction->getTransactions() as $ts) {
                     $inv = $ts->getInventory();
                     if ($inv instanceof FurnaceInventory) {
                         if ($ts->getSlot() === 2) {
                             switch ($inv->getResult()->getId()) {
                                 case Item::IRON_INGOT:
                                     $this->awardAchievement("acquireIron");
                                     break;
                             }
                         }
                     }
                 }
                 $this->currentTransaction = null;
             } elseif ($packet->windowid == 0) {
                 //Try crafting
                 $craftingGroup = new CraftingTransactionGroup($this->currentTransaction);
                 if ($craftingGroup->canExecute()) {
                     //We can craft!
                     $recipe = $craftingGroup->getMatchingRecipe();
                     if ($recipe instanceof BigShapelessRecipe and $this->craftingType !== 1) {
                         break;
                     } elseif ($recipe instanceof StonecutterShapelessRecipe and $this->craftingType !== 2) {
                         break;
                     }
                     if ($craftingGroup->execute()) {
                         switch ($craftingGroup->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), $this);
                                 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;
                         }
                     }
                     $this->currentTransaction = null;
                 }
             }
             break;
         case ProtocolInfo::SEND_INVENTORY_PACKET:
             //TODO, Mojang, enable this ´^_^`
             if ($this->spawned === false) {
                 break;
             }
             break;
         case ProtocolInfo::ENTITY_DATA_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $t = $this->level->getTile(new Vector3($packet->x, $packet->y, $packet->z));
             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, [$nbt["Text1"], $nbt["Text2"], $nbt["Text3"], $nbt["Text4"]]);
                     if (!isset($t->namedtag->Creator) or $t->namedtag["Creator"] !== $this->username) {
                         $ev->setCancelled(true);
                     }
                     $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;
     }
 }
Example #18
0
 /**
  * @param Vector3 $source
  * @param Item    $item
  * @param Vector3 $motion
  * @param int     $delay
  */
 public function dropItem(Vector3 $source, Item $item, Vector3 $motion = null, $delay = 10)
 {
     $motion = $motion === null ? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1) : $motion;
     $itemTag = NBT::putItemHelper($item);
     $itemTag->setName("Item");
     if ($item->getId() > 0 and $item->getCount() > 0) {
         $itemEntity = Entity::createEntity("Item", $this->getChunk($source->getX() >> 4, $source->getZ() >> 4, true), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $source->getX()), new Double("", $source->getY()), new Double("", $source->getZ())]), "Motion" => new Enum("Motion", [new Double("", $motion->x), new Double("", $motion->y + 0.1), new Double("", $motion->z)]), "Rotation" => new Enum("Rotation", [new Float("", lcg_value() * 360), new Float("", 0)]), "Health" => new Short("Health", 5), "Item" => $itemTag, "PickupDelay" => new Short("PickupDelay", $delay)]));
         $itemEntity->spawnToAll();
     }
 }
 public function initChunk()
 {
     if ($this->getProvider() instanceof LevelProvider and !$this->isInit) {
         $changed = \false;
         if ($this->NBTentities !== \null) {
             $this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->startTiming();
             foreach ($this->NBTentities as $nbt) {
                 if ($nbt instanceof Compound) {
                     if (!isset($nbt->id)) {
                         $this->setChanged();
                         continue;
                     }
                     if ($nbt["Pos"][0] >> 4 !== $this->x or $nbt["Pos"][2] >> 4 !== $this->z) {
                         $changed = \true;
                         continue;
                         //Fixes entities allocated in wrong chunks.
                     }
                     if (($entity = Entity::createEntity($nbt["id"], $this, $nbt)) instanceof Entity) {
                         $entity->spawnToAll();
                     } else {
                         $changed = \true;
                         continue;
                     }
                 }
             }
             $this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->stopTiming();
             $this->getProvider()->getLevel()->timings->syncChunkLoadTileEntitiesTimer->startTiming();
             foreach ($this->NBTtiles as $nbt) {
                 if ($nbt instanceof Compound) {
                     if (!isset($nbt->id)) {
                         $changed = \true;
                         continue;
                     }
                     if ($nbt["x"] >> 4 !== $this->x or $nbt["z"] >> 4 !== $this->z) {
                         $changed = \true;
                         continue;
                         //Fixes tiles allocated in wrong chunks.
                     }
                     if (Tile::createTile($nbt["id"], $this, $nbt) === \null) {
                         $changed = \true;
                         continue;
                     }
                 }
             }
             $this->getProvider()->getLevel()->timings->syncChunkLoadTileEntitiesTimer->stopTiming();
             $this->NBTentities = \null;
             $this->NBTtiles = \null;
         }
         $this->setChanged($changed);
         $this->isInit = \true;
     }
 }
 public function explodeB()
 {
     $send = [];
     $updateBlocks = [];
     $source = (new Vector3($this->source->x, $this->source->y, $this->source->z))->floor();
     $yield = 1 / $this->size * 100;
     if ($this->what instanceof Entity) {
         $this->level->getServer()->getPluginManager()->callEvent($ev = new EntityExplodeEvent($this->what, $this->source, $this->affectedBlocks, $yield));
         if ($ev->isCancelled()) {
             return \false;
         } else {
             $yield = $ev->getYield();
             $this->affectedBlocks = $ev->getBlockList();
         }
     }
     $explosionSize = $this->size * 2;
     $minX = Math::floorFloat($this->source->x - $explosionSize - 1);
     $maxX = Math::ceilFloat($this->source->x + $explosionSize + 1);
     $minY = Math::floorFloat($this->source->y - $explosionSize - 1);
     $maxY = Math::ceilFloat($this->source->y + $explosionSize + 1);
     $minZ = Math::floorFloat($this->source->z - $explosionSize - 1);
     $maxZ = Math::ceilFloat($this->source->z + $explosionSize + 1);
     $explosionBB = new AxisAlignedBB($minX, $minY, $minZ, $maxX, $maxY, $maxZ);
     $list = $this->level->getNearbyEntities($explosionBB, $this->what instanceof Entity ? $this->what : \null);
     foreach ($list as $entity) {
         $distance = $entity->distance($this->source) / $explosionSize;
         if ($distance <= 1) {
             $motion = $entity->subtract($this->source)->normalize();
             $impact = (1 - $distance) * ($exposure = 1);
             $damage = (int) (($impact * $impact + $impact) / 2 * 8 * $explosionSize + 1);
             if ($this->what instanceof Entity) {
                 $ev = new EntityDamageByEntityEvent($this->what, $entity, EntityDamageEvent::CAUSE_ENTITY_EXPLOSION, $damage);
             } elseif ($this->what instanceof Block) {
                 $ev = new EntityDamageByBlockEvent($this->what, $entity, EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, $damage);
             } else {
                 $ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, $damage);
             }
             $entity->attack($ev->getFinalDamage(), $ev);
             $entity->setMotion($motion->multiply($impact));
         }
     }
     $air = Item::get(Item::AIR);
     foreach ($this->affectedBlocks as $block) {
         if ($block->getId() === Block::TNT) {
             $mot = (new Random())->nextSignedFloat() * M_PI * 2;
             $tnt = Entity::createEntity("PrimedTNT", $this->level->getChunk($block->x >> 4, $block->z >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $block->x + 0.5), new Double("", $block->y), new Double("", $block->z + 0.5)]), "Motion" => new Enum("Motion", [new Double("", -\sin($mot) * 0.02), new Double("", 0.2), new Double("", -\cos($mot) * 0.02)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "Fuse" => new Byte("Fuse", \mt_rand(10, 30))]));
             $tnt->spawnToAll();
         } elseif (\mt_rand(0, 100) < $yield) {
             foreach ($block->getDrops($air) as $drop) {
                 $this->level->dropItem($block->add(0.5, 0.5, 0.5), Item::get(...$drop));
             }
         }
         $this->level->setBlockIdAt($block->x, $block->y, $block->z, 0);
         $pos = new Vector3($block->x, $block->y, $block->z);
         for ($side = 0; $side < 5; $side++) {
             $sideBlock = $pos->getSide($side);
             if (!isset($this->affectedBlocks[$index = ($sideBlock->x & 0xfffffff) << 35 | ($sideBlock->y & 0x7f) << 28 | $sideBlock->z & 0xfffffff]) and !isset($updateBlocks[$index])) {
                 $this->level->getServer()->getPluginManager()->callEvent($ev = new BlockUpdateEvent($this->level->getBlock($sideBlock)));
                 if (!$ev->isCancelled()) {
                     $ev->getBlock()->onUpdate(Level::BLOCK_UPDATE_NORMAL);
                 }
                 $updateBlocks[$index] = \true;
             }
         }
         $send[] = new Vector3($block->x - $source->x, $block->y - $source->y, $block->z - $source->z);
     }
     $pk = new ExplodePacket();
     $pk->x = $this->source->x;
     $pk->y = $this->source->y;
     $pk->z = $this->source->z;
     $pk->radius = $this->size;
     $pk->records = $send;
     $this->level->addChunkPacket($source->x >> 4, $source->z >> 4, $pk);
     return \true;
 }
Example #21
0
 public function blockBreak(BlockBreakEvent $event)
 {
     $block = $event->getBlock();
     if ($block->getId() === $this->data["lucky_block"] && $this->isAllowedWorld($block->getLevel())) {
         $player = $event->getPlayer();
         if (!$player->hasPermission("luckyblock.use")) {
             $player->sendMessage($this->tag . $this->message->get("not_allowed"));
             return;
         }
         $event->setCancelled();
         $player->getLevel()->setBlock($block, new Block(Block::AIR), false, true);
         $rand = new Random();
         switch ($rand->nextRange(1, 12)) {
             case 1:
                 if (!isset($this->data["functions"]["spawnTree"]) || $this->data["functions"]["spawnTree"]) {
                     $type = Sapling::OAK;
                     switch ($rand->nextRange(0, 3)) {
                         case 1:
                             $type = Sapling::BIRCH;
                             break;
                         case 2:
                             $type = Sapling::SPRUCE;
                             break;
                         case 3:
                             $type = Sapling::JUNGLE;
                             break;
                     }
                     if ($player->getLevel()->setBlock($block, new Sapling($type), true, true)) {
                         $player->getLevel()->getBlock($block)->onActivate(new Item(Item::DYE, 15), $player);
                         $player->sendMessage($this->tag . $this->message->get("tree"));
                     }
                     break;
                 }
             case 2:
                 if (!isset($this->data["functions"]["explosion"]) || $this->data["functions"]["explosion"]) {
                     $explosion = new Explosion($block, mt_rand($this->data["explosion_min"], $this->data["explosion_max"]));
                     if ($explosion->explodeA()) {
                         $explosion->explodeB();
                     }
                     $player->sendMessage($this->tag . $this->message->get("explosion"));
                     break;
                 }
             case 3:
                 if (!isset($this->data["functions"]["dropItem"]) || $this->data["functions"]["dropItem"]) {
                     if (mt_rand(0, 1)) {
                         if ($this->itemLoop($player, $block)) {
                             break;
                         }
                     }
                     if (count($this->data["items_dropped"]) === 0) {
                         $item = $this->randItem();
                     } else {
                         $item = $this->data["items_dropped"][mt_rand(0, count($this->data["items_dropped"]) - 1)];
                     }
                     $player->getLevel()->dropItem($block, $item);
                     $player->sendMessage($this->tag . $this->message->get("drop"));
                     break;
                 }
             case 4:
                 if (!isset($this->data["functions"]["bedrock"]) || $this->data["functions"]["bedrock"]) {
                     $player->getLevel()->setBlock($block, new Block(Block::BEDROCK));
                     $p = new Position($block->x, $block->y + 1, $block->z, $block->level);
                     if ($player->getLevel()->getBlock($p)->getId() != Block::AIR) {
                         break;
                     }
                     $block->getLevel()->setBlock($p, Block::get(Item::SIGN_POST));
                     $sign = new Sign($player->getLevel()->getChunk($block->x >> 4, $block->z >> 4), new CompoundTag(false, array(new IntTag("x", (int) $block->x), new IntTag("y", (int) $block->y + 1), new IntTag("z", (int) $block->z), new StringTag("Text1", $this->tag), new StringTag("Text2", $this->message->get("signText")))));
                     $sign->spawnToAll();
                     $player->sendMessage($this->tag . $this->message->get("sign"));
                     break;
                 }
             case 5:
                 if (!isset($this->data["functions"]["prison"]) || $this->data["functions"]["prison"]) {
                     $pos = $event->getPlayer();
                     $pos->x = round($pos->x) + 0.5;
                     $pos->y = round($pos->y);
                     $pos->z = round($pos->z) + 0.5;
                     $player->teleport($pos, $player->getYaw(), $player->getPitch());
                     $arr = [];
                     switch ($rand->nextRange(1, 5)) {
                         case 1:
                             $player->getLevel()->setBlock(new Position($pos->x, $pos->y - 1, $pos->z, $pos->getLevel()), new Block(Block::OBSIDIAN));
                             for ($x = $pos->x - 1; $x <= $pos->x + 1; $x++) {
                                 for ($z = $pos->z - 1; $z <= $pos->z + 1; $z++) {
                                     if (!($x === $pos->x && $z === $pos->z)) {
                                         for ($y = $pos->y; $y <= $pos->y + 2; $y++) {
                                             $player->getLevel()->setBlock(new Position($x, $y, $z, $pos->getLevel()), new Block(Block::OBSIDIAN));
                                         }
                                     }
                                 }
                             }
                             $player->getLevel()->updateAround($pos);
                             $player->sendMessage($this->tag . $this->message->get("prison"));
                             break;
                         case 2:
                             $player->getLevel()->setBlock(new Position($pos->x, $pos->y - 1, $pos->z, $pos->getLevel()), new Block(Block::STILL_LAVA));
                             $player->getLevel()->setBlock(new Position($pos->x, $pos->y - 2, $pos->z, $pos->getLevel()), new Block(Block::GLASS));
                             for ($x = $pos->x - 1; $x <= $pos->x + 1; $x++) {
                                 for ($z = $pos->z - 1; $z <= $pos->z + 1; $z++) {
                                     if (!($x === $pos->x && $z === $pos->z)) {
                                         for ($y = $pos->y; $y <= $pos->y + 2; $y++) {
                                             $player->getLevel()->setBlock(new Position($x, $y, $z, $pos->getLevel()), new Block(Block::IRON_BAR));
                                         }
                                     }
                                 }
                             }
                             $player->getLevel()->updateAround($pos);
                             $player->sendMessage($this->tag . $this->message->get("prison"));
                             break;
                         case 3:
                             $player->getLevel()->setBlock(new Position($pos->x, $pos->y - 1, $pos->z, $pos->getLevel()), new Block(Block::SANDSTONE));
                             for ($x = $pos->x - 1; $x <= $pos->x + 1; $x++) {
                                 for ($z = $pos->z - 1; $z <= $pos->z + 1; $z++) {
                                     if (!($x === $pos->x && $z === $pos->z)) {
                                         for ($y = $pos->y; $y <= $pos->y + 2; $y++) {
                                             $player->getLevel()->setBlock(new Position($x, $y, $z, $pos->getLevel()), new Block(Block::IRON_BAR));
                                         }
                                     }
                                 }
                             }
                             break;
                         case 4:
                             $arr = [["x" => -1, "y" => -1, "z" => -1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => -1, "z" => 0, "block" => Block::OBSIDIAN], ["x" => -1, "y" => -1, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => -1, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => -1, "z" => 0, "block" => Block::OBSIDIAN], ["x" => 0, "y" => -1, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => -1, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => -1, "z" => 0, "block" => Block::OBSIDIAN], ["x" => 1, "y" => -1, "z" => 1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 0, "z" => -1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 0, "z" => 0, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 0, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 0, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 0, "z" => 0, "block" => Block::STILL_WATER], ["x" => 0, "y" => 0, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 0, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 0, "z" => 0, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 0, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 0, "z" => 1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 1, "z" => -1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 1, "z" => 0, "block" => Block::GLASS], ["x" => -1, "y" => 1, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 1, "z" => -1, "block" => Block::GLASS], ["x" => 0, "y" => 1, "z" => 0, "block" => Block::STILL_WATER], ["x" => 0, "y" => 1, "z" => 1, "block" => Block::GLASS], ["x" => 1, "y" => 1, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 1, "z" => 0, "block" => Block::GLASS], ["x" => 1, "y" => 1, "z" => 1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 2, "z" => -1, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 2, "z" => 0, "block" => Block::OBSIDIAN], ["x" => -1, "y" => 2, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 2, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 2, "z" => 0, "block" => Block::OBSIDIAN], ["x" => 0, "y" => 2, "z" => 1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 2, "z" => -1, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 2, "z" => 0, "block" => Block::OBSIDIAN], ["x" => 1, "y" => 2, "z" => 1, "block" => Block::OBSIDIAN]];
                             break;
                         case 5:
                             $arr = [["x" => -1, "y" => 0, "z" => -1, "block" => Block::STILL_LAVA], ["x" => -1, "y" => 0, "z" => 0, "block" => Block::STILL_LAVA], ["x" => -1, "y" => 0, "z" => 1, "block" => Block::STILL_LAVA], ["x" => 0, "y" => 0, "z" => -1, "block" => Block::STILL_LAVA], ["x" => 0, "y" => 0, "z" => 0, "block" => Block::STILL_LAVA], ["x" => 0, "y" => 0, "z" => 1, "block" => Block::STILL_LAVA], ["x" => 1, "y" => 0, "z" => -1, "block" => Block::STILL_LAVA], ["x" => 1, "y" => 0, "z" => 0, "block" => Block::STILL_LAVA], ["x" => 1, "y" => 0, "z" => 1, "block" => Block::STILL_LAVA], ["x" => -1, "y" => 1, "z" => -1, "block" => Block::COBWEB], ["x" => -1, "y" => 1, "z" => 0, "block" => Block::COBWEB], ["x" => -1, "y" => 1, "z" => 1, "block" => Block::COBWEB], ["x" => 0, "y" => 1, "z" => -1, "block" => Block::COBWEB], ["x" => 0, "y" => 1, "z" => 0, "block" => Block::COBWEB], ["x" => 0, "y" => 1, "z" => 1, "block" => Block::COBWEB], ["x" => 1, "y" => 1, "z" => -1, "block" => Block::COBWEB], ["x" => 1, "y" => 1, "z" => 0, "block" => Block::COBWEB], ["x" => 1, "y" => 1, "z" => 1, "block" => Block::COBWEB]];
                             break;
                     }
                     $pos = $player->getPosition();
                     foreach ($arr as $i => $c) {
                         $player->getLevel()->setBlock($pos->add($c["x"], $c["y"], $c["z"]), Block::get($c["block"]), true, true);
                     }
                     break;
                 }
             case 6:
                 if (!isset($this->data["functions"]["chest"]) || $this->data["functions"]["chest"]) {
                     $player->getLevel()->setBlock($block, new Block(Block::CHEST), true, true);
                     $nbt = new CompoundTag("", [new ListTag("Items", []), new StringTag("id", Tile::CHEST), new IntTag("x", $block->x), new IntTag("y", $block->y), new IntTag("z", $block->z)]);
                     $nbt->Items->setTagType(NBT::TAG_Compound);
                     $tile = Tile::createTile("Chest", $block->getLevel()->getChunk($block->x >> 4, $block->z >> 4), $nbt);
                     if ($tile instanceof Chest) {
                         for ($i = 0; $i <= mt_rand(1, $this->data["max_chest_item"]); $i++) {
                             if (count($this->data["items_dropped"]) === 0) {
                                 $item = $this->randItem();
                             } else {
                                 $item = $this->data["items_dropped"][mt_rand(0, count($this->data["items_dropped"]) - 1)];
                             }
                             $tile->getInventory()->setItem($i, $item);
                         }
                         $player->sendMessage($this->tag . $this->message->get("chest"));
                     }
                     break;
                 }
             case 7:
                 if (!isset($this->data["functions"]["teleport"]) || $this->data["functions"]["teleport"]) {
                     $player->teleport($player->getLevel()->getSpawnLocation(), $player->getYaw(), $player->getPitch());
                     $player->sendMessage($this->tag . $this->message->get("spawn"));
                     break;
                 }
             case 8:
                 if (!isset($this->data["functions"]["potion"]) || $this->data["functions"]["potion"]) {
                     if (count($this->data["potions"])) {
                         $effect = Effect::getEffectByName($this->data["potions"][$rand->nextRange(0, count($this->data["potions"]) - 1)]);
                         $effect->setDuration($rand->nextRange(20, $this->data["max_duration"] * 20));
                         $player->addEffect($effect);
                         $player->sendMessage($this->tag . $this->message->get("effect"));
                     } else {
                         $player->sendMessage($this->tag . $this->message->get("unlucky"));
                     }
                     break;
                 }
             case 9:
                 //exec command
                 if (!isset($this->data["functions"]["execCmd"]) || $this->data["functions"]["execCmd"]) {
                     if (count($this->data["commands"])) {
                         $cmd = $this->data["commands"][$rand->nextRange(0, count($this->data["commands"]) - 1)];
                         $cmd = str_replace(["%PLAYER%", "%X%", "%Y%", "%Z%", "%WORLD%", "%IP%", "%XP%"], [$player->getName(), $player->getX(), $player->getY(), $player->getZ(), $player->getLevel()->getName(), $player->getAddress(), $player->getXpLevel()], $cmd);
                         $this->getServer()->dispatchCommand(new ConsoleCommandSender(), $cmd);
                         $player->sendMessage($this->tag . $this->message->get("command"));
                         break;
                     }
                 }
             case 10:
                 //mob
                 if (!isset($this->data["functions"]["mob"]) || $this->data["functions"]["mob"]) {
                     if (count($this->data["mob"])) {
                         $mob = $this->data["mob"][$rand->nextRange(0, count($this->data["mob"]) - 1)];
                         if ($this->isExistsEntity($mob)) {
                             $nbt = new CompoundTag("", [new ListTag("Pos", [new DoubleTag("", $block->getX()), new DoubleTag("", $block->getY()), new DoubleTag("", $block->getZ())]), new ListTag("Rotation", [new FloatTag("", $player->getYaw()), new FloatTag("", $player->getPitch())]), new StringTag("CustomName", $this->tag)]);
                             $entity = Entity::createEntity($mob, $player->getLevel()->getChunk($block->getX() >> 4, $block->getZ() >> 4), $nbt);
                             if ($entity instanceof Entity) {
                                 $entity->spawnToAll();
                                 $this->getServer()->getScheduler()->scheduleDelayedTask(new TaskExplodeMob($this, $entity, mt_rand($this->data["explosion_min"], $this->data["explosion_max"])), 20 * mt_rand(1, $this->data["mob_explosion_delay"]));
                                 $player->sendMessage($this->tag . $this->message->get("mob"));
                                 break;
                             }
                         }
                     }
                 }
             case 11:
                 if (!isset($this->data["functions"]["lightning"]) || $this->data["functions"]["lightning"]) {
                     $player->getLevel()->spawnLightning($player);
                     $player->sendMessage($this->tag . $this->message->get("lightning"));
                     break;
                 }
             case 12:
                 $player->sendMessage($this->tag . $this->message->get("unlucky"));
                 break;
         }
         $player->getLevel()->save();
     }
 }
Example #22
0
 /**
  * Handles a Minecraft packet
  * TODO: Separate all of this in handlers
  *
  * WARNING: Do not use this, it's only for internal use.
  * Changes to this function won't be recorded on the version.
  *
  * @param DataPacket $packet
  */
 public function handleDataPacket(DataPacket $packet)
 {
     if ($this->connected === false) {
         return;
     }
     if ($packet->pid() === ProtocolInfo::BATCH_PACKET) {
         /** @var BatchPacket $packet */
         $this->server->getNetwork()->processBatch($packet, $this);
         return;
     }
     $this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
     if ($ev->isCancelled()) {
         return;
     }
     switch ($packet->pid()) {
         case ProtocolInfo::LOGIN_PACKET:
             /*
              * A/N: Not going to implement any session code until it actually does stuff.
              * Single line functions are obnoxious to follow.
              */
             if ($this->loggedIn === true) {
                 break;
             }
             $this->username = TextFormat::clean($packet->username);
             $this->displayName = $this->username;
             $this->setNameTag($this->username);
             $this->iusername = strtolower($this->username);
             $this->randomClientId = $packet->clientId;
             $this->loginData = ["clientId" => $packet->clientId, "loginData" => null];
             $this->uuid = $packet->clientUUID;
             $this->rawUUID = $this->uuid->toBinary();
             $this->clientSecret = $packet->clientSecret;
             $this->protocol = $packet->protocol1;
             if (count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers() and $this->kick("Server is full")) {
                 break;
             }
             if ($packet->protocol1 < ProtocolInfo::CURRENT_PROTOCOL) {
                 $message = "";
                 if ($packet->protocol1 < ProtocolInfo::CURRENT_PROTOCOL) {
                     $message = "Please update Minecraft PE to join.";
                     $pk = new PlayStatusPacket();
                     $pk->status = PlayStatusPacket::LOGIN_FAILED_CLIENT;
                     $this->dataPacket($pk);
                 } else {
                     $message = "Please use an older version of Minecraft PE.";
                     $pk = new PlayStatusPacket();
                     $pk->status = PlayStatusPacket::LOGIN_FAILED_SERVER;
                     $this->dataPacket($pk);
                 }
                 $this->close("", $message, false);
                 return;
             }
             if (strpos($packet->username, "") !== false or preg_match('#^[a-zA-Z0-9_]{3,16}$#', $packet->username) == 0 or $this->username === "" or $this->iusername === "rcon" or $this->iusername === "console" or strlen($packet->username) > 16 or strlen($packet->username) < 3) {
                 $this->close("", "Please choose a valid username.");
                 return;
             }
             if (strlen($packet->skin) < 64 * 32 * 4) {
                 $this->close("", "Invalid skin.", false);
                 return;
             }
             $this->setSkin($packet->skin, $packet->slim);
             $this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
             if ($ev->isCancelled()) {
                 $this->close("", $ev->getKickMessage());
                 return;
             }
             if (!$this->server->isWhitelisted(strtolower($this->getName()))) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "Server is private.");
                 return;
             } elseif ($this->server->getNameBans()->isBanned(strtolower($this->getName())) or $this->server->getIPBans()->isBanned($this->getAddress())) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "You have been banned.");
                 return;
             }
             if ($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)) {
                 $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
             }
             if ($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)) {
                 $this->server->getPluginManager()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
             }
             foreach ($this->server->getOnlinePlayers() as $p) {
                 if ($p !== $this and strtolower($p->getName()) === strtolower($this->getName())) {
                     if ($p->kick("You connected from somewhere else.") === false) {
                         $this->close(TextFormat::YELLOW . $this->getName() . " has left the game", "You connected from somewhere else.");
                         return;
                     } else {
                         return;
                     }
                 }
             }
             $nbt = $this->server->getOfflinePlayerData($this->username);
             if (!isset($nbt->NameTag)) {
                 $nbt->NameTag = new String("NameTag", $this->username);
             } else {
                 $nbt["NameTag"] = $this->username;
             }
             $this->gamemode = $nbt["playerGameType"] & 0x3;
             if ($this->server->getForceGamemode()) {
                 $this->gamemode = $this->server->getGamemode();
                 $nbt->playerGameType = new Int("playerGameType", $this->gamemode);
             }
             $this->allowFlight = $this->isCreative();
             if (($level = $this->server->getLevelByName($nbt["Level"])) === null) {
                 $this->setLevel($this->server->getDefaultLevel(), true);
                 $nbt["Level"] = $this->level->getName();
                 $nbt["Pos"][0] = $this->level->getSpawnLocation()->x;
                 $nbt["Pos"][1] = $this->level->getSpawnLocation()->y + 5;
                 $nbt["Pos"][2] = $this->level->getSpawnLocation()->z;
             } else {
                 $this->setLevel($level, true);
             }
             if (!$nbt instanceof Compound) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", "Corrupt joining data, check your connection.");
                 return;
             }
             $this->achievements = [];
             /** @var Byte $achievement */
             foreach ($nbt->Achievements as $achievement) {
                 $this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
             }
             $nbt->lastPlayed = new Long("lastPlayed", floor(microtime(true) * 1000));
             parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt);
             $this->loggedIn = true;
             $this->server->addOnlinePlayer($this);
             $this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
             if ($ev->isCancelled()) {
                 $this->close(TextFormat::YELLOW . $this->username . " has left the game", $ev->getKickMessage());
                 return;
             }
             if ($this->isCreative()) {
                 $this->inventory->setHeldItemSlot(0);
             } else {
                 $this->inventory->setHeldItemSlot($this->inventory->getHotbarSlotIndex(0));
             }
             $pk = new PlayStatusPacket();
             $pk->status = PlayStatusPacket::LOGIN_SUCCESS;
             $this->dataPacket($pk);
             $this->uuid = $packet->clientUUID;
             $this->rawUUID = $this->uuid->toBinary();
             $this->clientSecret = $packet->clientSecret;
             if ($this->spawnPosition === null and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level) {
                 $this->spawnPosition = new Position($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
             }
             $spawnPosition = $this->getSpawn();
             $pk = new StartGamePacket();
             $pk->seed = -1;
             $pk->dimension = 0;
             $pk->x = $this->x;
             $pk->y = $this->y;
             $pk->z = $this->z;
             $pk->spawnX = (int) $spawnPosition->x;
             $pk->spawnY = (int) $spawnPosition->y;
             $pk->spawnZ = (int) $spawnPosition->z;
             $pk->generator = 1;
             //0 old, 1 infinite, 2 flat
             $pk->gamemode = $this->gamemode & 0x1;
             $pk->eid = 0;
             //Always use EntityID as zero for the actual player
             $this->dataPacket($pk);
             $pk = new SetTimePacket();
             $pk->time = $this->level->getTime();
             $pk->started = $this->level->stopTime == false;
             $this->dataPacket($pk);
             $pk = new SetSpawnPositionPacket();
             $pk->x = (int) $spawnPosition->x;
             $pk->y = (int) $spawnPosition->y;
             $pk->z = (int) $spawnPosition->z;
             $this->dataPacket($pk);
             if ($this->getHealth() <= 0) {
                 $this->dead = true;
             }
             $pk = new SetDifficultyPacket();
             $pk->difficulty = $this->server->getDifficulty();
             $this->dataPacket($pk);
             $this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "/" . TextFormat::AQUA . $this->ip . " connected");
             if ($this->gamemode === Player::SPECTATOR) {
                 $pk = new ContainerSetContentPacket();
                 $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE;
                 $this->dataPacket($pk);
             } else {
                 $pk = new ContainerSetContentPacket();
                 $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE;
                 foreach (Item::getCreativeItems() as $item) {
                     $pk->slots[] = clone $item;
                 }
                 $this->dataPacket($pk);
             }
             $this->server->sendFullPlayerListData($this);
             $this->server->sendRecipeList($this);
             //				$this->orderChunks();
             //				$this->sendNextChunk();
             break;
         case ProtocolInfo::MOVE_PLAYER_PACKET:
             $newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
             $revert = false;
             if ($this->dead === true or $this->spawned !== true) {
                 $revert = true;
                 $this->forceMovement = new Vector3($this->x, $this->y, $this->z);
             }
             if ($this->forceMovement instanceof Vector3 and (($dist = $newPos->distanceSquared($this->forceMovement)) > 0.04 or $revert)) {
                 $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->dead === true) {
                 break;
             }
             if ($packet->slot === 0x28 or $packet->slot === 0 or $packet->slot === 255) {
                 //0 for 0.8.0 compatibility
                 $packet->slot = -1;
                 //Air
             } else {
                 $packet->slot -= 9;
                 //Get real block slot
             }
             /** @var Item $item */
             $item = null;
             if ($this->isCreative()) {
                 //Creative mode match
                 $item = $packet->item;
                 $slot = Item::getCreativeItemIndex($item);
             } else {
                 $item = $this->inventory->getItem($packet->slot);
                 $slot = $packet->slot;
             }
             if ($packet->slot === -1) {
                 //Air
                 if ($this->isCreative()) {
                     $found = false;
                     for ($i = 0; $i < $this->inventory->getHotbarSize(); ++$i) {
                         if ($this->inventory->getHotbarSlotIndex($i) === -1) {
                             $this->inventory->setHeldItemIndex($i);
                             $found = true;
                             break;
                         }
                     }
                     if (!$found) {
                         //couldn't find a empty slot (error)
                         $this->inventory->sendContents($this);
                         break;
                     }
                 } else {
                     if ($packet->selectedSlot >= 0 and $packet->selectedSlot < 9) {
                         $this->inventory->setHeldItemIndex($packet->selectedSlot);
                         $this->inventory->setHeldItemSlot($packet->slot);
                     } else {
                         $this->inventory->sendContents($this);
                         break;
                     }
                 }
             } elseif ($item === null or $slot === -1 or !$item->deepEquals($packet->item)) {
                 // packet error or not implemented
                 $this->inventory->sendContents($this);
                 break;
             } elseif ($this->isCreative()) {
                 $this->inventory->setHeldItemIndex($packet->selectedSlot);
                 $this->inventory->setItem($packet->selectedSlot, $item);
                 $this->inventory->setHeldItemSlot($packet->selectedSlot);
             } else {
                 if ($packet->selectedSlot >= 0 and $packet->selectedSlot < 9) {
                     $this->inventory->setHeldItemIndex($packet->selectedSlot);
                     $this->inventory->setHeldItemSlot($slot);
                 } else {
                     $this->inventory->sendContents($this);
                     break;
                 }
             }
             $this->inventory->sendHeldItem($this->hasSpawned);
             $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
             break;
         case ProtocolInfo::USE_ITEM_PACKET:
             if ($this->spawned === false or $this->dead === true or $this->blocked) {
                 break;
             }
             $blockVector = new Vector3($packet->x, $packet->y, $packet->z);
             $this->craftingType = 0;
             if ($packet->face >= 0 and $packet->face <= 5) {
                 //Use Block, place
                 $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
                 if ($blockVector->distance($this) > 10 or $this->isCreative() and $this->isAdventure()) {
                 } 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;
                     //TODO: Implement adventure mode checks
                     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);
                             $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) {
                 $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::SNOWBALL) {
                     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", $aimPos->x), new Double("", $aimPos->y), new Double("", $aimPos->z)]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $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();
                     }
                 }
                 $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->dead === true and $packet->action !== 7) {
                 break;
             }
             $this->craftingType = 0;
             $packet->eid = $this->id;
             $pos = new Vector3($packet->x, $packet->y, $packet->z);
             switch ($packet->action) {
                 case PlayerActionPacket::ACTION_START_BREAK:
                     if ($this->lastBreak !== PHP_INT_MAX or $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()) {
                         $this->inventory->sendHeldItem($this);
                         break;
                     }
                     $this->lastBreak = microtime(true);
                     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, 0, 1))) {
                                 $this->inventory->sendContents($this);
                                 break;
                             }
                             $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new Double("", -sin($this->pitch / 180 * M_PI)), new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $this->pitch)]), "Fire" => new Short("Fire", $this->isOnFire() ? 45 * 60 : 0)]);
                             $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, 0, 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;
                         $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_RESPAWN:
                     if ($this->spawned === false or $this->isAlive() or !$this->isOnline()) {
                         break;
                     }
                     if ($this->server->isHardcore()) {
                         $this->setBanned(true);
                         break;
                     }
                     $this->craftingType = 0;
                     $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->dead = false;
                     $this->noDamageTicks = 60;
                     $this->setHealth($this->getMaxHealth());
                     $this->setFood(20);
                     $this->starvationTick = 0;
                     $this->foodTick = 0;
                     $this->lastSentVitals = 10;
                     $this->foodUsageTime = 0;
                     $this->removeAllEffects();
                     $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;
                 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;
                 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;
                 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;
             }
             $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->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $vector = new Vector3($packet->x, $packet->y, $packet->z);
             if ($this->isCreative()) {
                 $item = $this->inventory->getItemInHand();
             } else {
                 $item = $this->inventory->getItemInHand();
             }
             $oldItem = clone $item;
             if ($this->level->useBreakOn($vector, $item, $this) === true) {
                 if ($this->isSurvival()) {
                     if (!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()) {
                         $this->inventory->setItemInHand($item, $this);
                         $this->inventory->sendHeldItem($this->hasSpawned);
                     }
                 }
                 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:
             break;
         case ProtocolInfo::INTERACT_PACKET:
             if ($this->spawned === false or $this->dead === true or $this->blocked) {
                 break;
             }
             $this->craftingType = 0;
             $target = $this->level->getEntity($packet->target);
             $cancelled = false;
             if ($target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false) {
                 $cancelled = true;
             }
             if ($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->dead !== true and $target->dead !== true) {
                 if ($target instanceof DroppedItem or $target instanceof Arrow) {
                     $this->kick("Attempting to attack an invalid entity");
                     $this->server->getLogger()->warning("Player " . $this->getName() . " tried to attack an invalid entity");
                     return;
                 }
                 $item = $this->inventory->getItemInHand();
                 $damageTable = [Item::WOODEN_SWORD => 4, Item::GOLD_SWORD => 4, Item::STONE_SWORD => 5, Item::IRON_SWORD => 6, Item::DIAMOND_SWORD => 7, Item::WOODEN_AXE => 3, Item::GOLD_AXE => 3, Item::STONE_AXE => 3, Item::IRON_AXE => 5, Item::DIAMOND_AXE => 6, Item::WOODEN_PICKAXE => 2, Item::GOLD_PICKAXE => 2, Item::STONE_PICKAXE => 3, Item::IRON_PICKAXE => 4, Item::DIAMOND_PICKAXE => 5, Item::WOODEN_SHOVEL => 1, Item::GOLD_SHOVEL => 1, Item::STONE_SHOVEL => 2, Item::IRON_SHOVEL => 3, Item::DIAMOND_SHOVEL => 4];
                 $damage = [EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1];
                 if ($this->distance($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;
                     }
                     $armorValues = [Item::LEATHER_CAP => 1, Item::LEATHER_TUNIC => 3, Item::LEATHER_PANTS => 2, Item::LEATHER_BOOTS => 1, Item::CHAIN_HELMET => 1, Item::CHAIN_CHESTPLATE => 5, Item::CHAIN_LEGGINGS => 4, Item::CHAIN_BOOTS => 1, Item::GOLD_HELMET => 1, Item::GOLD_CHESTPLATE => 5, Item::GOLD_LEGGINGS => 3, Item::GOLD_BOOTS => 1, Item::IRON_HELMET => 2, Item::IRON_CHESTPLATE => 6, Item::IRON_LEGGINGS => 5, Item::IRON_BOOTS => 2, Item::DIAMOND_HELMET => 3, Item::DIAMOND_CHESTPLATE => 8, Item::DIAMOND_LEGGINGS => 6, Item::DIAMOND_BOOTS => 3];
                     $points = 0;
                     foreach ($target->getInventory()->getArmorContents() as $index => $i) {
                         if (isset($armorValues[$i->getId()])) {
                             $points += $armorValues[$i->getId()];
                         }
                     }
                     $damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
                 }
                 $ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
                 if ($cancelled) {
                     $ev->setCancelled();
                 }
                 $target->attack($ev->getFinalDamage(), $ev);
                 if ($ev->isCancelled()) {
                     if ($item->isTool() and $this->isSurvival()) {
                         $this->inventory->sendContents($this);
                     }
                     break;
                 }
                 if ($item->isTool() and $this->isSurvival()) {
                     if ($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()) {
                         $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1), $this);
                     } else {
                         $this->inventory->setItemInHand($item, $this);
                     }
                 }
             }
             break;
         case ProtocolInfo::ANIMATE_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 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->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
             //TODO: check if this should be true
             switch ($packet->event) {
                 case 9:
                     //Eating
                     $this->eatFoodInHand();
                     break;
             }
             break;
         case ProtocolInfo::DROP_ITEM_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             if (!$this->inventory->contains($packet->item)) {
                 $this->inventory->sendContents($this);
                 break;
             }
             $slot = $this->inventory->first($packet->item);
             if ($slot == -1) {
                 break;
             }
             $item = $this->inventory->getItem($slot);
             $ev = new PlayerDropItemEvent($this, $item);
             $this->server->getPluginManager()->callEvent($ev);
             if ($ev->isCancelled()) {
                 $this->inventory->sendSlot($slot, $this);
                 break;
             }
             $this->inventory->setItem($slot, Item::get(Item::AIR, null, 0));
             $motion = $this->getDirectionVector()->multiply(0.4);
             $this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
             $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
             break;
         case ProtocolInfo::TEXT_PACKET:
             if ($this->spawned === false or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             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($ev->getPlayer()->getDisplayName() . ": " . $ev->getMessage(), $ev->getRecipients());
                             }
                         }
                         $ev = new PlayerCommandPostprocessEvent($this, $message);
                         $this->server->getPluginManager()->callEvent($ev);
                     }
                 }
             }
             break;
         case ProtocolInfo::CONTAINER_CLOSE_PACKET:
             if ($this->spawned === false or $packet->windowid === 0) {
                 break;
             }
             $this->craftingType = 0;
             $this->currentTransaction = null;
             if (isset($this->windowIndex[$packet->windowid])) {
                 $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this));
                 $this->removeWindow($this->windowIndex[$packet->windowid]);
             } else {
                 unset($this->windowIndex[$packet->windowid]);
             }
             break;
         case ProtocolInfo::CRAFTING_EVENT_PACKET:
             if ($this->spawned === false or $this->dead) {
                 break;
             } 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 ($recipe === null or ($recipe instanceof BigShapelessRecipe or $recipe instanceof BigShapedRecipe) and $this->craftingType === 0) {
                 $this->inventory->sendContents($this);
                 break;
             }
             foreach ($packet->input as $i => $item) {
                 if ($item->getDamage() === -1 or $item->getDamage() === 0xffff) {
                     $item->setDamage(null);
                 }
                 if ($i < 9 and $item->getId() > 0) {
                     $item->setCount(1);
                 }
             }
             $canCraft = true;
             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 or !$ingredient->deepEquals($item, $ingredient->getDamage() !== null, $ingredient->getCompoundTag() !== null)) {
                                 $canCraft = false;
                                 break;
                             }
                         } elseif ($ingredient !== null and $ingredient->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 === $item and $n->getDamage() !== null and $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;
             }
             /** @var Item[] $ingredients */
             $ingredients = $packet->input;
             $result = $packet->output[0];
             if (!$canCraft or !$recipe->getResult() === $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 === $i and $i->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($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) {
                 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;
                 }
                 if ($this->isCreative()) {
                     if (Item::getCreativeItemIndex($packet->item) !== -1) {
                         $this->inventory->setItem($packet->slot, $packet->item);
                         $this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot);
                         //links $hotbar[$packet->slot] to $slots[$packet->slot]
                     }
                 }
                 $transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($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(), $this->inventory->getArmorItem($packet->slot), $packet->item);
             } elseif (isset($this->windowIndex[$packet->windowid])) {
                 $this->craftingType = 0;
                 $inv = $this->windowIndex[$packet->windowid];
                 $transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item);
             } else {
                 break;
             }
             if ($transaction->getSourceItem() === $transaction->getTargetItem() and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()) {
                 //No changes!
                 //No changes, just a local inventory update sent by the server
                 break;
             }
             if ($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < microtime(true) - 8) {
                 if ($this->currentTransaction !== null) {
                     foreach ($this->currentTransaction->getInventories() as $inventory) {
                         if ($inventory instanceof PlayerInventory) {
                             $inventory->sendArmorContents($this);
                         }
                         $inventory->sendContents($this);
                     }
                 }
                 $this->currentTransaction = new SimpleTransactionGroup($this);
             }
             $this->currentTransaction->addTransaction($transaction);
             if ($this->currentTransaction->canExecute()) {
                 $achievements = [];
                 foreach ($this->currentTransaction->getTransactions() as $ts) {
                     $inv = $ts->getInventory();
                     if ($inv instanceof FurnaceInventory) {
                         if ($ts->getSlot() === 2) {
                             switch ($inv->getResult()->getId()) {
                                 case Item::IRON_INGOT:
                                     $achievements[] = "acquireIron";
                                     break;
                             }
                         }
                     }
                 }
                 if ($this->currentTransaction->execute()) {
                     foreach ($achievements as $a) {
                         $this->awardAchievement($a);
                     }
                 }
                 $this->currentTransaction = null;
             }
             break;
         case ProtocolInfo::TILE_ENTITY_DATA_PACKET:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             $this->craftingType = 0;
             $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->username) {
                         $ev->setCancelled(true);
                     }
                     $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;
     }
 }
Example #23
0
 public function SkeletonRandomWalk()
 {
     foreach ($this->plugin->getServer()->getLevels() as $level) {
         foreach ($level->getEntities() as $zo) {
             if ($zo instanceof Skeleton) {
                 if (isset($this->plugin->Skeleton[$zo->getId()])) {
                     $zom =& $this->plugin->Skeleton[$zo->getId()];
                     if ($zom['canAttack'] != 0) {
                         $zom['canAttack'] -= 1;
                     }
                     $pos = $zo->getLocation();
                     //echo ($zom['IsChasing']."\n");
                     //真正的自由落体 by boybook
                     if ($zom['drop'] !== false) {
                         $olddrop = $zom['drop'];
                         $zom['drop'] += 0.5;
                         $drop = $zom['drop'];
                         //echo $drop."\n";
                         $dropy = $zo->getY() - ($olddrop * 0.05 + 0.0125);
                         $posd0 = new Vector3(floor($zo->getX()), floor($dropy), floor($zo->getZ()));
                         $posd = new Vector3($zo->getX(), $dropy, $zo->getZ());
                         if ($this->plugin->whatBlock($zo->getLevel(), $posd0) == "air") {
                             $zo->setPosition($posd);
                             //下降
                         } else {
                             for ($i = 1; $i <= $drop; $i++) {
                                 $posd0->y++;
                                 if ($this->plugin->whatBlock($zo->getLevel(), $posd0) != "block") {
                                     $posd->y = $posd0->y;
                                     $zo->setPosition($posd);
                                     //下降完成
                                     $h = $zom['drop'] * $zom['drop'] / 20;
                                     $damage = $h - 3;
                                     //echo($h . ": " . $damage . "\n");
                                     if ($damage > 0) {
                                         //$zo->attack($damage, EntityDamageEvent::CAUSE_FALL);
                                         $zo->setHealth($zo->getHealth() - $damage);
                                     }
                                     $zom['drop'] = false;
                                     break;
                                 }
                             }
                         }
                     } else {
                         $drop = 0;
                     }
                     if ($zom['IsChasing'] !== false) {
                         if (!$zom['knockBack']) {
                             //echo $zy;
                             $zom['up'] = 0;
                             if ($this->plugin->whatBlock($level, $pos) == "water") {
                                 $zom['swim'] += 1;
                                 if ($zom['swim'] >= 20) {
                                     $zom['swim'] = 0;
                                 }
                             } else {
                                 $zom['swim'] = 0;
                             }
                             //echo("目标:".$zo->getY()." ");
                             //echo("原先:".$zom['oldv3']->y."\n");
                             if (abs($zo->getY() - $zom['oldv3']->y) == 1 and $zom['canjump'] === true) {
                                 //var_dump("跳");
                                 $zom['canjump'] = false;
                                 $zom['jump'] = 0.5;
                             } else {
                                 if ($zom['jump'] > 0.01) {
                                     $zom['jump'] -= 0.1;
                                 } else {
                                     $zom['jump'] = 0.01;
                                 }
                             }
                             $pk3 = new SetEntityMotionPacket();
                             $pk3->entities = [[$zo->getID(), $zom['xxx'] / 10, -$zom['swim'] / 100 + $zom['jump'] - $drop, $zom['zzz'] / 10]];
                             foreach ($zo->getViewers() as $pl) {
                                 $pl->dataPacket($pk3);
                             }
                             $p = $this->plugin->getServer()->getPlayer($zom['IsChasing']);
                             if ($p instanceof Player) {
                                 $zom['shoot'] = $zom['shoot'] - 1;
                                 if ($zom['shoot'] <= 0) {
                                     //boom
                                     $zom['shoot'] = 20;
                                     $v3 = new Vector3($zo->getX(), $zo->getY() + 2, $zo->getZ());
                                     $chunk = $level->getChunk($v3->x >> 4, $v3->z >> 4, true);
                                     $posnn = new Vector3($zo->getX(), $p->getY(), $zo->getZ());
                                     $my = $p->getY() - $zo->getY();
                                     $d = $p->distance($posnn);
                                     $pitch = $this->getmypitch($my, $d);
                                     $nbt2 = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $zo->getX()), new Double("", $zo->getY()), new Double("", $zo->getZ())]), "Motion" => new Enum("Motion", [new Double("", -\sin($zom['yaw']) * \cos($pitch / 180 * M_PI)), new Double("", -\sin($pitch / 180 * M_PI)), new Double("", \cos($zom['yaw'] / 180 * M_PI) * \cos($pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $zom['yaw']), new Float("", $pitch)])]);
                                     $f = 1.5;
                                     //$ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this), $f);
                                     $ev = new EntityShootBowEvent($zo, new ITEM(262, 0), Entity::createEntity("Arrow", $chunk, $nbt2, $zo), $f);
                                 }
                             }
                         }
                     } else {
                         if ($zom['up'] == 1) {
                             if ($zom['yup'] <= 10) {
                                 $pk3 = new SetEntityMotionPacket();
                                 $pk3->entities = [[$zo->getID(), $zom['motionx'] / 10, $zom['motiony'] / 10, $zom['motionz'] / 10]];
                                 foreach ($zo->getViewers() as $pl) {
                                     $pl->dataPacket($pk3);
                                 }
                             } else {
                                 $pk3 = new SetEntityMotionPacket();
                                 $pk3->entities = [[$zo->getID(), $zom['motionx'] / 10 - $zom['motiony'] / 10, $zom['motionz'] / 10]];
                                 foreach ($zo->getViewers() as $pl) {
                                     $pl->dataPacket($pk3);
                                 }
                             }
                         } else {
                             $pk3 = new SetEntityMotionPacket();
                             $pk3->entities = [[$zo->getID(), $zom['motionx'] / 10, -$zom['motiony'] / 10, $zom['motionz'] / 10]];
                             foreach ($zo->getViewers() as $pl) {
                                 $pl->dataPacket($pk3);
                             }
                         }
                     }
                 }
             }
         }
     }
 }
Example #24
0
 public function activate()
 {
     $itemIndex = [];
     for ($i = 0; $i < $this->getSize(); $i++) {
         $item = $this->getInventory()->getItem($i);
         if ($item->getId() != Item::AIR) {
             $itemIndex[] = [$i, $item];
         }
     }
     $max = count($itemIndex) - 1;
     if ($max < 0) {
         $itemArr = null;
     } elseif ($max == 0) {
         $itemArr = $itemIndex[0];
     } else {
         $itemArr = $itemIndex[mt_rand(0, $max)];
     }
     if (is_array($itemArr)) {
         /** @var Item $item */
         $item = $itemArr[1];
         $item->setCount($item->getCount() - 1);
         $this->getInventory()->setItem($itemArr[0], $item->getCount() > 0 ? $item : Item::get(Item::AIR));
         $motion = $this->getMotion();
         $needItem = Item::get($item->getId(), $item->getDamage());
         $f = 1.5;
         switch ($needItem->getId()) {
             case Item::ARROW:
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)]), "Fire" => new ShortTag("Fire", 0)]);
                 $arrow = Entity::createEntity("Arrow", $this->chunk, $nbt);
                 $arrow->setMotion($arrow->getMotion()->multiply($f));
                 $arrow->spawnToAll();
                 break;
             case Item::SNOWBALL:
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)])]);
                 $snowball = Entity::createEntity("Snowball", $this->chunk, $nbt);
                 $snowball->setMotion($snowball->getMotion()->multiply($f));
                 $snowball->spawnToAll();
                 break;
             case Item::EGG:
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)])]);
                 $egg = Entity::createEntity("Egg", $this->chunk, $nbt);
                 $egg->setMotion($egg->getMotion()->multiply($f));
                 $egg->spawnToAll();
                 break;
             case Item::SPLASH_POTION:
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)]), "PotionId" => new ShortTag("PotionId", $item->getDamage())]);
                 $thrownPotion = Entity::createEntity("ThrownPotion", $this->chunk, $nbt);
                 $thrownPotion->setMotion($thrownPotion->getMotion()->multiply($f));
                 $thrownPotion->spawnToAll();
                 break;
             case Item::ENCHANTING_BOTTLE:
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)])]);
                 $thrownExpBottle = Entity::createEntity("ThrownExpBottle", $this->chunk, $nbt);
                 $thrownExpBottle->setMotion($thrownExpBottle->getMotion()->multiply($f));
                 $thrownExpBottle->spawnToAll();
                 break;
             default:
                 $itemTag = NBT::putItemHelper($needItem);
                 $itemTag->setName("Item");
                 $nbt = new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $this->x + $motion[0] * 2 + 0.5), new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)), new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)]), "Motion" => new ListTag("Motion", [new DoubleTag("", $motion[0]), new DoubleTag("", $motion[1]), new DoubleTag("", $motion[2])]), "Rotation" => new ListTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)]), "Health" => new ShortTag("Health", 5), "Item" => $itemTag, "PickupDelay" => new ShortTag("PickupDelay", 10)]);
                 $f = 0.3;
                 $itemEntity = new ItemEntity($this->chunk, $nbt, $this);
                 $itemEntity->setMotion($itemEntity->getMotion()->multiply($f));
                 $itemEntity->spawnToAll();
                 break;
         }
         for ($i = 1; $i < 10; $i++) {
             $this->getLevel()->addParticle(new SmokeParticle($this->add($motion[0] * $i * 0.3 + 0.5, $motion[1] == 0 ? 0.5 : $motion[1] * $i * 0.3, $motion[2] * $i * 0.3 + 0.5)));
         }
     }
 }
Example #25
0
 public function execute(CommandSender $sender, $currentAlias, array $args)
 {
     if (!$this->testPermission($sender)) {
         return true;
     }
     if (count($args) != 1 and count($args) != 4 and count($args) != 5) {
         $sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
         return true;
     }
     $x = 0;
     $y = 0;
     $z = 0;
     if (count($args) == 4 or count($args) == 5) {
         //position is set
         //TODO:simpilify them to one piece of code
         //Code for setting $x
         if (is_numeric($args[1])) {
             //x is given directly
             $x = $args[1];
         } elseif (strcmp($args[1], "~") >= 0) {
             //x is given with a "~"
             $offset_x = trim($args[1], "~");
             if ($sender instanceof Player) {
                 //using in-game
                 $x = is_numeric($offset_x) ? $sender->x + $offset_x : $sender->x;
             } else {
                 //using in console
                 $sender->sendMessage(TextFormat::RED . "You must specify a position where the entity is spawned to when using in console");
                 return false;
             }
         } else {
             //other circumstances
             $sender->sendMessage(TextFormat::RED . "Argument error");
             return false;
         }
         //Code for setting $y
         if (is_numeric($args[2])) {
             //y is given directly
             $y = $args[2];
         } elseif (strcmp($args[2], "~") >= 0) {
             //y is given with a "~"
             $offset_y = trim($args[2], "~");
             if ($sender instanceof Player) {
                 //using in-game
                 $y = is_numeric($offset_y) ? $sender->y + $offset_y : $sender->y;
                 if ($y < 0) {
                     $y = 0;
                 }
                 //in case y is outside the range of [0,128]
                 if ($y > 128) {
                     $y = 128;
                 }
             } else {
                 //using in console
                 $sender->sendMessage(TextFormat::RED . "You must specify a position where the entity is spawned to when using in console");
                 return false;
             }
         } else {
             //other circumstances
             $sender->sendMessage(TextFormat::RED . "Argument error");
             return false;
         }
         //Code for setting $z
         if (is_numeric($args[3])) {
             //z is given directly
             $z = $args[3];
         } elseif (strcmp($args[3], "~") >= 0) {
             //z is given with a "~"
             $offset_z = trim($args[3], "~");
             if ($sender instanceof Player) {
                 //using in-game
                 $z = is_numeric($offset_z) ? $sender->z + $offset_z : $sender->z;
             } else {
                 //using in console
                 $sender->sendMessage(TextFormat::RED . "You must specify a position where the entity is spawned to when using in console");
                 return false;
             }
         } else {
             //other circumstances
             $sender->sendMessage(TextFormat::RED . "Argument error");
             return false;
         }
     }
     //finish setting the location
     if (count($args) == 1) {
         if ($sender instanceof Player) {
             $x = $sender->x;
             $y = $sender->y;
             $z = $sender->z;
         } else {
             $sender->sendMessage(TextFormat::RED . "You must specify a position where the entity is spawned to when using in console");
             return false;
         }
     }
     //finish setting the location
     $entity = null;
     $type = $args[0];
     $level = $sender instanceof Player ? $sender->getLevel() : $sender->getServer()->getDefaultLevel();
     $chunk = $level->getChunk(round($x) >> 4, round($z) >> 4);
     $nbt = new CompoundTag("", ["Pos" => new EnumTag("Pos", [new DoubleTag("", $x), new DoubleTag("", $y), new DoubleTag("", $z)]), "Motion" => new EnumTag("Motion", [new DoubleTag("", 0), new DoubleTag("", 0), new DoubleTag("", 0)]), "Rotation" => new EnumTag("Rotation", [new FloatTag("", lcg_value() * 360), new FloatTag("", 0)])]);
     $entity = Entity::createEntity($type, $chunk, $nbt);
     if ($entity instanceof Entity) {
         $entity->spawnToAll();
         $sender->sendMessage("Successfully spawned entity {$type} at ({$x}, {$y}, {$z})");
         return true;
     } else {
         $sender->sendMessage(TextFormat::RED . "An error occurred when spawning the entity {$type}");
         return false;
     }
 }
Example #26
0
 private function scorchit($pos, $dir, $fuse)
 {
     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $pos->x), new Double("", $pos->y), new Double("", $pos->z)]), "Motion" => new Enum("Motion", [new Double("", $dir->x), new Double("", $dir->y), new Double("", $dir->z)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "Fuse" => new Byte("Fuse", $fuse)]);
     $entity = Entity::createEntity("PrimedTNT", $pos->getLevel()->getChunk($pos->x >> 4, $pos->z >> 4), $nbt);
     $entity->namedtag->setName("Scorched");
     $entity->spawnToAll();
     return true;
 }
Example #27
-1
 public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz)
 {
     $entity = null;
     $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4);
     if (!$chunk instanceof FullChunk) {
         return false;
     }
     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $block->getX() + 0.5), new Double("", $block->getY()), new Double("", $block->getZ() + 0.5)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", lcg_value() * 360), new Float("", 0)])]);
     if ($this->hasCustomName()) {
         $nbt->CustomName = new String("CustomName", $this->getCustomName());
     }
     $entity = Entity::createEntity($this->meta, $chunk, $nbt);
     if ($entity instanceof Entity) {
         $entity->setDataProperty(15, Entity::DATA_TYPE_BYTE, 1);
         $entity->getLevel()->getServer()->broadcastPopup(TextFormat::RED . "Mob AI isn't implemented yet!");
         if ($player->isSurvival()) {
             --$this->count;
         }
         $entity->spawnToAll();
         return true;
     }
     return false;
 }
Example #28
-1
 public function onActivate(Level $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz)
 {
     if ($target->isTransparent() === false and $face > 1 and $block->isSolid() === false) {
         $chunk = $level->getChunk($block->getX() >> 4, $block->getZ() >> 4);
         $faces = [2 => 1, 3 => 3, 4 => 0, 5 => 2];
         $motives = [["Kebab", 1, 1], ["Aztec", 1, 1], ["Alban", 1, 1], ["Aztec2", 1, 1], ["Bomb", 1, 1], ["Plant", 1, 1], ["Wasteland", 1, 1], ["Wanderer", 1, 2], ["Graham", 1, 2], ["Pool", 2, 1], ["Courbet", 2, 1], ["Sunset", 2, 1], ["Sea", 2, 1], ["Creebet", 2, 1], ["Match", 2, 2], ["Bust", 2, 2], ["Stage", 2, 2], ["Void", 2, 2], ["SkullAndRoses", 2, 2], ["Fighters", 4, 2], ["Skeleton", 4, 3], ["DonkeyKong", 4, 3], ["Pointer", 4, 4], ["Pigscene", 4, 4], ["Flaming Skull", 4, 4]];
         if ($this->hasCustomName()) {
             $nbt->CustomName = new String("CustomName", $this->getCustomName());
         }
         $motive = $motives[mt_rand(0, count($motives) - 1)];
         $data = ["x" => $target->x, "y" => $target->y, "z" => $target->z, "yaw" => $faces[$face] * 90, "Motive" => $motive[0]];
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $target->x), new Double("", $target->y), new Double("", $target->z)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", $faces[$face] * 90), new Float("", 0)])]);
         $entity = Entity::createEntity($this->meta, $chunk, $nbt, $data);
         if ($entity instanceof Entity) {
             if ($player->isSurvival()) {
                 --$this->count;
             }
             $entity->spawnToAll();
             return true;
         }
         return true;
     }
     return false;
 }
Example #29
-1
 /**
  * @param Vector3 $source
  * @param Item    $item
  * @param Vector3 $motion
  * @param int     $delay
  */
 public function dropItem(Vector3 $source, Item $item, Vector3 $motion = null, $delay = 10)
 {
     $motion = $motion === null ? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1) : $motion;
     if ($item->getId() > 0 and $item->getCount() > 0) {
         $itemEntity = Entity::createEntity("Item", $this->getChunk($source->getX() >> 4, $source->getZ() >> 4), new Compound("", ["Pos" => new Enum("Pos", [new Double("", $source->getX()), new Double("", $source->getY()), new Double("", $source->getZ())]), "Motion" => new Enum("Motion", [new Double("", $motion->x), new Double("", $motion->y), new Double("", $motion->z)]), "Rotation" => new Enum("Rotation", [new Float("", lcg_value() * 360), new Float("", 0)]), "Health" => new Short("Health", 5), "Item" => new Compound("Item", ["id" => new Short("id", $item->getId()), "Damage" => new Short("Damage", $item->getDamage()), "Count" => new Byte("Count", $item->getCount())]), "PickupDelay" => new Short("PickupDelay", $delay)]));
         $itemEntity->spawnToAll();
     }
 }
Example #30
-2
 /**
  * Handles a Minecraft packet
  * TODO: Separate all of this in handlers
  *
  * WARNING: Do not use this, it's only for internal use.
  * Changes to this function won't be recorded on the version.
  *
  * @param DataPacket $packet
  */
 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::LOGIN_PACKET:
             if ($this->loggedIn) {
                 break;
             }
             $this->username = TextFormat::clean($packet->username);
             $this->displayName = $this->username;
             $this->setNameTag($this->username);
             $this->iusername = strtolower($this->username);
             if (count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)) {
                 break;
             }
             if ($packet->protocol1 !== ProtocolInfo::CURRENT_PROTOCOL) {
                 if ($packet->protocol1 < 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->loginData = ["clientId" => $packet->clientId, "loginData" => null];
             $this->uuid = $packet->clientUUID;
             $this->rawUUID = $this->uuid->toBinary();
             $this->clientSecret = $packet->clientSecret;
             $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 * 32 * 4 and strlen($packet->skin) !== 64 * 64 * 4) {
                 $this->close("", "disconnectionScreen.invalidSkin");
                 break;
             }
             $this->setSkin($packet->skin, $packet->skinname, $packet->oldclient, $packet->slim, $packet->transparent);
             $this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
             if ($ev->isCancelled()) {
                 $this->close("", $ev->getKickMessage());
                 break;
             }
             $this->onPlayerPreLogin();
             break;
         case ProtocolInfo::MOVE_PLAYER_PACKET:
             $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)) {
                 $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;
             }
             if ($packet->slot === 0x28 or $packet->slot === 0 or $packet->slot === 255) {
                 //0 for 0.8.0 compatibility
                 $packet->slot = -1;
                 //Air
             } else {
                 $packet->slot -= 9;
                 //Get real block slot
             }
             /** @var Item $item */
             $item = null;
             if ($this->isCreative()) {
                 //Creative mode match
                 $item = $packet->item;
                 $slot = Item::getCreativeItemIndex($item);
             } else {
                 $item = $this->inventory->getItem($packet->slot);
                 $slot = $packet->slot;
             }
             if ($packet->slot === -1) {
                 //Air
                 if ($this->isCreative()) {
                     $found = false;
                     for ($i = 0; $i < $this->inventory->getHotbarSize(); ++$i) {
                         if ($this->inventory->getHotbarSlotIndex($i) === -1) {
                             $this->inventory->setHeldItemIndex($i);
                             $found = true;
                             break;
                         }
                     }
                     if (!$found) {
                         //couldn't find a empty slot (error)
                         $this->inventory->sendContents($this);
                         break;
                     }
                 } else {
                     if ($packet->selectedSlot >= 0 and $packet->selectedSlot < 9) {
                         $this->inventory->setHeldItemIndex($packet->selectedSlot);
                         $this->inventory->setHeldItemSlot($packet->slot);
                     } else {
                         $this->inventory->sendContents($this);
                         break;
                     }
                 }
             } elseif ($item === null or $slot === -1 or !$item->deepEquals($packet->item)) {
                 // packet error or not implemented
                 $this->inventory->sendContents($this);
                 break;
             } elseif ($this->isCreative()) {
                 $this->inventory->setHeldItemIndex($packet->selectedSlot);
                 $this->inventory->setItem($packet->selectedSlot, $item);
                 $this->inventory->setHeldItemSlot($packet->selectedSlot);
             } else {
                 if ($packet->selectedSlot >= 0 and $packet->selectedSlot < $this->inventory->getHotbarSize()) {
                     $this->inventory->setHeldItemIndex($packet->selectedSlot);
                     $this->inventory->setHeldItemSlot($slot);
                 } else {
                     $this->inventory->sendContents($this);
                     break;
                 }
             }
             $this->inventory->sendHeldItem($this->hasSpawned);
             $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 = 0;
             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;
                     //TODO: Implement adventure mode checks
                     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) {
                 $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::SNOWBALL) {
                     $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", $aimPos->x), new Double("", $aimPos->y), new Double("", $aimPos->z)]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $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();
                     }
                 }
                 $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_RESPAWN and $packet->action !== PlayerActionPacket::ACTION_DIMENSION_CHANGE) {
                 break;
             }
             $packet->eid = $this->id;
             $pos = new Vector3($packet->x, $packet->y, $packet->z);
             switch ($packet->action) {
                 case PlayerActionPacket::ACTION_START_BREAK:
                     if ($this->lastBreak !== PHP_INT_MAX or $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()) {
                         $this->inventory->sendHeldItem($this);
                         break;
                     }
                     $this->lastBreak = microtime(true);
                     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, 0, 1))) {
                                 $this->inventory->sendContents($this);
                                 break;
                             }
                             $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $this->x), new Double("", $this->y + $this->getEyeHeight()), new Double("", $this->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)), new Double("", -sin($this->pitch / 180 * M_PI)), new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $this->pitch)]), "Fire" => new Short("Fire", $this->isOnFire() ? 45 * 60 : 0)]);
                             $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, 0, 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;
                         $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_RESPAWN:
                     if ($this->spawned === false or $this->isAlive() or !$this->isOnline()) {
                         break;
                     }
                     if ($this->server->isHardcore()) {
                         $this->setBanned(true);
                         break;
                     }
                     $this->craftingType = 0;
                     $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->setHealth($this->getMaxHealth());
                     $this->removeAllEffects();
                     $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;
                 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;
                 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;
                 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;
             }
             $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 = 0;
             $vector = new Vector3($packet->x, $packet->y, $packet->z);
             if ($this->isCreative()) {
                 $item = $this->inventory->getItemInHand();
             } else {
                 $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)) {
                 if ($this->isSurvival()) {
                     if (!$item->deepEquals($oldItem) or $item->getCount() !== $oldItem->getCount()) {
                         $this->inventory->setItemInHand($item);
                         $this->inventory->sendHeldItem($this->hasSpawned);
                     }
                 }
                 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:
             break;
         case ProtocolInfo::INTERACT_PACKET:
             if ($this->spawned === false or !$this->isAlive() or $this->blocked) {
                 break;
             }
             $this->craftingType = 0;
             $target = $this->level->getEntity($packet->target);
             $cancelled = false;
             if ($target instanceof Player and $this->server->getConfigBoolean("pvp", true) === false) {
                 $cancelled = true;
             }
             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();
                 $damageTable = [Item::WOODEN_SWORD => 4, Item::GOLD_SWORD => 4, Item::STONE_SWORD => 5, Item::IRON_SWORD => 6, Item::DIAMOND_SWORD => 7, Item::WOODEN_AXE => 3, Item::GOLD_AXE => 3, Item::STONE_AXE => 3, Item::IRON_AXE => 5, Item::DIAMOND_AXE => 6, Item::WOODEN_PICKAXE => 2, Item::GOLD_PICKAXE => 2, Item::STONE_PICKAXE => 3, Item::IRON_PICKAXE => 4, Item::DIAMOND_PICKAXE => 5, Item::WOODEN_SHOVEL => 1, Item::GOLD_SHOVEL => 1, Item::STONE_SHOVEL => 2, Item::IRON_SHOVEL => 3, Item::DIAMOND_SHOVEL => 4];
                 $damage = [EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1];
                 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;
                     }
                     $armorValues = [Item::LEATHER_CAP => 1, Item::LEATHER_TUNIC => 3, Item::LEATHER_PANTS => 2, Item::LEATHER_BOOTS => 1, Item::CHAIN_HELMET => 1, Item::CHAIN_CHESTPLATE => 5, Item::CHAIN_LEGGINGS => 4, Item::CHAIN_BOOTS => 1, Item::GOLD_HELMET => 1, Item::GOLD_CHESTPLATE => 5, Item::GOLD_LEGGINGS => 3, Item::GOLD_BOOTS => 1, Item::IRON_HELMET => 2, Item::IRON_CHESTPLATE => 6, Item::IRON_LEGGINGS => 5, Item::IRON_BOOTS => 2, Item::DIAMOND_HELMET => 3, Item::DIAMOND_CHESTPLATE => 8, Item::DIAMOND_LEGGINGS => 6, Item::DIAMOND_BOOTS => 3];
                     $points = 0;
                     foreach ($target->getInventory()->getArmorContents() as $index => $i) {
                         if (isset($armorValues[$i->getId()])) {
                             $points += $armorValues[$i->getId()];
                         }
                     }
                     $damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
                 }
                 $ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
                 if ($cancelled) {
                     $ev->setCancelled();
                 }
                 $target->attack($ev->getFinalDamage(), $ev);
                 if ($ev->isCancelled()) {
                     if ($item->isTool() and $this->isSurvival()) {
                         $this->inventory->sendContents($this);
                     }
                     break;
                 }
                 if ($item->isTool() and $this->isSurvival()) {
                     if ($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()) {
                         $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
                     } else {
                         $this->inventory->setItemInHand($item);
                     }
                 }
             }
             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 = 0;
             $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
             //TODO: check if this should be true
             switch ($packet->event) {
                 case 9:
                     //Eating
                     $items = [Item::APPLE => 4, Item::MUSHROOM_STEW => 10, Item::BEETROOT_SOUP => 10, Item::BREAD => 5, Item::RAW_PORKCHOP => 3, Item::COOKED_PORKCHOP => 8, Item::RAW_BEEF => 3, Item::STEAK => 8, Item::COOKED_CHICKEN => 6, Item::RAW_CHICKEN => 2, Item::MELON_SLICE => 2, Item::GOLDEN_APPLE => 10, Item::PUMPKIN_PIE => 8, Item::CARROT => 4, Item::POTATO => 1, Item::BAKED_POTATO => 6, Item::COOKIE => 2, Item::COOKED_FISH => 5, Item::COOKED_SALMON => 6, Item::RAW_FISH => 2, Item::RAW_SALMON => 2, Item::CLOWN_FISH => 1, Item::PUFFER_FISH => 1];
                     $slot = $this->inventory->getItemInHand();
                     if ($this->getHealth() < $this->getMaxHealth() and isset($items[$slot->getId()])) {
                         $this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
                         if ($ev->isCancelled()) {
                             $this->inventory->sendContents($this);
                             break;
                         }
                         $pk = new EntityEventPacket();
                         $pk->eid = $this->getId();
                         $pk->event = EntityEventPacket::USE_ITEM;
                         $this->dataPacket($pk);
                         Server::broadcastPacket($this->getViewers(), $pk);
                         $amount = $items[$slot->getId()];
                         $ev = new EntityRegainHealthEvent($this, $amount, EntityRegainHealthEvent::CAUSE_EATING);
                         $this->heal($ev->getAmount(), $ev);
                         --$slot->count;
                         $this->inventory->setItemInHand($slot);
                         if ($slot->getId() === Item::MUSHROOM_STEW or $slot->getId() === Item::BEETROOT_SOUP) {
                             $this->inventory->addItem(Item::get(Item::BOWL, 0, 1));
                         } elseif ($slot->getId() === Item::PUFFER_FISH) {
                             //Pufferfish
                             //$this->addEffect(Effect::getEffect(Effect::HUNGER)->setAmplifier(2)->setDuration(15 * 20));
                             $this->addEffect(Effect::getEffect(Effect::NAUSEA)->setAmplifier(1)->setDuration(15 * 20));
                             $this->addEffect(Effect::getEffect(Effect::POISON)->setAmplifier(3)->setDuration(60 * 20));
                         }
                     }
                     break;
             }
             break;
         case ProtocolInfo::DROP_ITEM_PACKET:
             if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                 break;
             }
             $item = $this->inventory->getItemInHand();
             $ev = new PlayerDropItemEvent($this, $item);
             $this->server->getPluginManager()->callEvent($ev);
             if ($ev->isCancelled()) {
                 $this->inventory->sendContents($this);
                 break;
             }
             $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
             $motion = $this->getDirectionVector()->multiply(0.4);
             $this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
             $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
             break;
         case ProtocolInfo::TEXT_PACKET:
             if ($this->spawned === false or !$this->isAlive()) {
                 break;
             }
             $this->craftingType = 0;
             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 = 0;
             $this->currentTransaction = null;
             if (isset($this->windowIndex[$packet->windowid])) {
                 $this->server->getPluginManager()->callEvent(new InventoryCloseEvent($this->windowIndex[$packet->windowid], $this));
                 $this->removeWindow($this->windowIndex[$packet->windowid]);
             } else {
                 unset($this->windowIndex[$packet->windowid]);
             }
             break;
         case ProtocolInfo::CRAFTING_EVENT_PACKET:
             if ($this->spawned === false or !$this->isAlive()) {
                 break;
             } 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 ($recipe === null or ($recipe instanceof BigShapelessRecipe or $recipe instanceof BigShapedRecipe) and $this->craftingType === 0) {
                 $this->inventory->sendContents($this);
                 break;
             }
             foreach ($packet->input as $i => $item) {
                 if ($item->getDamage() === -1 or $item->getDamage() === 0xffff) {
                     $item->setDamage(null);
                 }
                 if ($i < 9 and $item->getId() > 0) {
                     $item->setCount(1);
                 }
             }
             $canCraft = true;
             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) {
                             if ($ingredient === null or !$ingredient->deepEquals($item, $ingredient->getDamage() !== null, $ingredient->getCompoundTag() !== null)) {
                                 $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;
             }
             /** @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, $i->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) {
                 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;
                 }
                 if ($this->isCreative()) {
                     if (Item::getCreativeItemIndex($packet->item) !== -1) {
                         $this->inventory->setItem($packet->slot, $packet->item);
                         $this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot);
                         //links $hotbar[$packet->slot] to $slots[$packet->slot]
                     }
                 }
                 $transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($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(), $this->inventory->getArmorItem($packet->slot), $packet->item);
             } elseif (isset($this->windowIndex[$packet->windowid])) {
                 $this->craftingType = 0;
                 $inv = $this->windowIndex[$packet->windowid];
                 $transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item);
             } else {
                 break;
             }
             if ($transaction->getSourceItem()->deepEquals($transaction->getTargetItem()) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()) {
                 //No changes!
                 //No changes, just a local inventory update sent by the server
                 break;
             }
             if ($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < microtime(true) - 8) {
                 if ($this->currentTransaction !== null) {
                     foreach ($this->currentTransaction->getInventories() as $inventory) {
                         if ($inventory instanceof PlayerInventory) {
                             $inventory->sendArmorContents($this);
                         }
                         $inventory->sendContents($this);
                     }
                 }
                 $this->currentTransaction = new SimpleTransactionGroup($this);
             }
             $this->currentTransaction->addTransaction($transaction);
             if ($this->currentTransaction->canExecute()) {
                 $achievements = [];
                 foreach ($this->currentTransaction->getTransactions() as $ts) {
                     $inv = $ts->getInventory();
                     if ($inv instanceof FurnaceInventory) {
                         if ($ts->getSlot() === 2) {
                             switch ($inv->getResult()->getId()) {
                                 case Item::IRON_INGOT:
                                     $achievements[] = "acquireIron";
                                     break;
                             }
                         }
                     }
                 }
                 if ($this->currentTransaction->execute()) {
                     foreach ($achievements as $a) {
                         $this->awardAchievement($a);
                     }
                 }
                 $this->currentTransaction = null;
             }
             break;
         case ProtocolInfo::BLOCK_ENTITY_DATA_PACKET:
             if ($this->spawned === false or $this->blocked === true or !$this->isAlive()) {
                 break;
             }
             $this->craftingType = 0;
             $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();
                     } else {
                         foreach ($ev->getLines() as $line) {
                             if (mb_strlen($line, "UTF-8") > 16) {
                                 $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();
 }