public function onPlayerMove(PlayerMoveEvent $event) { $player = $event->getPlayer(); if ($player instanceof Player) { if ($player->getLevel()->getName() === $this->plugin->vipLevelName) { if (isset($this->plugin->statueManager->npcsSpawns[$player->getName()])) { return; } foreach ($this->plugin->statueManager->npcs as $xnpc) { if ($xnpc instanceof StatueModel) { if ($player->getLevel()->getName() === $xnpc->levelName) { $statuePos = $xnpc->position; $pp = new Vector2(round($player->x), round($player->z)); $npc = new Vector2($statuePos->x, $statuePos->z); $dff = abs(round($pp->distance($npc))); if ($dff < 12 || $dff == 0) { $builder = new StatueBuilder($this->plugin); $builder->displayStatues($player, $this->plugin->statueManager->npcs); $this->plugin->statueManager->npcsSpawns[$player->getName()] = $player->getName(); } } } } } } }
/** * Uses a item on a position and face, placing it or activating the block * * @param Vector3 $vector * @param Item $item * @param int $face * @param float $fx default 0.0 * @param float $fy default 0.0 * @param float $fz default 0.0 * @param Player $player default null * * @return boolean */ public function useItemOn(Vector3 $vector, Item &$item, $face, $fx = 0.0, $fy = 0.0, $fz = 0.0, Player $player = null) { $target = $this->getBlock($vector); $block = $target->getSide($face); if ($block->y > 127 or $block->y < 0) { return false; } if ($target->getId() === Item::AIR) { return false; } if ($player instanceof Player) { $ev = new PlayerInteractEvent($player, $item, $target, $face); if (!$player->isOp() and ($distance = $this->server->getConfigInt("spawn-protection", 16)) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if ($t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if (!$ev->isCancelled()) { $target->onUpdate(self::BLOCK_UPDATE_TOUCH); if ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if ($item->canBeActivated() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)) { if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); return true; } } } } elseif ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if ($item->isPlaceable()) { $hand = $item->getBlock(); $hand->position($block); } elseif ($block->getId() === Item::FIRE) { $this->setBlock($block, new Air(), true); return false; } else { return false; } if (!($block->canBeReplaced() === true or $hand->getId() === Item::SLAB and $block->getId() === Item::SLAB)) { return false; } if ($target->canBeReplaced() === true) { $block = $target; $hand->position($block); //$face = -1; } if ($hand->isSolid() === true and $hand->getBoundingBox() !== null) { $entities = $this->getCollidingEntities($hand->getBoundingBox()); $realCount = 0; foreach ($entities as $e) { if ($e instanceof Arrow or $e instanceof DroppedItem) { continue; } ++$realCount; } if ($realCount > 0) { return false; //Entity in block } } if ($player instanceof Player) { $ev = new BlockPlaceEvent($player, $hand, $block, $target, $item); if (!$player->isOp() and ($distance = $this->server->getConfigInt("spawn-protection", 16)) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if ($t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if ($ev->isCancelled()) { return false; } } if ($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false) { return false; } if ($hand->getId() === Item::SIGN_POST or $hand->getId() === Item::WALL_SIGN) { $tile = Tile::createTile("Sign", $this->getChunk($block->x >> 4, $block->z >> 4), new Compound(false, ["id" => new String("id", Tile::SIGN), "x" => new Int("x", $block->x), "y" => new Int("y", $block->y), "z" => new Int("z", $block->z), "Text1" => new String("Text1", ""), "Text2" => new String("Text2", ""), "Text3" => new String("Text3", ""), "Text4" => new String("Text4", "")])); if ($player instanceof Player) { $tile->namedtag->Creator = new String("Creator", $player->getName()); } } $item->setCount($item->getCount() - 1); if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); } return true; }
/** * Uses a item on a position and face, placing it or activating the block * * @param Vector3 $vector * @param Item $item * @param int $face * @param float $fx default 0.0 * @param float $fy default 0.0 * @param float $fz default 0.0 * @param Player $player default null * * @return boolean */ public function useItemOn(Vector3 $vector, Item &$item, $face, $fx = 0.0, $fy = 0.0, $fz = 0.0, Player $player = null) { $target = $this->getBlock($vector); $block = $target->getSide($face); if ($block->y > 127 or $block->y < 0) { return false; } if ($target->getId() === Item::AIR) { return false; } if ($player !== null) { $ev = new PlayerInteractEvent($player, $item, $target, $face, $target->getId() === 0 ? PlayerInteractEvent::RIGHT_CLICK_AIR : PlayerInteractEvent::RIGHT_CLICK_BLOCK); if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if (count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if (!$ev->isCancelled()) { $target->onUpdate(self::BLOCK_UPDATE_TOUCH); if (!$player->isSneaking() and $target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if (!$player->isSneaking() and $item->canBeActivated() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)) { if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); return true; } } } else { return false; } } elseif ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if ($item->canBePlaced()) { $hand = $item->getBlock(); $hand->position($block); } elseif ($block->getId() === Item::FIRE) { $this->setBlock($block, new Air(), true); return false; } else { return false; } if (!($block->canBeReplaced() === true or $hand->getId() === Item::SLAB and $block->getId() === Item::SLAB)) { return false; } if ($target->canBeReplaced() === true) { $block = $target; $hand->position($block); //$face = -1; } if ($hand->isSolid() === true and $hand->getBoundingBox() !== null) { $entities = $this->getCollidingEntities($hand->getBoundingBox()); $realCount = 0; foreach ($entities as $e) { if ($e instanceof Arrow or $e instanceof DroppedItem) { continue; } ++$realCount; } if ($player !== null) { if ($diff = $player->getNextPosition()->subtract($player->getPosition()) and $diff->lengthSquared() > 1.0E-5) { $bb = $player->getBoundingBox()->getOffsetBoundingBox($diff->x, $diff->y, $diff->z); if ($hand->getBoundingBox()->intersectsWith($bb)) { ++$realCount; } } } if ($realCount > 0) { return false; //Entity in block } } $tag = $item->getNamedTagEntry("CanPlaceOn"); if ($tag instanceof Enum) { $canPlace = false; foreach ($tag as $v) { if ($v instanceof String) { $entry = Item::fromString($v->getValue()); if ($entry->getId() > 0 and $entry->getBlock() !== null and $entry->getBlock()->getId() === $target->getId()) { $canPlace = true; break; } } } if (!$canPlace) { return false; } } if ($player !== null) { $ev = new BlockPlaceEvent($player, $hand, $block, $target, $item); if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if (count($this->server->getOps()->getAll()) > 0 and $t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if ($ev->isCancelled()) { return false; } } if ($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false) { return false; } if ($hand->getId() === Item::SIGN_POST or $hand->getId() === Item::WALL_SIGN) { $nbt = new Compound("", ["id" => new String("id", Tile::SIGN), "x" => new Int("x", $block->x), "y" => new Int("y", $block->y), "z" => new Int("z", $block->z), "Text1" => new String("Text1", ""), "Text2" => new String("Text2", ""), "Text3" => new String("Text3", ""), "Text4" => new String("Text4", "")]); if ($player !== null) { $nbt->Creator = new String("Creator", $player->getRawUniqueId()); } if ($item->hasCustomBlockData()) { foreach ($item->getCustomBlockData() as $key => $v) { $nbt->{$key} = $v; } } Tile::createTile("Sign", $this->getChunk($block->x >> 4, $block->z >> 4), $nbt); } $item->setCount($item->getCount() - 1); if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); } return true; }
/** * Hate Zombie coordinates update timer * Timer:10 ticks */ public function ZombieHateWalk() { $zo = $this->entity; $level = $zo->getLevel(); if (isset($this->data)) { $zom =& $this->data; //$zom['yup'] = $zom['yup'] - 1; if (!$zom['knockBack']) { $zom['oldv3'] = $zo->getLocation(); $zom['canjump'] = true; //Zombie collision detection foreach ($level->getEntities() as $zo0) { if ($zo0 instanceof Zombie and !($zo0 == $zo)) { if ($zo->distance($zo0) <= $this->width * 2) { $dx = $zo->x - $zo0->x; $dz = $zo->z - $zo0->z; if ($dx == 0) { $dx = mt_rand(-5, 5) / 5; if ($dx == 0) { $dx = 1; } } if ($dz == 0) { $dz = mt_rand(-5, 5) / 5; if ($dz == 0) { $dz = 1; } } $zo->knockBack($zo0, 0, $dx / 5, $dz / 5, 0); $newpos = new Vector3($zo->x + $dx * 5, $zo->y, $zo->z + $dz * 5); $zom['x'] = $newpos->x; $zom['y'] = $newpos->y; $zom['z'] = $newpos->z; Server::getInstance()->getScheduler()->scheduleDelayedTask(new CallbackTask([$this, "knockBackover"], [$newpos]), 5); } } } if ($zom['IsChasing'] !== false) { $p = Server::getInstance()->getPlayer($zom['IsChasing']); if ($p instanceof Player === false) { $zom['IsChasing'] = false; //Cancel hate mode } else { //The real traveling direction calculation $xx = $p->getX() - $zo->getX(); $zz = $p->getZ() - $zo->getZ(); $yaw = $this->getyaw($xx, $zz); /* * x = $xxx, z = $zzz * x0 = $xx, z0 = $zz * x^2 + z^2 = 0.7 * x/z = x0/z0 => x = bi * z * => * bi^2 * z^2 + z^2 = 0.7 * z^2 * (bi^2 + 1) = 0.7 * */ if ($zz != 0) { $bi = $xx / $zz; } else { $bi = 0; } //zombie walk faster if ($zo->getHealth() == $zo->getMaxHealth()) { $zzz = sqrt($this->zo_hate_v / 2.5 / ($bi * $bi + 1)); } else { $zzz = sqrt($this->zo_hate_v / 2 / ($bi * $bi + 1)); } if ($zz < 0) { $zzz = -$zzz; } $xxx = $zzz * $bi; $zo_v2 = new Vector2($zo->getX(), $zo->getZ()); $p_v2 = new Vector2($p->getX(), $p->getZ()); if ($zo_v2->distance($p_v2) <= $this->zo_hate_v / 2) { $xxx = $xx; $zzz = $zz; } $zom['xxx'] = $xxx; $zom['zzz'] = $zzz; //Calculating the y axis //$width = $this->width; $pos0 = new Vector3($zo->getX(), $zo->getY() + 1, $zo->getZ()); //Original coordinate $pos = new Vector3($zo->getX() + $xxx, $zo->getY() + 1, $zo->getZ() + $zzz); //Target coordinates //I used to write Zombie width //$v = $this->zo_hate_v/2; //$pos_front = new Vector3 ($zo->getX() + ($xxx/$v*($v+$this->width)), $zo->getY() + 1, $zo->getZ() + ($zzz/$v*($v+$this->width))); //Front coordinates //$pos_back = new Vector3 ($zo->getX() + (-$xxx/$v*(-$v-$this->width)), $zo->getY() + 1, $zo->getZ() + (-$zzz/$v*(-$v-$this->width))); //Rear coordinates $zy = $this->ifjump($zo->getLevel(), $pos, true); if ($zy === false or $zy !== false and $this->ifjump($zo->getLevel(), $pos0, true, true) == 'fall') { //Front can not move forwar if ($this->ifjump($zo->getLevel(), $pos0, false) === false) { //Original coordinate is still vacant if ($zom['drop'] === false) { $zom['drop'] = 0; //Zombie falling speed } $pos2 = new Vector3($zo->getX(), $zo->getY() - ($zom['drop'] / 2 + 1.25), $zo->getZ()); //decline } else { $zom['drop'] = false; if ($this->whatBlock($level, $pos0) == "climb") { //ladder $zy = $pos0->y + 0.7; $pos2 = new Vector3($zo->getX(), $zy - 1, $zo->getZ()); //Target coordinates } elseif ($xxx != 0 and $zzz != 0) { //To the closest distance 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()); //Target coordinates } 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); //Target coordinates } else { $pos2 = new Vector3($zo->getX() - $xxx / 5, floor($zo->getY()), $zo->getZ() - $zzz / 5); //Target coordinates //He turned 180 degrees, to go } } else { $pos2 = new Vector3($zo->getX() - $xxx / 5, floor($zo->getY()), $zo->getZ() - $zzz / 5); //Target coordinates } } } else { $pos2 = new Vector3($zo->getX() + $xxx, $zy - 1, $zo->getZ() + $zzz); //Target coordinates } $zo->setPosition($pos2); $pos3 = $pos2; $pos3->y = $pos3->y + 2.62; $ppos = $p->getLocation(); $ppos->y = $ppos->y + $p->getEyeHeight(); $pitch = $this->getpitch($pos3, $ppos); $zom['yaw'] = $yaw; $zom['pitch'] = $pitch; if (!$zom['knockBack']) { $zom['x'] = $zo->getX(); $zom['y'] = $zo->getY(); $zom['z'] = $zo->getZ(); } } } } } }
public function SkeletonHateWalk() { foreach ($this->plugin->getServer()->getLevels() as $level) { foreach ($level->getEntities() as $zo) { if ($zo instanceof Skeleton) { if (isset($this->plugin->Skeleton[$zo->getId()])) { $zom =& $this->plugin->Skeleton[$zo->getId()]; //$zom['yup'] = $zom['yup'] - 1; if (!$zom['knockBack']) { $zom['oldv3'] = $zo->getLocation(); $zom['canjump'] = true; //僵尸碰撞检测 by boybook foreach ($level->getEntities() as $zo0) { if ($zo0 instanceof Skeleton and !($zo0 == $zo)) { if ($zo->distance($zo0) <= $this->width * 2) { $dx = $zo->x - $zo0->x; $dz = $zo->z - $zo0->z; if ($dx == 0) { $dx = mt_rand(-5, 5) / 5; if ($dx == 0) { $dx = 1; } } if ($dz == 0) { $dz = mt_rand(-5, 5) / 5; if ($dz == 0) { $dz = 1; } } $zo->knockBack($zo0, 0, $dx / 5, $dz / 5, 0); $newpos = new Vector3($zo->x + $dx * 5, $zo->y, $zo->z + $dz * 5); $zom['x'] = $newpos->x; $zom['y'] = $newpos->y; $zom['z'] = $newpos->z; $this->plugin->getServer()->getScheduler()->scheduleDelayedTask(new CallbackTask([$this->plugin, "knockBackover"], [$zo, $newpos]), 5); } } } if ($zom['IsChasing'] !== false) { //echo ("是属于仇恨模式\n"); $p = $this->plugin->getServer()->getPlayer($zom['IsChasing']); if ($p instanceof Player === false) { $zom['IsChasing'] = false; //取消仇恨模式 } else { //真正的行走方向计算 $xx = $p->getX() - $zo->getX(); $zz = $p->getZ() - $zo->getZ(); $yaw = $this->plugin->getyaw($xx, $zz); /* * x = $xxx, z = $zzz * x0 = $xx, z0 = $zz * x^2 + z^2 = 0.7 * x/z = x0/z0 => x = bi * z * => * bi^2 * z^2 + z^2 = 0.7 * z^2 * (bi^2 + 1) = 0.7 * */ if ($zz != 0) { $bi = $xx / $zz; } else { $bi = 0; } //根据wiki:僵尸掉血后走路更快 if ($zo->getHealth() == $zo->getMaxHealth()) { $zzz = sqrt($this->zo_hate_v / 2.5 / ($bi * $bi + 1)); } else { $zzz = sqrt($this->zo_hate_v / 2 / ($bi * $bi + 1)); } if ($zz < 0) { $zzz = -$zzz; } $xxx = $zzz * $bi; $zo_v2 = new Vector2($zo->getX(), $zo->getZ()); $p_v2 = new Vector2($p->getX(), $p->getZ()); if ($zo_v2->distance($p_v2) <= $this->zo_hate_v / 2) { $xxx = $xx; $zzz = $zz; } $zom['xxx'] = $xxx; $zom['zzz'] = $zzz; //计算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); //目标坐标 //用来写僵尸宽度的 //$v = $this->zo_hate_v/2; //$pos_front = new Vector3 ($zo->getX() + ($xxx/$v*($v+$this->width)), $zo->getY() + 1, $zo->getZ() + ($zzz/$v*($v+$this->width))); //前方坐标 //$pos_back = new Vector3 ($zo->getX() + (-$xxx/$v*(-$v-$this->width)), $zo->getY() + 1, $zo->getZ() + (-$zzz/$v*(-$v-$this->width))); //后方坐标 $zy = $this->plugin->ifjump($zo->getLevel(), $pos, true); if ($zy === false or $zy !== false and $this->plugin->ifjump($zo->getLevel(), $pos0, true, true) == 'fall') { //前方不可前进 //真正的自由落体 by boybook if ($this->plugin->ifjump($zo->getLevel(), $pos0, false) === false) { //原坐标依然是悬空 if ($zom['drop'] === false) { $zom['drop'] = 0; //僵尸下落的速度 } $pos2 = new Vector3($zo->getX(), $zo->getY() - ($zom['drop'] / 2 + 1.25), $zo->getZ()); //下降 } else { $zom['drop'] = false; if ($this->plugin->whatBlock($level, $pos0) == "climb") { //梯子 $zy = $pos0->y + 0.7; $pos2 = new Vector3($zo->getX(), $zy - 1, $zo->getZ()); //目标坐标 } elseif ($xxx != 0 and $zzz != 0) { //走向最近距离 if ($this->plugin->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->plugin->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 / 5, floor($zo->getY()), $zo->getZ() - $zzz / 5); //目标坐标 //转向180度,向身后走 } } else { $pos2 = new Vector3($zo->getX() - $xxx / 5, floor($zo->getY()), $zo->getZ() - $zzz / 5); //目标坐标 } } } else { $pos2 = new Vector3($zo->getX() + $xxx, $zy - 1, $zo->getZ() + $zzz); //目标坐标 } $zo->setPosition($pos2); $pos3 = $pos2; $pos3->y = $pos3->y + 2.62; $ppos = $p->getLocation(); $ppos->y = $ppos->y + $p->getEyeHeight(); $pitch = $this->plugin->getpitch($pos3, $ppos); $zom['yaw'] = $yaw; $zom['pitch'] = $pitch; if (!$zom['knockBack']) { $zom['x'] = $zo->getX(); $zom['y'] = $zo->getY(); $zom['z'] = $zo->getZ(); } } } } } } } } }
public function seePlayer(Player $target) { $pk = new MovePlayerPacket(); $pk->eid = $this->eid; if ($this->pos->yaw === -1 and $target !== null) { $xdiff = $target->x - $this->pos->x; $zdiff = $target->z - $this->pos->z; $angle = atan2($zdiff, $xdiff); $pk->yaw = $angle * 180 / M_PI - 90; } else { $pk->yaw = $this->pos->yaw; } if ($this->pos->pitch === -1 and $target !== null) { $ydiff = $target->y - $this->pos->y; $vec = new Vector2($this->pos->x, $this->pos->z); $dist = $vec->distance($target->x, $target->z); $angle = atan2($dist, $ydiff); $pk->pitch = $angle * 180 / M_PI - 90; } else { $pk->pitch = $this->pitch; } $pk->x = $this->pos->x; $pk->y = $this->pos->y + 1.62; $pk->z = $this->pos->z; $pk->bodyYaw = $pk->yaw; $pk->onGruond = 0; $target->dataPacket($pk); }
/** * Uses a item on a position and face, placing it or activating the block * * @param Vector3 $vector * @param Item $item * @param int $face * @param float $fx default 0.0 * @param float $fy default 0.0 * @param float $fz default 0.0 * @param Player $player default null * * @return bool */ public function useItemOn(Vector3 $vector, Item &$item, int $face, float $fx = 0.0, float $fy = 0.0, float $fz = 0.0, Player $player = null) { $target = $this->getBlock($vector); $block = $target->getSide($face); if ($block->y > 127 or $block->y < 0) { return false; } if ($target->getId() === Item::AIR) { return false; } if ($player !== null) { $ev = new PlayerInteractEvent($player, $item, $target, $face, $target->getId() === 0 ? PlayerInteractEvent::RIGHT_CLICK_AIR : PlayerInteractEvent::RIGHT_CLICK_BLOCK); if ($player->isSpectator()) { $ev->setCancelled(); } if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if ($t->distance($s) <= $distance) { $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if (!$ev->isCancelled()) { $target->onUpdate(self::BLOCK_UPDATE_TOUCH); if (!$player->isSneaking() and $target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if (!$player->isSneaking() and $item->canBeActivated() and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)) { if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); return true; } } } else { return false; } } elseif ($target->canBeActivated() === true and $target->onActivate($item, $player) === true) { return true; } if ($item->canBePlaced()) { $hand = $item->getBlock(); $hand->position($block); } else { return false; } if (!($block->canBeReplaced() === true or $hand->getId() === Item::SLAB and $block->getId() === Item::SLAB)) { return false; } if ($target->canBeReplaced() === true) { $block = $target; $hand->position($block); //$face = -1; } if ($hand->isSolid() === true and $hand->getBoundingBox() !== null) { $entities = $this->getCollidingEntities($hand->getBoundingBox()); $realCount = 0; foreach ($entities as $e) { if ($e instanceof Arrow or $e instanceof DroppedItem) { continue; } ++$realCount; } if ($player !== null) { if ($diff = $player->getNextPosition()->subtract($player->getPosition()) and $diff->lengthSquared() > 1.0E-5) { $bb = $player->getBoundingBox()->getOffsetBoundingBox($diff->x, $diff->y, $diff->z); if ($hand->getBoundingBox()->intersectsWith($bb)) { ++$realCount; } } } if ($realCount > 0) { return false; //Entity in block } } $tag = $item->getNamedTagEntry("CanPlaceOn"); if ($tag instanceof ListTag) { $canPlace = false; foreach ($tag as $v) { if ($v instanceof StringTag) { $entry = Item::fromString($v->getValue()); if ($entry->getId() > 0 and $entry->getBlock() !== null and $entry->getBlock()->getId() === $target->getId()) { $canPlace = true; break; } } } if (!$canPlace) { return false; } } if ($player !== null) { $ev = new BlockPlaceEvent($player, $hand, $block, $target, $item); if (!$player->isOp() and ($distance = $this->server->getSpawnRadius()) > -1) { $t = new Vector2($target->x, $target->z); $s = new Vector2($this->getSpawnLocation()->x, $this->getSpawnLocation()->z); if ($t->distance($s) <= $distance) { //set it to cancelled so plugins can bypass this $ev->setCancelled(); } } $this->server->getPluginManager()->callEvent($ev); if ($ev->isCancelled()) { return false; } } if ($hand->place($item, $block, $target, $face, $fx, $fy, $fz, $player) === false) { return false; } $this->addSound(new BlockPlaceSound($this->getBlock($block))); //Get updated block, $block is still the original block and cannot be used directly $item->setCount($item->getCount() - 1); if ($item->getCount() <= 0) { $item = Item::get(Item::AIR, 0, 0); } return true; }
/** * handle player presence * * @param Player $player * @param Position $from */ public function npcHandlePlayerPresence(Player $player, Position $from) { foreach ($this->npcs as $xnpc) { $statuePos = $xnpc->position; $pp = new Vector2(round($player->x), round($player->z)); $npc = new Vector2($statuePos->x, $statuePos->z); $dff = abs(round($pp->distance($npc))); if ($dff < 4 || $dff == 0) { $x = round($from->x); $y = round($from->y); $z = round($from->z); if (round($player->x) != $x || round($player->y) != $y || round($player->z) != $z) { $posKey = round($statuePos->x) . "." . round($statuePos->y) . "." . round($statuePos->z); if (isset($this->npcsPositions[$posKey])) { $npc = $this->npcsPositions[$posKey]; $block = Item::get(Item::GLASS); $direct = false; $update = true; $player->level->setBlock($statuePos, $block->getBlock(), $direct, $update); StatueBuilder::refreshNPCEquipments($player, $npc); } } } } }
private function getLeafGroupPoints(ChunkManager $level, $x, $y, $z) { $amount = $this->leafAmount * $this->totalHeight / 13; $groupsPerLayer = (int) (1.382 + $amount * $amount); if ($groupsPerLayer == 0) { $groupsPerLayer = 1; } $trunkTopY = $y + $this->trunkHeight; $groups = []; $groupY = $y + $this->totalHeight - $this->leafDistanceLimit; $groups[] = [new Vector3($x, $groupY, $z), $trunkTopY]; for ($currentLayer = (int) ($this->totalHeight - $this->leafDistanceLimit); $currentLayer >= 0; $currentLayer--) { $layerSize = $this->getRoughLayerSize($currentLayer); if ($layerSize < 0) { $groupY--; continue; } for ($count = 0; $count < $groupsPerLayer; $count++) { $scale = $this->widthScale * $layerSize * ($this->random->nextFloat() + 0.328); $randomOffset = Vector2::createRandomDirection($this->random)->multiply($scale); $groupX = (int) ($randomOffset->getX() + $x + 0.5); $groupZ = (int) ($randomOffset->getY() + $z + 0.5); $group = new Vector3($groupX, $groupY, $groupZ); if ($this->getAvailableBlockSpace($level, $group, $group->add(0, $this->leafDistanceLimit, 0)) != -1) { continue; } $xOff = (int) ($x - $groupX); $zOff = (int) ($z - $groupZ); $horizontalDistanceToTrunk = sqrt($xOff * $xOff + $zOff * $zOff); $verticalDistanceToTrunk = $horizontalDistanceToTrunk * $this->branchSlope; $yDiff = (int) ($groupY - $verticalDistanceToTrunk); if ($yDiff > $trunkTopY) { $base = $trunkTopY; } else { $base = $yDiff; } if ($this->getAvailableBlockSpace($level, new Vector3($x, $base, $z), $group) == -1) { $groups[] = [$group, $base]; } } $groupY--; } return $groups; }