示例#1
0
 public function onUpdate($currentTick)
 {
     if ($this->closed !== false) {
         return false;
     }
     if (++$this->switchDirectionTicker === 100) {
         $this->switchDirectionTicker = 0;
         if (mt_rand(0, 100) < 50) {
             $this->swimDirection = null;
         }
     }
     $this->lastUpdate = $currentTick;
     $this->timings->startTiming();
     $hasUpdate = parent::onUpdate($currentTick);
     if ($this->isAlive()) {
         if ($this->y > 62 and $this->swimDirection !== null) {
             $this->swimDirection->y = -0.5;
         }
         $inWater = $this->isInsideOfWater();
         if (!$inWater) {
             $this->motionY -= $this->gravity;
             $this->swimDirection = null;
         } elseif ($this->swimDirection !== null) {
             if ($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2 <= $this->swimDirection->lengthSquared()) {
                 $this->motionX = $this->swimDirection->x * $this->swimSpeed;
                 $this->motionY = $this->swimDirection->y * $this->swimSpeed;
                 $this->motionZ = $this->swimDirection->z * $this->swimSpeed;
             }
         } else {
             $this->swimDirection = $this->generateRandomDirection();
             $this->swimSpeed = mt_rand(50, 100) / 2000;
         }
         $expectedPos = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
         $this->move($this->motionX, $this->motionY, $this->motionZ);
         if ($expectedPos->distanceSquared($this) > 0) {
             $this->swimDirection = $this->generateRandomDirection();
             $this->swimSpeed = mt_rand(50, 100) / 2000;
         }
         $friction = 1 - $this->drag;
         $this->motionX *= $friction;
         $this->motionY *= 1 - $this->drag;
         $this->motionZ *= $friction;
         $f = sqrt($this->motionX ** 2 + $this->motionZ ** 2);
         $this->yaw = -atan2($this->motionX, $this->motionZ) * 180 / M_PI;
         $this->pitch = -atan2($f, $this->motionY) * 180 / M_PI;
         if ($this->onGround) {
             $this->motionY *= -0.5;
         }
     }
     $this->timings->stopTiming();
     return $hasUpdate or !$this->onGround or abs($this->motionX) > 1.0E-5 or abs($this->motionY) > 1.0E-5 or abs($this->motionZ) > 1.0E-5;
 }
示例#2
0
 private function getOptimalFlowDirections()
 {
     if ($this->temporalVector === null) {
         $this->temporalVector = new Vector3(0, 0, 0);
     }
     for ($j = 0; $j < 4; ++$j) {
         $this->flowCost[$j] = 1000;
         $x = $this->x;
         $y = $this->y;
         $z = $this->z;
         if ($j === 0) {
             --$x;
         } elseif ($j === 1) {
             ++$x;
         } elseif ($j === 2) {
             --$z;
         } elseif ($j === 3) {
             ++$z;
         }
         $block = $this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $z));
         if (!$block->canBeFlowedInto() and !$block instanceof Liquid) {
             continue;
         } elseif ($block instanceof Liquid and $block->getDamage() === 0) {
             continue;
         } elseif ($this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y - 1, $z))->canBeFlowedInto()) {
             $this->flowCost[$j] = 0;
         } else {
             $this->flowCost[$j] = $this->calculateFlowCost($block, 1, $j);
         }
     }
     $minCost = $this->flowCost[0];
     for ($i = 1; $i < 4; ++$i) {
         if ($this->flowCost[$i] < $minCost) {
             $minCost = $this->flowCost[$i];
         }
     }
     for ($i = 0; $i < 4; ++$i) {
         $this->isOptimalFlowDirection[$i] = $this->flowCost[$i] === $minCost;
     }
     return $this->isOptimalFlowDirection;
 }
