Наследование: extends Projectile
Пример #1
0
 public function onUpdate($currentTick)
 {
     parent::onUpdate($currentTick);
     $this->getLevel()->addParticle(new DustParticle($this->getPosition(), $this->namedtag["r"], $this->namedtag["g"], $this->namedtag["b"]));
     /*if($this->onGround){
     			$this->kill();
     		}*/
 }
Пример #2
0
 public function onDataPacketReceive(DataPacketReceiveEvent $event)
 {
     $pk = $event->getPacket();
     if ($pk->pid() !== ProtocolInfo::USE_ITEM_PACKET || $pk->face !== 0xff) {
         return false;
     }
     $p = $event->getPlayer();
     $inv = $p->getInventory();
     $i = $inv->getItemInHand();
     if ($i->getID() == 262) {
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $p->x), new Double("", $p->y + $p->getEyeHeight()), new Double("", $p->z)]), "Motion" => new Enum("Motion", [new Double("", -sin($p->getyaw() / 180 * M_PI) * cos($p->getPitch() / 180 * M_PI)), new Double("", -sin($p->getPitch() / 180 * M_PI)), new Double("", cos($p->getyaw() / 180 * M_PI) * cos($p->getPitch() / 180 * M_PI))]), "Rotation" => new Enum("Rotation", [new Float("", $p->getyaw()), new Float("", $p->getPitch())])]);
         $arrow = new Arrow($p->chunk, $nbt, $p);
         $ev = new EntityShootBowEvent($p, Item::get(264, 0, 0), $arrow, 1.5);
         $this->getServer(0)->getPluginManager()->callEvent($ev);
         if ($ev->isCancelled()) {
             $arrow->kill();
         } else {
             $i->setCount($i->getCount() - 1);
             $inv->setItem($inv->getHeldItemSlot(), $i);
             $arrow->spawnToAll();
         }
     }
 }
Пример #3
0
 public function onUpdate($currentTick)
 {
     if ($this->closed) {
         return \false;
     }
     $this->timings->startTiming();
     $hasUpdate = parent::onUpdate($currentTick);
     if (!$this->hadCollision and $this->isCritical) {
         $this->level->addParticle(new CriticalParticle($this->add($this->width / 2 + \mt_rand(-100, 100) / 500, $this->height / 2 + \mt_rand(-100, 100) / 500, $this->width / 2 + \mt_rand(-100, 100) / 500)));
     } elseif ($this->onGround) {
         $this->isCritical = \false;
     }
     if ($this->age > 1200) {
         $this->kill();
         $hasUpdate = \true;
     }
     $this->timings->stopTiming();
     $this->Light($this->width, $this->height, $this->length);
     return $hasUpdate;
 }