示例#3
0
 public function spawnExperienceOrb(Vector3 $pos, $exp = 0)
 {
     if ($exp > 50) {
         $exp = 50;
     }
     $ExpPerBall = mt_rand(5, 10);
     while ($exp >= $ExpPerBall) {
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $pos->getX() + mt_rand(-1, 1) + mt_rand(100, 999) / 1000), new Double("", $pos->getY()), new Double("", $pos->getZ() + mt_rand(-1, 1) + mt_rand(100, 999) / 1000)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "Experience" => new Long("Experience", $exp)]);
         $chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, false);
         $expOrb = new ExperienceOrb($chunk, $nbt);
         $expOrb->spawnToAll();
         $exp -= $ExpPerBall;
         $ExpPerBall = mt_rand(5, 10);
     }
     if ($exp > 0) {
         $nbt = new Compound("", ["Pos" => new Enum("Pos", [new Double("", $pos->getX() + mt_rand(-1, 1) + mt_rand(100, 999) / 1000), new Double("", $pos->getY()), new Double("", $pos->getZ() + mt_rand(-1, 1) + mt_rand(100, 999) / 1000)]), "Motion" => new Enum("Motion", [new Double("", 0), new Double("", 0), new Double("", 0)]), "Rotation" => new Enum("Rotation", [new Float("", 0), new Float("", 0)]), "Experience" => new Long("Experience", $exp)]);
         $chunk = $this->getChunk($pos->x >> 4, $pos->z >> 4, false);
         $expOrb = new ExperienceOrb($chunk, $nbt);
         $expOrb->spawnToAll();
     }
 }