Пример #4
0
 public function MobRandomWalk()
 {
     $ann = $this->animals;
     $filter_res = array_filter($ann);
     if (!empty($filter_res)) {
         foreach ($this->animals as $animal) {
             if (in_array($animal['type'], $this->nighttype)) {
                 $level = $this->getServer()->getLevelByName($animal['level']);
                 $zo = $level->getEntity($animal['ID']);
                 if ($zo != "") {
                     $zom =& $this->animals[$zo->getId()];
                     if ($zom['IsStop'] != "1") {
                         $zom['yup'] = $zom['yup'] - 1;
                         $h_r = $this->hatred_r;
                         //仇恨半径
                         $pos = new Vector3($zo->getX(), $zo->getY(), $zo->getZ());
                         $hatred = false;
                         foreach ($zo->getViewers() as $p) {
                             //获取附近玩家
                             if ($p->distance($pos) <= $h_r) {
                                 //玩家在仇恨半径内
                                 if ($hatred === false) {
                                     $hatred = $p;
                                 } elseif ($hatred instanceof Player) {
                                     if ($p->distance($pos) <= $hatred->distance($pos)) {
                                         //比上一个更近
                                         $hatred = $p;
                                     }
                                 }
                             }
                         }
                         //echo ($zom['IsChasing']."\n");
                         if ($hatred == false or $this->dif == 0) {
                             $zom['IsChasing'] = false;
                         } else {
                             $zom['IsChasing'] = $hatred->getName();
                         }
                         //echo ($zom['IsChasing']."\n");
                         if ($zom['IsChasing'] !== false) {
                             //echo ("是属于仇恨模式\n");
                             $p = $this->getServer()->getPlayer($zom['IsChasing']);
                             if ($p instanceof Player === false) {
                                 $zom['IsChasing'] = false;
                                 //取消仇恨模式
                             } else {
                                 /*
                                 $xxx = 0.07;
                                 $zzz = 0.07;
                                 $posz1 = new Vector3 ($zo->getX() + $xxx, $zo->getY(), $zo->getZ());
                                     if($p->distance($pos) > $p->distance($posz1)){
                                     $xxx = 0.07;
                                     }
                                     if($p->distance($pos) == $p->distance($posz1)){
                                     $xxx = 0;
                                     }
                                     if($p->distance($pos) < $p->distance($posz1)){
                                     $xxx = -0.07;
                                     }
                                 $posz2 = new Vector3 ($zo->getX()+ $xxx, $zo->getY(), $zo->getZ() + $zzz);
                                     if($p->distance($pos) < $p->distance($posz2)){
                                     $zzz = -0.07;
                                     }
                                     if($p->distance($pos) == $p->distance($posz2)){
                                     $zzz = 0;
                                     }
                                     if($p->distance($pos) > $p->distance($posz2)){
                                     $zzz = 0.07;
                                     }
                                 */
                                 //还不如用旧算法了。。
                                 /*
                                 $zx =floor($zo->getX());
                                 $zZ = floor($zo->getZ());
                                 $xxx = 0.07;
                                 $zzz = 0.07;
                                 */
                                 $x1 = $zo->getX() - $p->getX();
                                 //$jumpy = $zo->getY() - 1;
                                 if ($x1 >= -0.5 and $x1 <= 0.5) {
                                     //直行
                                     //$zx = $zo->getX();
                                     $xxx = 0;
                                 } elseif ($x1 < 0) {
                                     //$zx = $zo->getX() +0.07;
                                     $xxx = 0.07000000000000001;
                                 } else {
                                     //$zx = $zo->getX() -0.07;
                                     $xxx = -0.07000000000000001;
                                 }
                                 $z1 = $zo->getZ() - $p->getZ();
                                 if ($z1 >= -0.5 and $z1 <= 0.5) {
                                     //直行
                                     //$zZ = $zo->getZ();
                                     $zzz = 0;
                                 } elseif ($z1 < 0) {
                                     //$zZ = $zo->getZ() +0.07;
                                     $zzz = 0.07000000000000001;
                                 } else {
                                     //$zZ = $zo->getZ() -0.07;
                                     $zzz = -0.07000000000000001;
                                 }
                                 if ($xxx == 0 and $zzz == 0) {
                                     $xxx = 0.1;
                                 }
                                 $zom['xxx'] = $xxx * 10;
                                 $zom['zzz'] = $zzz * 10;
                                 //计算y轴
                                 //$width = $this->width;
                                 $pos0 = new Vector3($zo->getX(), $zo->getY() + 1, $zo->getZ());
                                 //原坐标
                                 $pos = new Vector3($zo->getX() + $xxx, $zo->getY() + 1, $zo->getZ() + $zzz);
                                 //目标坐标
                                 $zy = $this->ifjump($zo->getLevel(), $pos, true);
                                 if ($zy === false) {
                                     //前方不可前进
                                     //伪自由落体
                                     if ($this->ifjump($zo->getLevel(), $pos0, true) === false) {
                                         //原坐标依然是悬空
                                         $pos2 = new Vector3($zo->getX(), $zo->getY() - 2, $zo->getZ());
                                         //下降
                                         $zom['up'] = 1;
                                         $zom['yup'] = 0;
                                         //var_dump("2");
                                     } else {
                                         if ($this->whatBlock($level, $pos0) == "climb") {
                                             //梯子
                                             $zy = $pos0->y + 0.07000000000000001;
                                             $pos2 = new Vector3($zo->getX(), $zy - 1, $zo->getZ());
                                             //目标坐标
                                         } elseif ($xxx != 0 and $zzz != 0) {
                                             //走向最近距离
                                             if ($this->ifjump($zo->getLevel(), new Vector3($zo->getX() + $xxx, $zo->getY() + 1, $zo->getZ()), true) !== false) {
                                                 $pos2 = new Vector3($zo->getX() + $xxx, floor($zo->getY()), $zo->getZ());
                                                 //目标坐标
                                             } elseif ($this->ifjump($zo->getLevel(), new Vector3($zo->getX(), $zo->getY() + 1, $zo->getZ() + $zzz), true) !== false) {
                                                 $pos2 = new Vector3($zo->getX(), floor($zo->getY()), $zo->getZ() + $zzz);
                                                 //目标坐标
                                             } else {
                                                 $pos2 = new Vector3($zo->getX() - $xxx, floor($zo->getY()), $zo->getZ() - $zzz);
                                                 //目标坐标
                                                 //转向180度,向身后走
                                                 $zom['up'] = 0;
                                             }
                                         } else {
                                             $pos2 = new Vector3($zo->getX() - $xxx, floor($zo->getY()), $zo->getZ() - $zzz);
                                             //目标坐标
                                             //转向180度,向身后走
                                             $zom['up'] = 0;
                                         }
                                     }
                                 } else {
                                     $pos2 = new Vector3($zo->getX() + $xxx, $zy - 1, $zo->getZ() + $zzz);
                                     //目标坐标
                                     //echo $zy;
                                     $zom['up'] = 0;
                                     if ($this->whatBlock($level, $pos2) == "water") {
                                         $zom['swim'] += 1;
                                         if ($zom['swim'] >= 20) {
                                             $zom['swim'] = 0;
                                         }
                                     } else {
                                         $zom['swim'] = 0;
                                     }
                                     //var_dump("目标:".($zy - 1) );
                                     //var_dump("原先:".$zo->getY());
                                     if (abs($zy - 1 - floor($zo->getY())) == 1) {
                                         //var_dump("跳");
                                         $zom['jump'] = 0.5;
                                     } else {
                                         if ($zom['jump'] > 0.01) {
                                             $zom['jump'] -= 0.1;
                                         } else {
                                             $zom['jump'] = 0.01;
                                         }
                                     }
                                 }
                                 $zo->setPosition($pos2);
                                 $v3 = new Vector3($zo->getX(), $zo->getY() + 2, $zo->getZ());
                                 $yaw = $this->getyaw($xxx, $zzz);
                                 $pos3 = $pos2;
                                 $pos3->y = $pos3->y + 2.62;
                                 $ppos = $p->getLocation();
                                 $ppos->y = $ppos->y + $p->getEyeHeight();
                                 $pitch = $this->getpitch($pos3, $ppos);
                                 $zom['x'] = $zo->getX();
                                 $zom['y'] = $zo->getY();
                                 $zom['z'] = $zo->getZ();
                                 $zom['yaw'] = $yaw;
                                 $zom['pitch'] = $pitch;
                                 $pk3 = new SetEntityMotionPacket();
                                 $pk3->entities = [[$zo->getID(), $xxx, -$zom['swim'] / 100 + $zom['jump'], $zzz]];
                                 foreach ($zo->getViewers() as $pl) {
                                     $pl->dataPacket($pk3);
                                 }
                                 if ($zom['type'] == "34") {
                                     //$zom['type'] = "skeleton";
                                     if ($zom['hurt'] >= 10) {
                                         $zom['hurt'] = $zom['hurt'] - 1;
                                     } else {
                                         $chunk = $level->getChunk($v3->x >> 4, $v3->z >> 4, true);
                                         $nbt = $this->getNBT($v3);
                                         $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, $p), $f);
                                         //var_dump("shoot|".-$zom['pitch']."|".$zom['yaw']);
                                         //var_dump(233333);
                                         $arrow = new Arrow($chunk, $nbt2);
                                         $arrow->setPosition($v3);
                                         $arrow->spawnToAll();
                                         //$p = $this->getServer()->getPlayer($zom['IsChasing']);
                                         //$d = $p->distance($v3);
                                         //$d = $d/1.2;
                                         //var_dump($d);
                                         if (!isset($this->arrow[$arrow->getId()])) {
                                             $this->addarrow($arrow->getId(), $zom['yaw'], $arrow->getLevel()->getName(), $arrow->getX(), $arrow->getY(), $arrow->getZ(), $p->getX(), $p->getY(), $p->getZ());
                                         }
                                         $zom['hurt'] = 20;
                                     }
                                 }
                                 if (0 <= $p->distance($pos) and $p->distance($pos) <= 1.5) {
                                     if ($zom['type'] == "33") {
                                         //$zom['type'] = "FiringCreeper";
                                         $zom['IsStop'] = 1;
                                         $zom['time'] = 30;
                                     }
                                     if ($zom['type'] == "32") {
                                         //$zom['type'] = "Zombie";
                                         if ($zom['hurt'] >= 0) {
                                             $zom['hurt'] = $zom['hurt'] - 1;
                                         } else {
                                             $p->knockBack($zo, 0, $xxx, $zzz, 0.4);
                                             if ($p->isSurvival()) {
                                                 $p->sethealth($p->gethealth() - $this->dif * 2);
                                             }
                                             $zom['hurt'] = 10;
                                         }
                                     }
                                 }
                             }
                         } else {
                             if ($zom['IsChasing'] === false) {
                                 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);
                                     }
                                 }
                             }
                         }
                     } else {
                         $zom['time'] = $zom['time'] - 1;
                         if ($zom['time'] <= 0) {
                             //$zo->sethealth(0);
                             unset($this->animals[$zo->getId()]);
                             $level->removeEntity($level->getEntity($zo->getId()));
                             $e = new Explosion(new Position($zo->getX(), $zo->getY(), $zo->getZ(), $level), $this->bomb);
                             $e->explode();
                             //$pos = new Vector3($zo->getX(), $zo->getY(), $zo->getZ());
                         }
                     }
                 } else {
                     unset($this->animals[$animal['ID']]);
                 }
             }
         }
     }
     unset($zo);
 }
Пример #5
0
 public function removeArrow(Arrow $arrow)
 {
     $arrow->kill();
     $arrow->close();
 }
Пример #6
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 (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->getLevel()->getName();
                 $nbt["Pos"][0] = $this->getLevel()->getSpawn()->x;
                 $nbt["Pos"][1] = $this->getLevel()->getSpawn()->y;
                 $nbt["Pos"][2] = $this->getLevel()->getSpawn()->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->getLevel()->getChunkAt($nbt["Pos"][0], $nbt["Pos"][2], 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 (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->getLevel()->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->getLevel()->getTime();
             $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;
             }
             $this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->getLevel()->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
             $this->orderChunks();
             $this->tasks[] = $this->server->getScheduler()->scheduleDelayedRepeatingTask(new CallbackTask([$this, "orderChunks"]), 10, 40);
             $this->sendNextChunk();
             $this->tasks[] = $this->chunkLoadTask = $this->server->getScheduler()->scheduleRepeatingTask(new CallbackTask([$this, "sendNextChunk"]), 1);
             break;
         case ProtocolInfo::ROTATE_HEAD_PACKET:
             if ($this->spawned === false) {
                 break;
             }
             $this->setRotation($packet->yaw, $this->pitch);
             break;
         case ProtocolInfo::MOVE_PLAYER_PACKET:
             if ($this->spawned === false) {
                 break;
             }
             $newPos = new Vector3($packet->x, $packet->y, $packet->z);
             $oldPos = new Vector3($this->x, $this->y, $this->z);
             $revert = false;
             if ($this->forceMovement instanceof Vector3 and $newPos->distance($this->forceMovement) > 0.1) {
                 $revert = true;
             } elseif ($newPos->distance($this) > 100) {
                 $this->server->getLogger()->warning($this->getName() . " moved too quickly!");
                 $revert = true;
             } else {
                 if ($this->chunk === null or !$this->chunk->isGenerated()) {
                     $chunk = $this->getLevel()->getChunkAt($newPos->x >> 4, $newPos->z >> 4);
                     if (!$chunk instanceof FullChunk or !$chunk->isGenerated()) {
                         $revert = true;
                     }
                 }
             }
             if (!$revert) {
                 $dx = $newPos->x - $this->x;
                 $dy = $newPos->y - $this->y;
                 $dz = $newPos->z - $this->z;
                 $packet->yaw %= 360;
                 $packet->pitch %= 360;
                 if ($packet->yaw < 0) {
                     $packet->yaw += 360;
                 }
                 if ($packet->pitch < 0) {
                     $packet->pitch += 360;
                 }
                 $this->setRotation($packet->yaw, $packet->pitch);
                 //$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
                 $revert = !$this->move($dx, $dy, $dz);
                 $diffX = $this->x - $newPos->x;
                 $diffZ = $this->z - $newPos->z;
                 $diffY = $this->y - $newPos->y;
                 if ($diffY > -0.5 or $diffY < 0.5) {
                     $diffY = 0;
                 }
                 $diff = $diffX ** 2 + $diffY ** 2 + $diffZ ** 2;
                 if (!$revert and $diff > 0.0625 and !$this->isSleeping() and $this->isSurvival()) {
                     $revert = true;
                     $this->server->getLogger()->warning($this->getName() . " moved wrongly!");
                 }
             }
             if ($revert) {
                 $pk = new MovePlayerPacket();
                 $pk->eid = 0;
                 $pk->x = $this->x;
                 $pk->y = $this->y + $this->getEyeHeight();
                 $pk->z = $this->z;
                 $pk->bodyYaw = $this->yaw;
                 $pk->pitch = $this->pitch;
                 $pk->yaw = $this->yaw;
                 $pk->teleport = true;
                 $this->directDataPacket($pk);
                 $this->forceMovement = new Vector3($this->x, $this->y, $this->z);
             } else {
                 $this->forceMovement = null;
             }
             break;
         case ProtocolInfo::PLAYER_EQUIPMENT_PACKET:
             if ($this->spawned === false) {
                 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:
             $blockVector = new Vector3($packet->x, $packet->y, $packet->z);
             $this->craftingType = 0;
             if (($this->spawned === false or $this->blocked === true or $this->dead === true) and $packet->face >= 0 and $packet->face <= 5) {
                 $target = $this->getLevel()->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;
             }
             $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->getLevel()->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 = clone $this->inventory->getItemInHand();
                     //TODO: Implement adventure mode checks
                     if ($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true) {
                         $this->inventory->setItemInHand($item);
                         $this->inventory->sendHeldItem($this->hasSpawned);
                         break;
                     }
                 }
                 $target = $this->getLevel()->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) {
                 //TODO: add event
                 $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->entity->inAction === true){
                     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;
                             }
                         }
                         $f = 1.5;
                         $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) * $f), new Double("", -sin($this->pitch / 180 * M_PI) * $f), new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI) * $f)]), "Rotation" => new Enum("Rotation", [new Float("", $this->yaw), new Float("", $this->pitch)])]);
                         $arrow = new Arrow($this->chunk, $nbt, $this);
                         $ev = new EntityShootBowEvent($this, $bow, $arrow, $f);
                         $this->server->getPluginManager()->callEvent($ev);
                         if ($ev->isCancelled()) {
                             $arrow->kill();
                         } else {
                             if ($this->isSurvival()) {
                                 $this->inventory->removeItem(Item::get(Item::ARROW, 0, 1));
                                 $bow->setDamage($bow->getDamage() + 1);
                                 $this->inventory->setItemInHand($bow);
                                 if ($bow->getDamage() >= 385) {
                                     $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0));
                                 }
                             }
                             $arrow->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 = clone $this->inventory->getItemInHand();
             }
             if ($this->getLevel()->useBreakOn($vector, $item, $this) === true) {
                 if ($this->isSurvival()) {
                     $this->inventory->setItemInHand($item);
                     $this->inventory->sendHeldItem($this->hasSpawned);
                 }
                 break;
             }
             $this->inventory->sendContents($this);
             $target = $this->getLevel()->getBlock($vector);
             $tile = $this->getLevel()->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:
             if ($this->spawned === false or $this->blocked === true or $this->dead === true) {
                 break;
             }
             for ($i = 0; $i < 4; ++$i) {
                 $s = $packet->slots[$i];
                 if ($s === 0 or $s === 255) {
                     $s = Item::get(Item::AIR, 0, 1);
                 } else {
                     $s = Item::get($s + 256, 0, 1);
                 }
                 $slot = $this->inventory->getArmorItem($i);
                 if ($slot->getID() !== Item::AIR and $s->getID() === Item::AIR) {
                     $this->inventory->setArmorItem($i, Item::get(Item::AIR, 0, 1));
                 } elseif ($s->getID() !== Item::AIR and $slot->getID() === Item::AIR and ($sl = $this->inventory->first($s)) !== -1) {
                     if ($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false) {
                         $this->inventory->sendContents($this);
                     } else {
                         $this->inventory->setItem($sl, Item::get(Item::AIR, 0, 1));
                     }
                 } elseif ($s->getID() !== Item::AIR and $slot->getID() !== Item::AIR and ($slot->getID() !== $s->getID() or $slot->getDamage() !== $s->getDamage()) and ($sl = $this->inventory->first($s)) !== -1) {
                     if ($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false) {
                         $this->inventory->sendContents($this);
                     } else {
                         $this->inventory->setItem($sl, $slot);
                     }
                 }
             }
             if ($this->inAction === true) {
                 $this->inAction = false;
                 $this->sendMetadata($this->getViewers());
             }
             break;
         case ProtocolInfo::INTERACT_PACKET:
             if ($this->spawned === false) {
                 break;
             }
             $this->craftingType = 0;
             $target = $this->getLevel()->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->blocked === false 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] = -intval($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
                 }
                 $ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
                 if ($cancelled) {
                     $ev->setCancelled();
                 }
                 $this->server->getPluginManager()->callEvent($ev);
                 if ($ev->isCancelled()) {
                     if ($item->isTool() and $this->isSurvival()) {
                         $this->inventory->sendContents($this);
                     }
                     break;
                 }
                 $target->attack($ev->getFinalDamage(), $ev);
                 if ($item->isTool() and $this->isSurvival()) {
                     if ($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()) {
                         $this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
                     }
                 }
             }
             break;
         case ProtocolInfo::ANIMATE_PACKET:
             if ($this->spawned === false) {
                 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->setHealth(20);
             $this->dead = false;
             $this->sendMetadata($this->getViewers());
             $this->sendSettings();
             $this->inventory->sendContents($this);
             $this->inventory->sendArmorContents($this);
             $this->spawnToAll();
             $this->blocked = false;
             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);
                         $this->heal($items[$slot->getID()]);
                         --$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));
                         }
                     }
                     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));
             $motion = $this->getDirectionVector()->multiply(0.4);
             $this->getLevel()->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) {
                 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]
                     }
                 } else {
                 }
                 $transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($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.4) {
                 if ($this->currentTransaction instanceof SimpleTransactionGroup) {
                     foreach ($this->currentTransaction->getInventories() as $inventory) {
                         $inventory->sendContents($inventory->getViewers());
                     }
                 }
                 $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 remainings
                                 $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;
                         }
                     }
                     $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->getLevel()->getTile($v = 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($this->getLevel()->getBlock($v), $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;
     }
 }