示例#4
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::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::PLAYER_INPUT_PACKET:
             break;
         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 * 64 * 4 and strlen($packet->skin) != 64 * 32 * 4) {
                 $this->close("", "disconnectionScreen.invalidSkin");
                 break;
                 //$this->setSkin("", "Standard_Steve");
             }
             $this->setSkin($packet->skin, $packet->skinName);
             $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:
             /** EntityLink **/
             if ($this->getlinkType() === Entity::LINK_MASTER) {
                 $this->getlinkedTarget()->followEntity($this);
             }
             $newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
             $revert = false;
             if (!$this->isAlive() or $this->spawned !== true) {
                 $revert = true;
                 $this->forceMovement = new Vector3($this->x, $this->y, $this->z);
             }
             if ($this->teleportPosition !== null or $this->forceMovement instanceof Vector3 and (($dist = $newPos->distanceSquared($this->forceMovement)) > 0.1 or $revert)) {
                 if ($this->forceMovement instanceof Vector3) {
                     $this->sendPosition($this->forceMovement, $packet->yaw, $packet->pitch);
                 }
             } else {
                 $packet->yaw %= 360;
                 $packet->pitch %= 360;
                 if ($packet->yaw < 0) {
                     $packet->yaw += 360;
                 }
                 $this->setRotation($packet->yaw, $packet->pitch);
                 $this->newPosition = $newPos;
                 $this->forceMovement = null;
             }
             break;
         case ProtocolInfo::MOB_EQUIPMENT_PACKET:
             if ($this->spawned === false or !$this->isAlive()) {
                 break;
             }
             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 instanceof Launchable) {
                     $item->launch($this);
                     if ($this->isSurvival()) {
                         $item->setCount($item->getCount() - 1);
                         $this->inventory->setItemInHand($item->getCount() > 0 ? $item : Item::get(Item::AIR));
                     }
                 }
                 $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();
                                 }
                             }
                         }
                     } 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->getAttribute()->resetAll();
                     $this->setHealth($this->getMaxHealth());
                     $this->setFood(20);
                     $this->setSpeed(0.1);
                     $this->starvationTick = 0;
                     $this->foodTick = 0;
                     $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->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, true)) {
                 if ($this->isSurvival()) {
                     if (!$item->equals($oldItem) or $item->getCount() !== $oldItem->getCount()) {
                         $this->inventory->setItemInHand($item);
                         $this->inventory->sendHeldItem($this);
                     }
                 }
                 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;
             }
             /**
              * EntityLink *
              */
             if ($target !== null && $target->isVehicle()) {
                 switch ($packet->action) {
                     case Player::INTERACT_PACKET_IN:
                         $this->linkEntity($target);
                         break;
                     case Player::INTERACT_PACKET_LEAVE:
                         $this->unlinkEntity($target);
                         break;
                 }
                 return;
             }
             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("BukkitPE.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
                     $this->eatFoodInHand();
                     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;
             }
             /** @var Item $item */
             foreach ($packet->input as $i => $item) {
                 if ($item->getDamage() === -1 or $item->getDamage() === 0xffff) {
                     $item->setDamage(null);
                 }
                 if ($i < 9 and $item->getId() > 0) {
                     $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) {
                                 $canCraft = false;
                                 break;
                             }
                             if ($ingredient->getId() != 0 and !$ingredient->deepEquals($item, $ingredient->getDamage() !== null, $ingredient->getCompoundTag() !== null)) {
                                 $canCraft = false;
                                 break;
                             }
                         } elseif ($ingredient !== null and $item->getId() !== 0) {
                             $canCraft = false;
                             break;
                         }
                     }
                 }
             } elseif ($recipe instanceof ShapelessRecipe) {
                 $needed = $recipe->getIngredientList();
                 for ($x = 0; $x < 3 and $canCraft; ++$x) {
                     for ($y = 0; $y < 3; ++$y) {
                         $item = clone $packet->input[$y * 3 + $x];
                         foreach ($needed as $k => $n) {
                             if ($n->deepEquals($item, $n->getDamage() !== null, $n->getCompoundTag() !== null)) {
                                 $remove = min($n->getCount(), $item->getCount());
                                 $n->setCount($n->getCount() - $remove);
                                 $item->setCount($item->getCount() - $remove);
                                 if ($n->getCount() === 0) {
                                     unset($needed[$k]);
                                 }
                             }
                         }
                         if ($item->getCount() > 0) {
                             $canCraft = false;
                             break;
                         }
                     }
                 }
                 if (count($needed) > 0) {
                     $canCraft = false;
                 }
             } else {
                 $canCraft = false;
             }
             /** @var Item[] $ingredients */
             $ingredients = $packet->input;
             $result = $packet->output[0];
             if (!$canCraft or !$recipe->getResult()->deepEquals($result)) {
                 $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": expected " . $recipe->getResult() . ", got " . $result . ", using: " . implode(", ", $ingredients));
                 $this->inventory->sendContents($this);
                 break;
             }
             $used = array_fill(0, $this->inventory->getSize(), 0);
             foreach ($ingredients as $ingredient) {
                 $slot = -1;
                 foreach ($this->inventory->getContents() as $index => $i) {
                     if ($ingredient->getId() !== 0 and $ingredient->deepEquals($i, $ingredient->getDamage() !== null) and $i->getCount() - $used[$index] >= 1) {
                         $slot = $index;
                         $used[$index]++;
                         break;
                     }
                 }
                 if ($ingredient->getId() !== 0 and $slot === -1) {
                     $canCraft = false;
                     break;
                 }
             }
             if (!$canCraft) {
                 $this->server->getLogger()->debug("Unmatched recipe " . $recipe->getId() . " from player " . $this->getName() . ": client does not have enough items, using: " . implode(", ", $ingredients));
                 $this->inventory->sendContents($this);
                 break;
             }
             $this->server->getPluginManager()->callEvent($ev = new CraftItemEvent($this, $ingredients, $recipe));
             if ($ev->isCancelled()) {
                 $this->inventory->sendContents($this);
                 break;
             }
             foreach ($used as $slot => $count) {
                 if ($count === 0) {
                     continue;
                 }
                 $item = $this->inventory->getItem($slot);
                 if ($item->getCount() > $count) {
                     $newItem = clone $item;
                     $newItem->setCount($item->getCount() - $count);
                 } else {
                     $newItem = Item::get(Item::AIR, 0, 0);
                 }
                 $this->inventory->setItem($slot, $newItem);
             }
             $extraItem = $this->inventory->addItem($recipe->getResult());
             if (count($extraItem) > 0) {
                 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->server->getProperty("experience.enable", true) and $this->server->getProperty("experience.smelt-drop", true)) {
                                 $this->addExperience($inv->getResult()->count * $inv->getResult()->getExperience());
                             }
                         }
                     }
                 }
                 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(TextFormat::clean($line), "UTF-8") > 20) {
                                 // temp fix for despawn of text
                                 $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();
 }
示例#5
0
 public function calculateIntercept(Vector3 $pos1, Vector3 $pos2)
 {
     $v1 = $pos1->getIntermediateWithXValue($pos2, $this->minX);
     $v2 = $pos1->getIntermediateWithXValue($pos2, $this->maxX);
     $v3 = $pos1->getIntermediateWithYValue($pos2, $this->minY);
     $v4 = $pos1->getIntermediateWithYValue($pos2, $this->maxY);
     $v5 = $pos1->getIntermediateWithZValue($pos2, $this->minZ);
     $v6 = $pos1->getIntermediateWithZValue($pos2, $this->maxZ);
     if ($v1 !== null and !$this->isVectorInYZ($v1)) {
         $v1 = null;
     }
     if ($v2 !== null and !$this->isVectorInYZ($v2)) {
         $v2 = null;
     }
     if ($v3 !== null and !$this->isVectorInXZ($v3)) {
         $v3 = null;
     }
     if ($v4 !== null and !$this->isVectorInXZ($v4)) {
         $v4 = null;
     }
     if ($v5 !== null and !$this->isVectorInXY($v5)) {
         $v5 = null;
     }
     if ($v6 !== null and !$this->isVectorInXY($v6)) {
         $v6 = null;
     }
     $vector = null;
     if ($v1 !== null and ($vector === null or $pos1->distanceSquared($v1) < $pos1->distanceSquared($vector))) {
         $vector = $v1;
     }
     if ($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))) {
         $vector = $v2;
     }
     if ($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))) {
         $vector = $v3;
     }
     if ($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))) {
         $vector = $v4;
     }
     if ($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))) {
         $vector = $v5;
     }
     if ($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))) {
         $vector = $v6;
     }
     if ($vector === null) {
         return null;
     }
     $f = -1;
     if ($vector === $v1) {
         $f = 4;
     } elseif ($vector === $v2) {
         $f = 5;
     } elseif ($vector === $v3) {
         $f = 0;
     } elseif ($vector === $v4) {
         $f = 1;
     } elseif ($vector === $v5) {
         $f = 2;
     } elseif ($vector === $v6) {
         $f = 3;
     }
     return MovingObjectPosition::fromBlock(0, 0, 0, $f, $vector);
 }
示例#6
0
 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 = Level::blockHash($sideBlock->x, $sideBlock->y, $sideBlock->z)]) 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;
 }
示例#7
0
 public function __construct(Level $level, Vector3 $start, Vector3 $direction, $yOffset = 0, $maxDistance = 0)
 {
     $this->level = $level;
     $this->maxDistance = (int) $maxDistance;
     $this->blockQueue = new \SplFixedArray(3);
     $startClone = new Vector3($start->x, $start->y, $start->z);
     $startClone->y += $yOffset;
     $this->currentDistance = 0;
     $mainDirection = 0;
     $secondDirection = 0;
     $thirdDirection = 0;
     $mainPosition = 0;
     $secondPosition = 0;
     $thirdPosition = 0;
     $pos = new Vector3($startClone->x, $startClone->y, $startClone->z);
     $startBlock = $this->level->getBlock(new Vector3(floor($pos->x), floor($pos->y), floor($pos->z)));
     if ($this->getXLength($direction) > $mainDirection) {
         $this->mainFace = $this->getXFace($direction);
         $mainDirection = $this->getXLength($direction);
         $mainPosition = $this->getXPosition($direction, $startClone, $startBlock);
         $this->secondFace = $this->getYFace($direction);
         $secondDirection = $this->getYLength($direction);
         $secondPosition = $this->getYPosition($direction, $startClone, $startBlock);
         $this->thirdFace = $this->getZFace($direction);
         $thirdDirection = $this->getZLength($direction);
         $thirdPosition = $this->getZPosition($direction, $startClone, $startBlock);
     }
     if ($this->getYLength($direction) > $mainDirection) {
         $this->mainFace = $this->getYFace($direction);
         $mainDirection = $this->getYLength($direction);
         $mainPosition = $this->getYPosition($direction, $startClone, $startBlock);
         $this->secondFace = $this->getZFace($direction);
         $secondDirection = $this->getZLength($direction);
         $secondPosition = $this->getZPosition($direction, $startClone, $startBlock);
         $this->thirdFace = $this->getXFace($direction);
         $thirdDirection = $this->getXLength($direction);
         $thirdPosition = $this->getXPosition($direction, $startClone, $startBlock);
     }
     if ($this->getZLength($direction) > $mainDirection) {
         $this->mainFace = $this->getZFace($direction);
         $mainDirection = $this->getZLength($direction);
         $mainPosition = $this->getZPosition($direction, $startClone, $startBlock);
         $this->secondFace = $this->getXFace($direction);
         $secondDirection = $this->getXLength($direction);
         $secondPosition = $this->getXPosition($direction, $startClone, $startBlock);
         $this->thirdFace = $this->getYFace($direction);
         $thirdDirection = $this->getYLength($direction);
         $thirdPosition = $this->getYPosition($direction, $startClone, $startBlock);
     }
     $d = $mainPosition / $mainDirection;
     $secondd = $secondPosition - $secondDirection * $d;
     $thirdd = $thirdPosition - $thirdDirection * $d;
     $this->secondError = floor($secondd * self::$gridSize);
     $this->secondStep = round($secondDirection / $mainDirection * self::$gridSize);
     $this->thirdError = floor($thirdd * self::$gridSize);
     $this->thirdStep = round($thirdDirection / $mainDirection * self::$gridSize);
     if ($this->secondError + $this->secondStep <= 0) {
         $this->secondError = -$this->secondStep + 1;
     }
     if ($this->thirdError + $this->thirdStep <= 0) {
         $this->thirdError = -$this->thirdStep + 1;
     }
     $lastBlock = $startBlock->getSide(Vector3::getOppositeSide($this->mainFace));
     if ($this->secondError < 0) {
         $this->secondError += self::$gridSize;
         $lastBlock = $lastBlock->getSide(Vector3::getOppositeSide($this->secondFace));
     }
     if ($this->thirdError < 0) {
         $this->thirdError += self::$gridSize;
         $lastBlock = $lastBlock->getSide(Vector3::getOppositeSide($this->thirdFace));
     }
     $this->secondError -= self::$gridSize;
     $this->thirdError -= self::$gridSize;
     $this->blockQueue[0] = $lastBlock;
     $this->currentBlock = -1;
     $this->scan();
     $startBlockFound = false;
     for ($cnt = $this->currentBlock; $cnt >= 0; --$cnt) {
         if ($this->blockEquals($this->blockQueue[$cnt], $startBlock)) {
             $this->currentBlock = $cnt;
             $startBlockFound = true;
             break;
         }
     }
     if (!$startBlockFound) {
         throw new \InvalidStateException("Start block missed in BlockIterator");
     }
     $this->maxDistanceInt = round($maxDistance / (sqrt($mainDirection ** 2 + $secondDirection ** 2 + $thirdDirection ** 2) / $mainDirection));
 }
示例#8
0
 public function getAttachedFace()
 {
     return Vector3::getOppositeSide($this->getFacing());
 }
示例#9
0
 /**
  * Returns a side Vector
  *
  * @param int $side
  * @param int $step
  *
  * @return Position
  *
  * @throws LevelException
  */
 public function getSide($side, $step = 1)
 {
     if (!$this->isValid()) {
         throw new LevelException("Undefined Level reference");
     }
     return Position::fromObject(parent::getSide($side, $step), $this->level);
 }
示例#10
0
 /**
  * @param Vector3|Position|Location $pos
  * @param float                     $yaw
  * @param float                     $pitch
  *
  * @return bool
  */
 public function teleport(Vector3 $pos, $yaw = null, $pitch = null)
 {
     if ($pos instanceof Location) {
         $yaw = $yaw === null ? $pos->yaw : $yaw;
         $pitch = $pitch === null ? $pos->pitch : $pitch;
     }
     $from = Position::fromObject($this, $this->level);
     $to = Position::fromObject($pos, $pos instanceof Position ? $pos->getLevel() : $this->level);
     $this->server->getPluginManager()->callEvent($ev = new EntityTeleportEvent($this, $from, $to));
     if ($ev->isCancelled()) {
         return false;
     }
     $this->ySize = 0;
     $pos = $ev->getTo();
     $this->setMotion($this->temporalVector->setComponents(0, 0, 0));
     if ($this->setPositionAndRotation($pos, $yaw === null ? $this->yaw : $yaw, $pitch === null ? $this->pitch : $pitch) !== false) {
         $this->resetFallDistance();
         $this->onGround = true;
         $this->lastX = $this->x;
         $this->lastY = $this->y;
         $this->lastZ = $this->z;
         $this->lastYaw = $this->yaw;
         $this->lastPitch = $this->pitch;
         $this->updateMovement();
         return true;
     }
     return false;
 }