From 2d4a32fc77c89909bb6bb623ee271f565b93493f Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 19 Aug 2019 17:20:34 +0100 Subject: [PATCH] first look at separating Entity and Location --- src/block/Banner.php | 2 +- src/block/Bed.php | 3 +- src/block/Ladder.php | 2 +- src/block/Sign.php | 2 +- src/block/Skull.php | 2 +- src/command/defaults/ParticleCommand.php | 9 +- src/command/defaults/SeedCommand.php | 2 +- src/command/defaults/SetWorldSpawnCommand.php | 5 +- src/command/defaults/SpawnpointCommand.php | 3 +- src/command/defaults/TeleportCommand.php | 14 +- src/entity/Entity.php | 173 ++++++++++-------- src/entity/ExperienceManager.php | 6 +- src/entity/Human.php | 8 +- src/entity/Living.php | 32 ++-- src/entity/Squid.php | 8 +- src/entity/object/ExperienceOrb.php | 10 +- src/entity/object/FallingBlock.php | 13 +- src/entity/object/ItemEntity.php | 4 +- src/entity/object/Painting.php | 6 +- src/entity/object/PrimedTNT.php | 4 +- src/entity/projectile/Arrow.php | 2 +- src/entity/projectile/Egg.php | 2 +- src/entity/projectile/EnderPearl.php | 7 +- src/entity/projectile/ExperienceBottle.php | 6 +- src/entity/projectile/Projectile.php | 22 +-- src/entity/projectile/Snowball.php | 2 +- src/entity/projectile/SplashPotion.php | 12 +- src/item/Bow.php | 9 +- src/item/ChorusFruit.php | 9 +- src/item/ProjectileItem.php | 7 +- src/item/enchantment/KnockbackEnchantment.php | 3 +- src/network/mcpe/NetworkSession.php | 14 +- .../mcpe/handler/InGamePacketHandler.php | 10 +- .../mcpe/handler/PreSpawnPacketHandler.php | 11 +- src/player/Player.php | 129 +++++++------ src/world/Explosion.php | 6 +- 36 files changed, 302 insertions(+), 257 deletions(-) diff --git a/src/block/Banner.php b/src/block/Banner.php index 216335615..23f0a026a 100644 --- a/src/block/Banner.php +++ b/src/block/Banner.php @@ -156,7 +156,7 @@ class Banner extends Transparent{ if($face !== Facing::DOWN){ $this->facing = $face; if($face === Facing::UP){ - $this->rotation = $player !== null ? ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f : 0; + $this->rotation = $player !== null ? ((int) floor((($player->getLocation()->getYaw() + 180) * 16 / 360) + 0.5)) & 0x0f : 0; } return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); diff --git a/src/block/Bed.php b/src/block/Bed.php index e8f07dc27..a8f4cdf47 100644 --- a/src/block/Bed.php +++ b/src/block/Bed.php @@ -138,11 +138,12 @@ class Bed extends Transparent{ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ if($player !== null){ $other = $this->getOtherHalf(); + $playerPos = $player->getPosition(); if($other === null){ $player->sendMessage(TextFormat::GRAY . "This bed is incomplete"); return true; - }elseif($player->distanceSquared($this->pos) > 4 and $player->distanceSquared($other->pos) > 4){ + }elseif($playerPos->distanceSquared($this->pos) > 4 and $playerPos->distanceSquared($other->pos) > 4){ $player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.tooFar")); return true; } diff --git a/src/block/Ladder.php b/src/block/Ladder.php index 9478bf5bb..8ff08707e 100644 --- a/src/block/Ladder.php +++ b/src/block/Ladder.php @@ -66,7 +66,7 @@ class Ladder extends Transparent{ } public function onEntityInside(Entity $entity) : void{ - if($entity->asVector3()->floor()->distanceSquared($this->pos) < 1){ //entity coordinates must be inside block + if($entity->getPosition()->floor()->distanceSquared($this->pos) < 1){ //entity coordinates must be inside block $entity->resetFallDistance(); $entity->onGround = true; } diff --git a/src/block/Sign.php b/src/block/Sign.php index c8c35f598..88bd8f784 100644 --- a/src/block/Sign.php +++ b/src/block/Sign.php @@ -118,7 +118,7 @@ class Sign extends Transparent{ if($face !== Facing::DOWN){ $this->facing = $face; if($face === Facing::UP){ - $this->rotation = $player !== null ? ((int) floor((($player->yaw + 180) * 16 / 360) + 0.5)) & 0x0f : 0; + $this->rotation = $player !== null ? ((int) floor((($player->getLocation()->getYaw() + 180) * 16 / 360) + 0.5)) & 0x0f : 0; } return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); diff --git a/src/block/Skull.php b/src/block/Skull.php index 3d33758b3..e5cd481e9 100644 --- a/src/block/Skull.php +++ b/src/block/Skull.php @@ -108,7 +108,7 @@ class Skull extends Flowable{ $this->skullType = $item->getSkullType(); //TODO: the item should handle this, but this hack is currently needed because of tile mess } if($player !== null and $face === Facing::UP){ - $this->rotation = ((int) floor(($player->yaw * 16 / 360) + 0.5)) & 0xf; + $this->rotation = ((int) floor(($player->getLocation()->getYaw() * 16 / 360) + 0.5)) & 0xf; } return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } diff --git a/src/command/defaults/ParticleCommand.php b/src/command/defaults/ParticleCommand.php index 22afc6dc6..6a2c380f9 100644 --- a/src/command/defaults/ParticleCommand.php +++ b/src/command/defaults/ParticleCommand.php @@ -91,11 +91,12 @@ class ParticleCommand extends VanillaCommand{ } if($sender instanceof Player){ - $world = $sender->getWorld(); + $senderPos = $sender->getPosition(); + $world = $senderPos->getWorld(); $pos = new Vector3( - $this->getRelativeDouble($sender->getX(), $sender, $args[1]), - $this->getRelativeDouble($sender->getY(), $sender, $args[2], 0, World::Y_MAX), - $this->getRelativeDouble($sender->getZ(), $sender, $args[3]) + $this->getRelativeDouble($senderPos->getX(), $sender, $args[1]), + $this->getRelativeDouble($senderPos->getY(), $sender, $args[2], 0, World::Y_MAX), + $this->getRelativeDouble($senderPos->getZ(), $sender, $args[3]) ); }else{ $world = $sender->getServer()->getWorldManager()->getDefaultWorld(); diff --git a/src/command/defaults/SeedCommand.php b/src/command/defaults/SeedCommand.php index 1ce522ff6..29017edb5 100644 --- a/src/command/defaults/SeedCommand.php +++ b/src/command/defaults/SeedCommand.php @@ -44,7 +44,7 @@ class SeedCommand extends VanillaCommand{ } if($sender instanceof Player){ - $seed = $sender->getWorld()->getSeed(); + $seed = $sender->getPosition()->getWorld()->getSeed(); }else{ $seed = $sender->getServer()->getWorldManager()->getDefaultWorld()->getSeed(); } diff --git a/src/command/defaults/SetWorldSpawnCommand.php b/src/command/defaults/SetWorldSpawnCommand.php index 641de76b2..45534184a 100644 --- a/src/command/defaults/SetWorldSpawnCommand.php +++ b/src/command/defaults/SetWorldSpawnCommand.php @@ -51,8 +51,9 @@ class SetWorldSpawnCommand extends VanillaCommand{ if(count($args) === 0){ if($sender instanceof Player){ - $world = $sender->getWorld(); - $pos = (new Vector3($sender->x, $sender->y, $sender->z))->round(); + $location = $sender->getPosition(); + $world = $location->getWorld(); + $pos = $location->asVector3()->round(); }else{ $sender->sendMessage(TextFormat::RED . "You can only perform this command as a player"); diff --git a/src/command/defaults/SpawnpointCommand.php b/src/command/defaults/SpawnpointCommand.php index 071433b3b..91813c24c 100644 --- a/src/command/defaults/SpawnpointCommand.php +++ b/src/command/defaults/SpawnpointCommand.php @@ -82,7 +82,8 @@ class SpawnpointCommand extends VanillaCommand{ return true; }elseif(count($args) <= 1){ if($sender instanceof Player){ - $pos = new Position($sender->getFloorX(), $sender->getFloorY(), $sender->getFloorZ(), $sender->getWorld()); + $cpos = $sender->getPosition(); + $pos = Position::fromObject($cpos->floor(), $cpos->getWorld()); $target->setSpawn($pos); Command::broadcastCommandMessage($sender, new TranslationContainer("commands.spawnpoint.success", [$target->getName(), round($pos->x, 2), round($pos->y, 2), round($pos->z, 2)])); diff --git a/src/command/defaults/TeleportCommand.php b/src/command/defaults/TeleportCommand.php index 512ce095d..9494546d4 100644 --- a/src/command/defaults/TeleportCommand.php +++ b/src/command/defaults/TeleportCommand.php @@ -96,8 +96,10 @@ class TeleportCommand extends VanillaCommand{ } } + $targetLocation = $target->getLocation(); + if(count($args) < 3){ - $origin->teleport($target); + $origin->teleport($targetLocation); Command::broadcastCommandMessage($sender, new TranslationContainer("commands.tp.success", [$origin->getName(), $target->getName()])); return true; @@ -108,11 +110,11 @@ class TeleportCommand extends VanillaCommand{ $pos = 0; } - $x = $this->getRelativeDouble($target->x, $sender, $args[$pos++]); - $y = $this->getRelativeDouble($target->y, $sender, $args[$pos++], 0, 256); - $z = $this->getRelativeDouble($target->z, $sender, $args[$pos++]); - $yaw = $target->getYaw(); - $pitch = $target->getPitch(); + $x = $this->getRelativeDouble($targetLocation->x, $sender, $args[$pos++]); + $y = $this->getRelativeDouble($targetLocation->y, $sender, $args[$pos++], 0, 256); + $z = $this->getRelativeDouble($targetLocation->z, $sender, $args[$pos++]); + $yaw = $targetLocation->getYaw(); + $pitch = $targetLocation->getPitch(); if(count($args) === 6 or (count($args) === 5 and $pos === 3)){ $yaw = (float) $args[$pos++]; diff --git a/src/entity/Entity.php b/src/entity/Entity.php index 9ef45a078..d2e54ed58 100644 --- a/src/entity/Entity.php +++ b/src/entity/Entity.php @@ -59,7 +59,6 @@ use pocketmine\Server; use pocketmine\timings\Timings; use pocketmine\timings\TimingsHandler; use pocketmine\world\format\Chunk; -use pocketmine\entity\Location; use pocketmine\world\Position; use pocketmine\world\World; use function abs; @@ -77,7 +76,7 @@ use function sin; use function spl_object_id; use const M_PI_2; -abstract class Entity extends Location{ +abstract class Entity{ public const MOTION_THRESHOLD = 0.00001; @@ -103,6 +102,8 @@ abstract class Entity extends Location{ /** @var Block[] */ protected $blocksAround = []; + /** @var Location */ + protected $location; /** @var Location */ protected $lastLocation; /** @var Vector3 */ @@ -240,13 +241,17 @@ abstract class Entity extends Location{ /** @var float[] $rotation */ $rotation = $nbt->getListTag("Rotation")->getAllValues(); - parent::__construct($pos[0], $pos[1], $pos[2], $rotation[0], $rotation[1], $world); - assert(!is_nan($this->x) and !is_infinite($this->x) and !is_nan($this->y) and !is_infinite($this->y) and !is_nan($this->z) and !is_infinite($this->z)); + $this->location = new Location($pos[0], $pos[1], $pos[2], $rotation[0], $rotation[1], $world); + assert( + !is_nan($this->location->x) and !is_infinite($this->location->x) and + !is_nan($this->location->y) and !is_infinite($this->location->y) and + !is_nan($this->location->z) and !is_infinite($this->location->z) + ); $this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0); $this->recalculateBoundingBox(); - $this->chunk = $this->world->getChunkAtPosition($this, false); + $this->chunk = $this->getWorld()->getChunkAtPosition($this->location, false); if($this->chunk === null){ throw new \InvalidStateException("Cannot create entities in unloaded chunks"); } @@ -268,7 +273,7 @@ abstract class Entity extends Location{ $this->initEntity($nbt); $this->chunk->addEntity($this); - $this->world->addEntity($this); + $this->getWorld()->addEntity($this); $this->lastUpdate = $this->server->getTick(); (new EntitySpawnEvent($this))->call(); @@ -366,12 +371,12 @@ abstract class Entity extends Location{ $halfWidth = $this->width / 2; $this->boundingBox = new AxisAlignedBB( - $this->x - $halfWidth, - $this->y, - $this->z - $halfWidth, - $this->x + $halfWidth, - $this->y + $this->height, - $this->z + $halfWidth + $this->location->x - $halfWidth, + $this->location->y, + $this->location->z - $halfWidth, + $this->location->x + $halfWidth, + $this->location->y + $this->height, + $this->location->z + $halfWidth ); } @@ -544,9 +549,9 @@ abstract class Entity extends Location{ } $nbt->setTag("Pos", new ListTag([ - new DoubleTag($this->x), - new DoubleTag($this->y), - new DoubleTag($this->z) + new DoubleTag($this->location->x), + new DoubleTag($this->location->y), + new DoubleTag($this->location->z) ])); $nbt->setTag("Motion", new ListTag([ @@ -556,8 +561,8 @@ abstract class Entity extends Location{ ])); $nbt->setTag("Rotation", new ListTag([ - new FloatTag($this->yaw), - new FloatTag($this->pitch) + new FloatTag($this->location->yaw), + new FloatTag($this->location->pitch) ])); $nbt->setFloat("FallDistance", $this->fallDistance); @@ -727,7 +732,7 @@ abstract class Entity extends Location{ $this->checkBlockCollision(); - if($this->y <= -16 and $this->isAlive()){ + if($this->location->y <= -16 and $this->isAlive()){ $ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10); $this->attack($ev); $hasUpdate = true; @@ -826,13 +831,13 @@ abstract class Entity extends Location{ //TODO: hack for client-side AI interference: prevent client sided movement when motion is 0 $this->setImmobile($this->motion->x == 0 and $this->motion->y == 0 and $this->motion->z == 0); - $diffPosition = $this->distanceSquared($this->lastLocation); - $diffRotation = ($this->yaw - $this->lastLocation->yaw) ** 2 + ($this->pitch - $this->lastLocation->pitch) ** 2; + $diffPosition = $this->location->distanceSquared($this->lastLocation); + $diffRotation = ($this->location->yaw - $this->lastLocation->yaw) ** 2 + ($this->location->pitch - $this->lastLocation->pitch) ** 2; $diffMotion = $this->motion->subtract($this->lastMotion)->lengthSquared(); if($teleport or $diffPosition > 0.0001 or $diffRotation > 1.0){ - $this->lastLocation = $this->asLocation(); + $this->lastLocation = $this->location->asLocation(); $this->broadcastMovement($teleport); } @@ -851,24 +856,24 @@ abstract class Entity extends Location{ protected function broadcastMovement(bool $teleport = false) : void{ $pk = new MoveActorAbsolutePacket(); $pk->entityRuntimeId = $this->id; - $pk->position = $this->getOffsetPosition($this); + $pk->position = $this->getOffsetPosition($this->location); //this looks very odd but is correct as of 1.5.0.7 //for arrows this is actually x/y/z rotation //for mobs x and z are used for pitch and yaw, and y is used for headyaw - $pk->xRot = $this->pitch; - $pk->yRot = $this->yaw; //TODO: head yaw - $pk->zRot = $this->yaw; + $pk->xRot = $this->location->pitch; + $pk->yRot = $this->location->yaw; //TODO: head yaw + $pk->zRot = $this->location->yaw; if($teleport){ $pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT; } - $this->world->broadcastPacketToViewers($this, $pk); + $this->getWorld()->broadcastPacketToViewers($this->location, $pk); } protected function broadcastMotion() : void{ - $this->world->broadcastPacketToViewers($this, SetActorMotionPacket::create($this->id, $this->getMotion())); + $this->getWorld()->broadcastPacketToViewers($this->location, SetActorMotionPacket::create($this->id, $this->getMotion())); } public function hasGravity() : bool{ @@ -903,7 +908,7 @@ abstract class Entity extends Location{ } if($this->onGround){ - $friction *= $this->world->getBlockAt((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z))->getFrictionFactor(); + $friction *= $this->getWorld()->getBlockAt((int) floor($this->location->x), (int) floor($this->location->y - 1), (int) floor($this->location->z))->getFrictionFactor(); } $this->motion->x *= $friction; @@ -911,7 +916,8 @@ abstract class Entity extends Location{ } protected function checkObstruction(float $x, float $y, float $z) : bool{ - if(count($this->world->getCollisionBoxes($this, $this->getBoundingBox(), false)) === 0){ + $world = $this->getWorld(); + if(count($world->getCollisionBoxes($this, $this->getBoundingBox(), false)) === 0){ return false; } @@ -923,13 +929,13 @@ abstract class Entity extends Location{ $diffY = $y - $floorY; $diffZ = $z - $floorZ; - if($this->world->getBlockAt($floorX, $floorY, $floorZ)->isSolid()){ - $westNonSolid = !$this->world->getBlockAt($floorX - 1, $floorY, $floorZ)->isSolid(); - $eastNonSolid = !$this->world->getBlockAt($floorX + 1, $floorY, $floorZ)->isSolid(); - $downNonSolid = !$this->world->getBlockAt($floorX, $floorY - 1, $floorZ)->isSolid(); - $upNonSolid = !$this->world->getBlockAt($floorX, $floorY + 1, $floorZ)->isSolid(); - $northNonSolid = !$this->world->getBlockAt($floorX, $floorY, $floorZ - 1)->isSolid(); - $southNonSolid = !$this->world->getBlockAt($floorX, $floorY, $floorZ + 1)->isSolid(); + if($world->getBlockAt($floorX, $floorY, $floorZ)->isSolid()){ + $westNonSolid = !$world->getBlockAt($floorX - 1, $floorY, $floorZ)->isSolid(); + $eastNonSolid = !$world->getBlockAt($floorX + 1, $floorY, $floorZ)->isSolid(); + $downNonSolid = !$world->getBlockAt($floorX, $floorY - 1, $floorZ)->isSolid(); + $upNonSolid = !$world->getBlockAt($floorX, $floorY + 1, $floorZ)->isSolid(); + $northNonSolid = !$world->getBlockAt($floorX, $floorY, $floorZ - 1)->isSolid(); + $southNonSolid = !$world->getBlockAt($floorX, $floorY, $floorZ + 1)->isSolid(); $direction = -1; $limit = 9999; @@ -1006,7 +1012,7 @@ abstract class Entity extends Location{ } public function getHorizontalFacing() : int{ - $angle = $this->yaw % 360; + $angle = $this->location->yaw % 360; if($angle < 0){ $angle += 360.0; } @@ -1028,16 +1034,16 @@ abstract class Entity extends Location{ * @return Vector3 */ public function getDirectionVector() : Vector3{ - $y = -sin(deg2rad($this->pitch)); - $xz = cos(deg2rad($this->pitch)); - $x = -$xz * sin(deg2rad($this->yaw)); - $z = $xz * cos(deg2rad($this->yaw)); + $y = -sin(deg2rad($this->location->pitch)); + $xz = cos(deg2rad($this->location->pitch)); + $x = -$xz * sin(deg2rad($this->location->yaw)); + $z = $xz * cos(deg2rad($this->location->yaw)); return $this->temporalVector->setComponents($x, $y, $z)->normalize(); } public function getDirectionPlane() : Vector2{ - return (new Vector2(-cos(deg2rad($this->yaw) - M_PI_2), -sin(deg2rad($this->yaw) - M_PI_2)))->normalize(); + return (new Vector2(-cos(deg2rad($this->location->yaw) - M_PI_2), -sin(deg2rad($this->location->yaw) - M_PI_2)))->normalize(); } public function onUpdate(int $currentTick) : bool{ @@ -1105,7 +1111,7 @@ abstract class Entity extends Location{ if($this->closed){ throw new \InvalidStateException("Cannot schedule update on garbage entity " . get_class($this)); } - $this->world->updateEntities[$this->id] = $this; + $this->getWorld()->updateEntities[$this->id] = $this; } public function onNearbyBlockChange() : void{ @@ -1172,7 +1178,7 @@ abstract class Entity extends Location{ } public function getEyePos() : Vector3{ - return new Vector3($this->x, $this->y + $this->getEyeHeight(), $this->z); + return new Vector3($this->location->x, $this->location->y + $this->getEyeHeight(), $this->location->z); } public function onCollideWithPlayer(Player $player) : void{ @@ -1180,7 +1186,7 @@ abstract class Entity extends Location{ } public function isUnderwater() : bool{ - $block = $this->world->getBlockAt((int) floor($this->x), $blockY = (int) floor($y = ($this->y + $this->getEyeHeight())), (int) floor($this->z)); + $block = $this->getWorld()->getBlockAt((int) floor($this->location->x), $blockY = (int) floor($y = ($this->location->y + $this->getEyeHeight())), (int) floor($this->location->z)); if($block instanceof Water){ $f = ($blockY + 1) - ($block->getFluidHeightPercent() - 0.1111111); @@ -1191,7 +1197,7 @@ abstract class Entity extends Location{ } public function isInsideOfSolid() : bool{ - $block = $this->world->getBlockAt((int) floor($this->x), (int) floor($y = ($this->y + $this->getEyeHeight())), (int) floor($this->z)); + $block = $this->getWorld()->getBlockAt((int) floor($this->location->x), (int) floor($y = ($this->location->y + $this->getEyeHeight())), (int) floor($this->location->z)); return $block->isSolid() and !$block->isTransparent() and $block->collidesWithBB($this->getBoundingBox()); } @@ -1252,7 +1258,7 @@ abstract class Entity extends Location{ assert(abs($dx) <= 20 and abs($dy) <= 20 and abs($dz) <= 20, "Movement distance is excessive: dx=$dx, dy=$dy, dz=$dz"); - $list = $this->world->getCollisionBoxes($this, $moveBB->addCoord($dx, $dy, $dz), false); + $list = $this->getWorld()->getCollisionBoxes($this, $moveBB->addCoord($dx, $dy, $dz), false); foreach($list as $bb){ $dy = $bb->calculateYOffset($moveBB, $dy); @@ -1285,8 +1291,7 @@ abstract class Entity extends Location{ $stepBB = clone $this->boundingBox; - $list = $this->world->getCollisionBoxes($this, $stepBB->addCoord($dx, $dy, $dz), false); - + $list = $this->getWorld()->getCollisionBoxes($this, $stepBB->addCoord($dx, $dy, $dz), false); foreach($list as $bb){ $dy = $bb->calculateYOffset($stepBB, $dy); } @@ -1318,9 +1323,9 @@ abstract class Entity extends Location{ $this->boundingBox = $moveBB; } - $this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; - $this->y = $this->boundingBox->minY - $this->ySize; - $this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; + $this->location->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; + $this->location->y = $this->boundingBox->minY - $this->ySize; + $this->location->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; $this->checkChunks(); $this->checkBlockCollision(); @@ -1370,10 +1375,12 @@ abstract class Entity extends Location{ $this->blocksAround = []; + $world = $this->getWorld(); + for($z = $minZ; $z <= $maxZ; ++$z){ for($x = $minX; $x <= $maxX; ++$x){ for($y = $minY; $y <= $maxY; ++$y){ - $block = $this->world->getBlockAt($x, $y, $z); + $block = $world->getBlockAt($x, $y, $z); if($block->hasEntityCollision()){ $this->blocksAround[] = $block; } @@ -1412,11 +1419,15 @@ abstract class Entity extends Location{ } public function getPosition() : Position{ - return $this->asPosition(); + return $this->location->asPosition(); } public function getLocation() : Location{ - return $this->asLocation(); + return $this->location->asLocation(); + } + + public function getWorld() : World{ + return $this->location->getWorld(); } protected function setPosition(Vector3 $pos) : bool{ @@ -1424,15 +1435,15 @@ abstract class Entity extends Location{ return false; } - if($pos instanceof Position and $pos->world !== null and $pos->world !== $this->world){ + if($pos instanceof Position and $pos->world !== null and $pos->world !== $this->getWorld()){ if(!$this->switchWorld($pos->getWorld())){ return false; } } - $this->x = $pos->x; - $this->y = $pos->y; - $this->z = $pos->z; + $this->location->x = $pos->x; + $this->location->y = $pos->y; + $this->location->z = $pos->z; $this->recalculateBoundingBox(); @@ -1444,8 +1455,8 @@ abstract class Entity extends Location{ } public function setRotation(float $yaw, float $pitch) : void{ - $this->yaw = $yaw; - $this->pitch = $pitch; + $this->location->yaw = $yaw; + $this->location->pitch = $pitch; $this->scheduleUpdate(); } @@ -1460,16 +1471,16 @@ abstract class Entity extends Location{ } protected function checkChunks() : void{ - $chunkX = $this->getFloorX() >> 4; - $chunkZ = $this->getFloorZ() >> 4; + $chunkX = $this->location->getFloorX() >> 4; + $chunkZ = $this->location->getFloorZ() >> 4; if($this->chunk === null or ($this->chunk->getX() !== $chunkX or $this->chunk->getZ() !== $chunkZ)){ if($this->chunk !== null){ $this->chunk->removeEntity($this); } - $this->chunk = $this->world->getChunk($chunkX, $chunkZ, true); + $this->chunk = $this->getWorld()->getChunk($chunkX, $chunkZ, true); if(!$this->justCreated){ - $newChunk = $this->world->getViewersForPosition($this); + $newChunk = $this->getWorld()->getViewersForPosition($this->location); foreach($this->hasSpawned as $player){ if(!isset($newChunk[spl_object_id($player)])){ $this->despawnFrom($player); @@ -1491,7 +1502,7 @@ abstract class Entity extends Location{ } protected function resetLastMovements() : void{ - $this->lastLocation = $this->asLocation(); + $this->lastLocation = $this->location->asLocation(); $this->lastMotion = clone $this->motion; } @@ -1546,8 +1557,8 @@ abstract class Entity extends Location{ $yaw = $yaw ?? $pos->yaw; $pitch = $pitch ?? $pos->pitch; } - $from = Position::fromObject($this, $this->world); - $to = Position::fromObject($pos, $pos instanceof Position ? $pos->getWorld() : $this->world); + $from = $this->location->asPosition(); + $to = Position::fromObject($pos, $pos instanceof Position ? $pos->getWorld() : $this->getWorld()); $ev = new EntityTeleportEvent($this, $from, $to); $ev->call(); if($ev->isCancelled()){ @@ -1557,7 +1568,7 @@ abstract class Entity extends Location{ $pos = $ev->getTo(); $this->setMotion($this->temporalVector->setComponents(0, 0, 0)); - if($this->setPositionAndRotation($pos, $yaw ?? $this->yaw, $pitch ?? $this->pitch)){ + if($this->setPositionAndRotation($pos, $yaw ?? $this->location->yaw, $pitch ?? $this->location->pitch)){ $this->resetFallDistance(); $this->onGround = true; @@ -1574,16 +1585,16 @@ abstract class Entity extends Location{ return false; } - if($this->isValid()){ - $this->world->removeEntity($this); + if($this->location->isValid()){ + $this->getWorld()->removeEntity($this); if($this->chunk !== null){ $this->chunk->removeEntity($this); } $this->despawnFromAll(); } - $this->setWorld($targetWorld); - $this->world->addEntity($this); + $this->location->setWorld($targetWorld); + $this->getWorld()->addEntity($this); $this->chunk = null; return true; @@ -1609,11 +1620,11 @@ abstract class Entity extends Location{ $pk = new AddActorPacket(); $pk->entityRuntimeId = $this->getId(); $pk->type = static::NETWORK_ID; - $pk->position = $this->asVector3(); + $pk->position = $this->location->asVector3(); $pk->motion = $this->getMotion(); - $pk->yaw = $this->yaw; - $pk->headYaw = $this->yaw; //TODO - $pk->pitch = $this->pitch; + $pk->yaw = $this->location->yaw; + $pk->headYaw = $this->location->yaw; //TODO + $pk->pitch = $this->location->pitch; $pk->attributes = $this->attributeMap->getAll(); $pk->metadata = $this->getSyncedNetworkData(false); @@ -1636,7 +1647,7 @@ abstract class Entity extends Location{ if($this->closed){ return; } - foreach($this->world->getViewersForPosition($this) as $player){ + foreach($this->getWorld()->getViewersForPosition($this->location) as $player){ $this->spawnTo($player); } } @@ -1719,8 +1730,8 @@ abstract class Entity extends Location{ if($this->chunk !== null){ $this->chunk->removeEntity($this); } - if($this->isValid()){ - $this->world->removeEntity($this); + if($this->location->isValid()){ + $this->getWorld()->removeEntity($this); } } @@ -1732,7 +1743,7 @@ abstract class Entity extends Location{ */ protected function destroyCycles() : void{ $this->chunk = null; - $this->setWorld(null); + $this->location->setWorld(null); $this->lastDamageCause = null; } diff --git a/src/entity/ExperienceManager.php b/src/entity/ExperienceManager.php index 1c963c43c..1d280812d 100644 --- a/src/entity/ExperienceManager.php +++ b/src/entity/ExperienceManager.php @@ -95,7 +95,7 @@ class ExperienceManager{ if($playSound){ $newLevel = $this->getXpLevel(); if((int) ($newLevel / 5) > (int) ($oldLevel / 5)){ - $this->entity->getWorld()->addSound($this->entity->asVector3(), new XpLevelUpSound($newLevel)); + $this->entity->getWorld()->addSound($this->entity->getPosition(), new XpLevelUpSound($newLevel)); } } @@ -187,9 +187,9 @@ class ExperienceManager{ if($playSound){ $newLevel = $this->getXpLevel(); if((int) ($newLevel / 5) > (int) ($oldLevel / 5)){ - $this->entity->getWorld()->addSound($this->entity->asVector3(), new XpLevelUpSound($newLevel)); + $this->entity->getWorld()->addSound($this->entity->getPosition(), new XpLevelUpSound($newLevel)); }elseif($this->getCurrentTotalXp() > $oldTotal){ - $this->entity->getWorld()->addSound($this->entity->asVector3(), new XpCollectSound()); + $this->entity->getWorld()->addSound($this->entity->getPosition(), new XpCollectSound()); } } diff --git a/src/entity/Human.php b/src/entity/Human.php index 838b0c6bb..8a7eca6e3 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -316,7 +316,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $this->effectManager->add(new EffectInstance(VanillaEffects::ABSORPTION(), 5 * 20, 1)); $this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM); - $this->world->addSound($this->add(0, $this->eyeHeight, 0), new TotemUseSound()); + $this->getWorld()->addSound($this->location->add(0, $this->eyeHeight, 0), new TotemUseSound()); $hand = $this->inventory->getItemInHand(); if($hand instanceof Totem){ @@ -412,10 +412,10 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $pk->uuid = $this->getUniqueId(); $pk->username = $this->getName(); $pk->entityRuntimeId = $this->getId(); - $pk->position = $this->asVector3(); + $pk->position = $this->location->asVector3(); $pk->motion = $this->getMotion(); - $pk->yaw = $this->yaw; - $pk->pitch = $this->pitch; + $pk->yaw = $this->location->yaw; + $pk->pitch = $this->location->pitch; $pk->item = $this->getInventory()->getItemInHand(); $pk->metadata = $this->getSyncedNetworkData(false); $player->sendDataPacket($pk); diff --git a/src/entity/Living.php b/src/entity/Living.php index 7770bd5f3..269f242a7 100644 --- a/src/entity/Living.php +++ b/src/entity/Living.php @@ -380,7 +380,7 @@ abstract class Living extends Entity{ private function damageItem(Durable $item, int $durabilityRemoved) : void{ $item->applyDamage($durabilityRemoved); if($item->isBroken()){ - $this->world->addSound($this, new ItemBreakSound()); + $this->getWorld()->addSound($this->location, new ItemBreakSound()); } } @@ -434,11 +434,11 @@ abstract class Living extends Entity{ $source->getCause() === EntityDamageEvent::CAUSE_PROJECTILE or $source->getCause() === EntityDamageEvent::CAUSE_ENTITY_ATTACK ) and $e->isOnFire()){ - $this->setOnFire(2 * $this->world->getDifficulty()); + $this->setOnFire(2 * $this->getWorld()->getDifficulty()); } - $deltaX = $this->x - $e->x; - $deltaZ = $this->z - $e->z; + $deltaX = $this->location->x - $e->location->x; + $deltaZ = $this->location->z - $e->location->z; $this->knockBack($deltaX, $deltaZ, $source->getKnockBack()); } } @@ -482,11 +482,11 @@ abstract class Living extends Entity{ $ev = new EntityDeathEvent($this, $this->getDrops(), $this->getXpDropAmount()); $ev->call(); foreach($ev->getDrops() as $item){ - $this->getWorld()->dropItem($this, $item); + $this->getWorld()->dropItem($this->location, $item); } //TODO: check death conditions (must have been damaged by player < 5 seconds from death) - $this->world->dropExperience($this, $ev->getXpDropAmount()); + $this->getWorld()->dropExperience($this->location, $ev->getXpDropAmount()); $this->startDeathAnimation(); } @@ -684,8 +684,8 @@ abstract class Living extends Entity{ $blocks = []; $nextIndex = 0; - foreach(VoxelRayTrace::inDirection($this->add(0, $this->eyeHeight, 0), $this->getDirectionVector(), $maxDistance) as $vector3){ - $block = $this->world->getBlockAt($vector3->x, $vector3->y, $vector3->z); + foreach(VoxelRayTrace::inDirection($this->location->add(0, $this->eyeHeight, 0), $this->getDirectionVector(), $maxDistance) as $vector3){ + $block = $this->getWorld()->getBlockAt($vector3->x, $vector3->y, $vector3->z); $blocks[$nextIndex++] = $block; if($maxLength !== 0 and count($blocks) > $maxLength){ @@ -731,15 +731,15 @@ abstract class Living extends Entity{ * @param Vector3 $target */ public function lookAt(Vector3 $target) : void{ - $horizontal = sqrt(($target->x - $this->x) ** 2 + ($target->z - $this->z) ** 2); - $vertical = $target->y - $this->y; - $this->pitch = -atan2($vertical, $horizontal) / M_PI * 180; //negative is up, positive is down + $horizontal = sqrt(($target->x - $this->location->x) ** 2 + ($target->z - $this->location->z) ** 2); + $vertical = $target->y - $this->location->y; + $this->location->pitch = -atan2($vertical, $horizontal) / M_PI * 180; //negative is up, positive is down - $xDist = $target->x - $this->x; - $zDist = $target->z - $this->z; - $this->yaw = atan2($zDist, $xDist) / M_PI * 180 - 90; - if($this->yaw < 0){ - $this->yaw += 360.0; + $xDist = $target->x - $this->location->x; + $zDist = $target->z - $this->location->z; + $this->location->yaw = atan2($zDist, $xDist) / M_PI * 180 - 90; + if($this->location->yaw < 0){ + $this->location->yaw += 360.0; } } diff --git a/src/entity/Squid.php b/src/entity/Squid.php index d2e5cc00e..e428868c9 100644 --- a/src/entity/Squid.php +++ b/src/entity/Squid.php @@ -66,7 +66,7 @@ class Squid extends WaterAnimal{ $this->swimSpeed = mt_rand(150, 350) / 2000; $e = $source->getDamager(); if($e !== null){ - $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); + $this->swimDirection = $this->location->subtract($e->location)->normalize(); } $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); @@ -94,7 +94,7 @@ class Squid extends WaterAnimal{ if($this->isAlive()){ - if($this->y > 62 and $this->swimDirection !== null){ + if($this->location->y > 62 and $this->swimDirection !== null){ $this->swimDirection->y = -0.5; } @@ -112,8 +112,8 @@ class Squid extends WaterAnimal{ } $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); - $this->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); - $this->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); + $this->location->yaw = (-atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->location->pitch = (-atan2($f, $this->motion->y) * 180 / M_PI); } return $hasUpdate; diff --git a/src/entity/object/ExperienceOrb.php b/src/entity/object/ExperienceOrb.php index 391a3351f..0fce9180d 100644 --- a/src/entity/object/ExperienceOrb.php +++ b/src/entity/object/ExperienceOrb.php @@ -156,7 +156,7 @@ class ExperienceOrb extends Entity{ return null; } - $entity = $this->world->getEntity($this->targetPlayerRuntimeId); + $entity = $this->getWorld()->getEntity($this->targetPlayerRuntimeId); if($entity instanceof Human){ return $entity; } @@ -178,13 +178,13 @@ class ExperienceOrb extends Entity{ } $currentTarget = $this->getTargetPlayer(); - if($currentTarget !== null and (!$currentTarget->isAlive() or $currentTarget->distanceSquared($this) > self::MAX_TARGET_DISTANCE ** 2)){ + if($currentTarget !== null and (!$currentTarget->isAlive() or $currentTarget->location->distanceSquared($this->location) > self::MAX_TARGET_DISTANCE ** 2)){ $currentTarget = null; } if($this->lookForTargetTime >= 20){ if($currentTarget === null){ - $newTarget = $this->world->getNearestEntity($this, self::MAX_TARGET_DISTANCE, Human::class); + $newTarget = $this->getWorld()->getNearestEntity($this->location, self::MAX_TARGET_DISTANCE, Human::class); if($newTarget instanceof Human and !($newTarget instanceof Player and $newTarget->isSpectator())){ $currentTarget = $newTarget; @@ -199,7 +199,7 @@ class ExperienceOrb extends Entity{ $this->setTargetPlayer($currentTarget); if($currentTarget !== null){ - $vector = $currentTarget->add(0, $currentTarget->getEyeHeight() / 2, 0)->subtract($this)->divide(self::MAX_TARGET_DISTANCE); + $vector = $currentTarget->getPosition()->add(0, $currentTarget->getEyeHeight() / 2, 0)->subtract($this)->divide(self::MAX_TARGET_DISTANCE); $distance = $vector->lengthSquared(); if($distance < 1){ @@ -221,7 +221,7 @@ class ExperienceOrb extends Entity{ } protected function tryChangeMovement() : void{ - $this->checkObstruction($this->x, $this->y, $this->z); + $this->checkObstruction($this->location->x, $this->location->y, $this->location->z); parent::tryChangeMovement(); } diff --git a/src/entity/object/FallingBlock.php b/src/entity/object/FallingBlock.php index 4fad1c482..fe23efbcf 100644 --- a/src/entity/object/FallingBlock.php +++ b/src/entity/object/FallingBlock.php @@ -96,9 +96,10 @@ class FallingBlock extends Entity{ $hasUpdate = parent::entityBaseTick($tickDiff); if(!$this->isFlaggedForDespawn()){ - $pos = $this->add(-$this->width / 2, $this->height, -$this->width / 2)->floor(); + $world = $this->getWorld(); + $pos = $this->location->add(-$this->width / 2, $this->height, -$this->width / 2)->floor(); - $this->block->position($this->world, $pos->x, $pos->y, $pos->z); + $this->block->position($world, $pos->x, $pos->y, $pos->z); $blockTarget = null; if($this->block instanceof Fallable){ @@ -108,15 +109,15 @@ class FallingBlock extends Entity{ if($this->onGround or $blockTarget !== null){ $this->flagForDespawn(); - $block = $this->world->getBlock($pos); - if(($block->isTransparent() and !$block->canBeReplaced()) or !$this->world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ()) or ($this->onGround and abs($this->y - $this->getFloorY()) > 0.001)){ + $block = $world->getBlock($pos); + if(($block->isTransparent() and !$block->canBeReplaced()) or !$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ()) or ($this->onGround and abs($this->location->y - $this->location->getFloorY()) > 0.001)){ //FIXME: anvils are supposed to destroy torches - $this->getWorld()->dropItem($this, $this->block->asItem()); + $world->dropItem($this->location, $this->block->asItem()); }else{ $ev = new EntityBlockChangeEvent($this, $block, $blockTarget ?? $this->block); $ev->call(); if(!$ev->isCancelled()){ - $this->getWorld()->setBlock($pos, $ev->getTo()); + $world->setBlock($pos, $ev->getTo()); } } $hasUpdate = true; diff --git a/src/entity/object/ItemEntity.php b/src/entity/object/ItemEntity.php index 421db601a..2cda0ca32 100644 --- a/src/entity/object/ItemEntity.php +++ b/src/entity/object/ItemEntity.php @@ -125,7 +125,7 @@ class ItemEntity extends Entity{ } protected function tryChangeMovement() : void{ - $this->checkObstruction($this->x, $this->y, $this->z); + $this->checkObstruction($this->location->x, $this->location->y, $this->location->z); parent::tryChangeMovement(); } @@ -235,7 +235,7 @@ class ItemEntity extends Entity{ protected function sendSpawnPacket(Player $player) : void{ $pk = new AddItemActorPacket(); $pk->entityRuntimeId = $this->getId(); - $pk->position = $this->asVector3(); + $pk->position = $this->location->asVector3(); $pk->motion = $this->getMotion(); $pk->item = $this->getItem(); $pk->metadata = $this->getSyncedNetworkData(false); diff --git a/src/entity/object/Painting.php b/src/entity/object/Painting.php index 01a07d9f6..8e96e3982 100644 --- a/src/entity/object/Painting.php +++ b/src/entity/object/Painting.php @@ -118,9 +118,9 @@ class Painting extends Entity{ if($drops){ //non-living entities don't have a way to create drops generically yet - $this->world->dropItem($this, VanillaItems::PAINTING()); + $this->getWorld()->dropItem($this->location, VanillaItems::PAINTING()); } - $this->world->addParticle($this->add(0.5, 0.5, 0.5), new DestroyBlockParticle(VanillaBlocks::OAK_PLANKS())); + $this->getWorld()->addParticle($this->location->add(0.5, 0.5, 0.5), new DestroyBlockParticle(VanillaBlocks::OAK_PLANKS())); } protected function recalculateBoundingBox() : void{ @@ -131,7 +131,7 @@ class Painting extends Entity{ public function onNearbyBlockChange() : void{ parent::onNearbyBlockChange(); - if(!self::canFit($this->world, $this->blockIn->getSide($this->facing), $this->facing, false, $this->getMotive())){ + if(!self::canFit($this->getWorld(), $this->blockIn->getSide($this->facing), $this->facing, false, $this->getMotive())){ $this->kill(); } } diff --git a/src/entity/object/PrimedTNT.php b/src/entity/object/PrimedTNT.php index 6375dd3ba..09cc70861 100644 --- a/src/entity/object/PrimedTNT.php +++ b/src/entity/object/PrimedTNT.php @@ -62,7 +62,7 @@ class PrimedTNT extends Entity implements Explosive{ $this->fuse = $nbt->getShort("Fuse", 80, true); - $this->world->addSound($this, new IgniteSound()); + $this->getWorld()->addSound($this->location, new IgniteSound()); } @@ -100,7 +100,7 @@ class PrimedTNT extends Entity implements Explosive{ $ev = new ExplosionPrimeEvent($this, 4); $ev->call(); if(!$ev->isCancelled()){ - $explosion = new Explosion(Position::fromObject($this->add(0, $this->height / 2, 0), $this->world), $ev->getForce(), $this); + $explosion = new Explosion(Position::fromObject($this->location->add(0, $this->height / 2, 0), $this->getWorld()), $ev->getForce(), $this); if($ev->isBlockBreaking()){ $explosion->explodeA(); } diff --git a/src/entity/projectile/Arrow.php b/src/entity/projectile/Arrow.php index 496670382..01478eacd 100644 --- a/src/entity/projectile/Arrow.php +++ b/src/entity/projectile/Arrow.php @@ -142,7 +142,7 @@ class Arrow extends Projectile{ protected function onHit(ProjectileHitEvent $event) : void{ $this->setCritical(false); - $this->world->addSound($this, new ArrowHitSound()); + $this->getWorld()->addSound($this->location, new ArrowHitSound()); } protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{ diff --git a/src/entity/projectile/Egg.php b/src/entity/projectile/Egg.php index 367dc2e7b..d16f11d9c 100644 --- a/src/entity/projectile/Egg.php +++ b/src/entity/projectile/Egg.php @@ -35,7 +35,7 @@ class Egg extends Throwable{ protected function onHit(ProjectileHitEvent $event) : void{ for($i = 0; $i < 6; ++$i){ - $this->world->addParticle($this, new ItemBreakParticle(VanillaItems::EGG())); + $this->getWorld()->addParticle($this->location, new ItemBreakParticle(VanillaItems::EGG())); } } } diff --git a/src/entity/projectile/EnderPearl.php b/src/entity/projectile/EnderPearl.php index e13cbddc6..536cbbdd6 100644 --- a/src/entity/projectile/EnderPearl.php +++ b/src/entity/projectile/EnderPearl.php @@ -33,6 +33,7 @@ use pocketmine\math\Vector3; use pocketmine\network\mcpe\protocol\types\entity\EntityLegacyIds; use pocketmine\world\particle\EndermanTeleportParticle; use pocketmine\world\sound\EndermanTeleportSound; +use function get_class; class EnderPearl extends Throwable{ public const NETWORK_ID = EntityLegacyIds::ENDER_PEARL; @@ -53,10 +54,10 @@ class EnderPearl extends Throwable{ //TODO: check end gateways (when they are added) //TODO: spawn endermites at origin - $this->world->addParticle($owner, new EndermanTeleportParticle()); - $this->world->addSound($owner, new EndermanTeleportSound()); + $this->getWorld()->addParticle($origin = $owner->getPosition(), new EndermanTeleportParticle()); + $this->getWorld()->addSound($origin, new EndermanTeleportSound()); $owner->teleport($target = $event->getRayTraceResult()->getHitVector()); - $this->world->addSound($target, new EndermanTeleportSound()); + $this->getWorld()->addSound($target, new EndermanTeleportSound()); $owner->attack(new EntityDamageEvent($owner, EntityDamageEvent::CAUSE_FALL, 5)); } diff --git a/src/entity/projectile/ExperienceBottle.php b/src/entity/projectile/ExperienceBottle.php index 95c0a9465..fbb3666bf 100644 --- a/src/entity/projectile/ExperienceBottle.php +++ b/src/entity/projectile/ExperienceBottle.php @@ -39,9 +39,9 @@ class ExperienceBottle extends Throwable{ } public function onHit(ProjectileHitEvent $event) : void{ - $this->world->addParticle($this, new PotionSplashParticle(PotionSplashParticle::DEFAULT_COLOR())); - $this->world->addSound($this, new PotionSplashSound()); + $this->getWorld()->addParticle($this->location, new PotionSplashParticle(PotionSplashParticle::DEFAULT_COLOR())); + $this->getWorld()->addSound($this->location, new PotionSplashSound()); - $this->world->dropExperience($this, mt_rand(3, 11)); + $this->getWorld()->dropExperience($this->location, mt_rand(3, 11)); } } diff --git a/src/entity/projectile/Projectile.php b/src/entity/projectile/Projectile.php index 72eaa7db0..52376fbc1 100644 --- a/src/entity/projectile/Projectile.php +++ b/src/entity/projectile/Projectile.php @@ -84,7 +84,7 @@ abstract class Projectile extends Entity{ $blockData = null; if($nbt->hasTag("tileX", IntTag::class) and $nbt->hasTag("tileY", IntTag::class) and $nbt->hasTag("tileZ", IntTag::class)){ - $blockPos = new Position($nbt->getInt("tileX"), $nbt->getInt("tileY"), $nbt->getInt("tileZ"), $this->world); + $blockPos = new Position($nbt->getInt("tileX"), $nbt->getInt("tileY"), $nbt->getInt("tileZ"), $this->getWorld()); }else{ break; } @@ -164,7 +164,7 @@ abstract class Projectile extends Entity{ } public function onNearbyBlockChange() : void{ - if($this->blockHit !== null and $this->world->isInLoadedTerrain($this->blockHit->getPos()) and !$this->blockHit->isSameState($this->world->getBlock($this->blockHit->getPos()))){ + if($this->blockHit !== null and $this->getWorld()->isInLoadedTerrain($this->blockHit->getPos()) and !$this->blockHit->isSameState($this->getWorld()->getBlock($this->blockHit->getPos()))){ $this->blockHit = null; } @@ -180,7 +180,7 @@ abstract class Projectile extends Entity{ Timings::$entityMoveTimer->startTiming(); - $start = $this->asVector3(); + $start = $this->location->asVector3(); $end = $start->add($this->motion); $blockHit = null; @@ -188,7 +188,7 @@ abstract class Projectile extends Entity{ $hitResult = null; foreach(VoxelRayTrace::betweenPoints($start, $end) as $vector3){ - $block = $this->world->getBlockAt($vector3->x, $vector3->y, $vector3->z); + $block = $this->getWorld()->getBlockAt($vector3->x, $vector3->y, $vector3->z); $blockHitResult = $this->calculateInterceptWithBlock($block, $start, $end); if($blockHitResult !== null){ @@ -202,7 +202,7 @@ abstract class Projectile extends Entity{ $entityDistance = PHP_INT_MAX; $newDiff = $end->subtract($start); - foreach($this->world->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){ + foreach($this->getWorld()->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){ if($entity->getId() === $this->getOwningEntityId() and $this->ticksLived < 5){ continue; } @@ -214,7 +214,7 @@ abstract class Projectile extends Entity{ continue; } - $distance = $this->distanceSquared($entityHitResult->hitVector); + $distance = $this->location->distanceSquared($entityHitResult->hitVector); if($distance < $entityDistance){ $entityDistance = $distance; @@ -224,9 +224,9 @@ abstract class Projectile extends Entity{ } } - $this->x = $end->x; - $this->y = $end->y; - $this->z = $end->z; + $this->location->x = $end->x; + $this->location->y = $end->y; + $this->location->z = $end->z; $this->recalculateBoundingBox(); if($hitResult !== null){ @@ -259,8 +259,8 @@ abstract class Projectile extends Entity{ //recompute angles... $f = sqrt(($this->motion->x ** 2) + ($this->motion->z ** 2)); - $this->yaw = (atan2($this->motion->x, $this->motion->z) * 180 / M_PI); - $this->pitch = (atan2($this->motion->y, $f) * 180 / M_PI); + $this->location->yaw = (atan2($this->motion->x, $this->motion->z) * 180 / M_PI); + $this->location->pitch = (atan2($this->motion->y, $f) * 180 / M_PI); } $this->checkChunks(); diff --git a/src/entity/projectile/Snowball.php b/src/entity/projectile/Snowball.php index 6e7d09084..88fcc4223 100644 --- a/src/entity/projectile/Snowball.php +++ b/src/entity/projectile/Snowball.php @@ -32,7 +32,7 @@ class Snowball extends Throwable{ protected function onHit(ProjectileHitEvent $event) : void{ for($i = 0; $i < 6; ++$i){ - $this->world->addParticle($this, new SnowballPoofParticle()); + $this->getWorld()->addParticle($this->location, new SnowballPoofParticle()); } } } diff --git a/src/entity/projectile/SplashPotion.php b/src/entity/projectile/SplashPotion.php index 53b892670..2b4012346 100644 --- a/src/entity/projectile/SplashPotion.php +++ b/src/entity/projectile/SplashPotion.php @@ -89,14 +89,14 @@ class SplashPotion extends Throwable{ $particle = new PotionSplashParticle(Color::mix(...$colors)); } - $this->world->addParticle($this, $particle); - $this->world->addSound($this, new PotionSplashSound()); + $this->getWorld()->addParticle($this->location, $particle); + $this->getWorld()->addSound($this->location, new PotionSplashSound()); if($hasEffects){ if(!$this->willLinger()){ - foreach($this->world->getNearbyEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){ + foreach($this->getWorld()->getNearbyEntities($this->boundingBox->expandedCopy(4.125, 2.125, 4.125), $this) as $entity){ if($entity instanceof Living and $entity->isAlive()){ - $distanceSquared = $entity->getEyePos()->distanceSquared($this); + $distanceSquared = $entity->getEyePos()->distanceSquared($this->location); if($distanceSquared > 16){ //4 blocks continue; } @@ -129,11 +129,11 @@ class SplashPotion extends Throwable{ $blockIn = $event->getBlockHit()->getSide($event->getRayTraceResult()->getHitFace()); if($blockIn->getId() === BlockLegacyIds::FIRE){ - $this->world->setBlock($blockIn->getPos(), VanillaBlocks::AIR()); + $this->getWorld()->setBlock($blockIn->getPos(), VanillaBlocks::AIR()); } foreach($blockIn->getHorizontalSides() as $horizontalSide){ if($horizontalSide->getId() === BlockLegacyIds::FIRE){ - $this->world->setBlock($horizontalSide->getPos(), VanillaBlocks::AIR()); + $this->getWorld()->setBlock($horizontalSide->getPos(), VanillaBlocks::AIR()); } } } diff --git a/src/item/Bow.php b/src/item/Bow.php index 9aabc9a87..ec1b7e9e7 100644 --- a/src/item/Bow.php +++ b/src/item/Bow.php @@ -50,11 +50,12 @@ class Bow extends Tool{ return ItemUseResult::FAIL(); } + $location = $player->getLocation(); $nbt = EntityFactory::createBaseNBT( $player->getEyePos(), $player->getDirectionVector(), - ($player->yaw > 180 ? 360 : 0) - $player->yaw, - -$player->pitch + ($location->yaw > 180 ? 360 : 0) - $location->yaw, + -$location->pitch ); $nbt->setShort("Fire", $player->isOnFire() ? 45 * 60 : 0); @@ -63,7 +64,7 @@ class Bow extends Tool{ $baseForce = min((($p ** 2) + $p * 2) / 3, 1); /** @var ArrowEntity $entity */ - $entity = EntityFactory::create(ArrowEntity::class, $player->getWorld(), $nbt, $player, $baseForce >= 1); + $entity = EntityFactory::create(ArrowEntity::class, $location->getWorld(), $nbt, $player, $baseForce >= 1); $infinity = $this->hasEnchantment(Enchantment::INFINITY()); if($infinity){ @@ -104,7 +105,7 @@ class Bow extends Tool{ } $ev->getProjectile()->spawnToAll(); - $player->getWorld()->addSound($player, new BowShootSound()); + $location->getWorld()->addSound($location, new BowShootSound()); }else{ $entity->spawnToAll(); } diff --git a/src/item/ChorusFruit.php b/src/item/ChorusFruit.php index 72a8b987b..5bca29208 100644 --- a/src/item/ChorusFruit.php +++ b/src/item/ChorusFruit.php @@ -49,9 +49,10 @@ class ChorusFruit extends Food{ $world = $consumer->getWorld(); assert($world !== null); - $minX = $consumer->getFloorX() - 8; - $minY = min($consumer->getFloorY(), $consumer->getWorld()->getWorldHeight()) - 8; - $minZ = $consumer->getFloorZ() - 8; + $origin = $consumer->getPosition(); + $minX = $origin->getFloorX() - 8; + $minY = min($origin->getFloorY(), $consumer->getWorld()->getWorldHeight()) - 8; + $minZ = $origin->getFloorZ() - 8; $maxX = $minX + 16; $maxY = $minY + 16; @@ -76,7 +77,7 @@ class ChorusFruit extends Food{ } //Sounds are broadcasted at both source and destination - $world->addSound($consumer->asVector3(), new EndermanTeleportSound()); + $world->addSound($origin, new EndermanTeleportSound()); $consumer->teleport($target = new Vector3($x + 0.5, $y + 1, $z + 0.5)); $world->addSound($target, new EndermanTeleportSound()); diff --git a/src/item/ProjectileItem.php b/src/item/ProjectileItem.php index ecbc0fdc6..cd3461bd1 100644 --- a/src/item/ProjectileItem.php +++ b/src/item/ProjectileItem.php @@ -53,14 +53,15 @@ abstract class ProjectileItem extends Item{ } public function onClickAir(Player $player, Vector3 $directionVector) : ItemUseResult{ - $nbt = EntityFactory::createBaseNBT($player->getEyePos(), $directionVector, $player->yaw, $player->pitch); + $location = $player->getLocation(); + $nbt = EntityFactory::createBaseNBT($player->getEyePos(), $directionVector, $location->yaw, $location->pitch); $this->addExtraTags($nbt); $class = $this->getProjectileEntityClass(); Utils::testValidInstance($class, Throwable::class); /** @var Throwable $projectile */ - $projectile = EntityFactory::create($class, $player->getWorld(), $nbt, $player); + $projectile = EntityFactory::create($class, $location->getWorld(), $nbt, $player); $projectile->setMotion($projectile->getMotion()->multiply($this->getThrowForce())); $projectileEv = new ProjectileLaunchEvent($projectile); @@ -72,7 +73,7 @@ abstract class ProjectileItem extends Item{ $projectile->spawnToAll(); - $player->getWorld()->addSound($player, new ThrowSound()); + $location->getWorld()->addSound($location, new ThrowSound()); $this->pop(); diff --git a/src/item/enchantment/KnockbackEnchantment.php b/src/item/enchantment/KnockbackEnchantment.php index da274a409..d50470003 100644 --- a/src/item/enchantment/KnockbackEnchantment.php +++ b/src/item/enchantment/KnockbackEnchantment.php @@ -38,7 +38,8 @@ class KnockbackEnchantment extends MeleeWeaponEnchantment{ public function onPostAttack(Entity $attacker, Entity $victim, int $enchantmentLevel) : void{ if($victim instanceof Living){ - $victim->knockBack($victim->x - $attacker->x, $victim->z - $attacker->z, $enchantmentLevel * 0.5); + $diff = $victim->getPosition()->subtract($attacker->getPosition()); + $victim->knockBack($diff->x, $diff->z, $enchantmentLevel * 0.5); } } } diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 7d94ffe76..8c983df52 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -623,8 +623,9 @@ class NetworkSession{ } public function syncMovement(Vector3 $pos, ?float $yaw = null, ?float $pitch = null, int $mode = MovePlayerPacket::MODE_NORMAL) : void{ - $yaw = $yaw ?? $this->player->getYaw(); - $pitch = $pitch ?? $this->player->getPitch(); + $location = $this->player->getLocation(); + $yaw = $yaw ?? $location->getYaw(); + $pitch = $pitch ?? $location->getPitch(); $pk = new MovePlayerPacket(); $pk->entityRuntimeId = $this->player->getId(); @@ -767,7 +768,7 @@ class NetworkSession{ public function startUsingChunk(int $chunkX, int $chunkZ, \Closure $onCompletion) : void{ Utils::validateCallableSignature(function(int $chunkX, int $chunkZ){}, $onCompletion); - $world = $this->player->getWorld(); + $world = $this->player->getLocation()->getWorld(); assert($world !== null); ChunkCache::getInstance($world)->request($chunkX, $chunkZ)->onResolve( @@ -776,16 +777,17 @@ class NetworkSession{ if(!$this->isConnected()){ return; } - if($world !== $this->player->getWorld() or !$this->player->isUsingChunk($chunkX, $chunkZ)){ + $currentWorld = $this->player->getLocation()->getWorld(); + if($world !== $currentWorld or !$this->player->isUsingChunk($chunkX, $chunkZ)){ $this->logger->debug("Tried to send no-longer-active chunk $chunkX $chunkZ in world " . $world->getFolderName()); return; } - $this->player->world->timings->syncChunkSendTimer->startTiming(); + $currentWorld->timings->syncChunkSendTimer->startTiming(); try{ $this->queueCompressed($promise); $onCompletion($chunkX, $chunkZ); }finally{ - $this->player->world->timings->syncChunkSendTimer->stopTiming(); + $currentWorld->timings->syncChunkSendTimer->stopTiming(); } } ); diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 62d2660bb..774bc4d1e 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -301,7 +301,7 @@ class InGamePacketHandler extends PacketHandler{ */ private function onFailedBlockAction(Vector3 $blockPos, ?int $face) : void{ $this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex()); - if($blockPos->distanceSquared($this->player) < 10000){ + if($blockPos->distanceSquared($this->player->getLocation()) < 10000){ $blocks = $blockPos->sidesArray(); if($face !== null){ $sidePos = $blockPos->getSide($face); @@ -311,7 +311,7 @@ class InGamePacketHandler extends PacketHandler{ }else{ $blocks[] = $blockPos; } - $this->player->getWorld()->sendBlocks([$this->player], $blocks); + $this->player->getLocation()->getWorld()->sendBlocks([$this->player], $blocks); } } @@ -510,11 +510,11 @@ class InGamePacketHandler extends PacketHandler{ public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ $pos = new Vector3($packet->x, $packet->y, $packet->z); - if($pos->distanceSquared($this->player) > 10000){ + if($pos->distanceSquared($this->player->getLocation()) > 10000){ return false; } - $block = $this->player->getWorld()->getBlock($pos); + $block = $this->player->getLocation()->getWorld()->getBlock($pos); try{ $offset = 0; $nbt = (new NetworkNbtSerializer())->read($packet->namedtag, $offset, 512)->getTag(); @@ -703,7 +703,7 @@ class InGamePacketHandler extends PacketHandler{ } public function handleLevelSoundEvent(LevelSoundEventPacket $packet) : bool{ - $this->player->getWorld()->broadcastPacketToViewers($this->player->asVector3(), $packet); + $this->player->getWorld()->broadcastPacketToViewers($this->player->getPosition(), $packet); return true; } diff --git a/src/network/mcpe/handler/PreSpawnPacketHandler.php b/src/network/mcpe/handler/PreSpawnPacketHandler.php index b643f00d9..f6a76867e 100644 --- a/src/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/network/mcpe/handler/PreSpawnPacketHandler.php @@ -53,23 +53,24 @@ class PreSpawnPacketHandler extends PacketHandler{ public function setUp() : void{ $spawnPosition = $this->player->getSpawn(); + $location = $this->player->getLocation(); $pk = new StartGamePacket(); $pk->entityUniqueId = $this->player->getId(); $pk->entityRuntimeId = $this->player->getId(); $pk->playerGamemode = NetworkSession::getClientFriendlyGamemode($this->player->getGamemode()); - $pk->playerPosition = $this->player->getOffsetPosition($this->player); - $pk->pitch = $this->player->pitch; - $pk->yaw = $this->player->yaw; + $pk->playerPosition = $this->player->getOffsetPosition($location); + $pk->pitch = $location->pitch; + $pk->yaw = $location->yaw; $pk->seed = -1; $pk->dimension = DimensionIds::OVERWORLD; //TODO: implement this properly $pk->worldGamemode = NetworkSession::getClientFriendlyGamemode($this->server->getGamemode()); - $pk->difficulty = $this->player->getWorld()->getDifficulty(); + $pk->difficulty = $location->getWorld()->getDifficulty(); $pk->spawnX = $spawnPosition->getFloorX(); $pk->spawnY = $spawnPosition->getFloorY(); $pk->spawnZ = $spawnPosition->getFloorZ(); $pk->hasAchievementsDisabled = true; - $pk->time = $this->player->getWorld()->getTime(); + $pk->time = $location->getWorld()->getTime(); $pk->eduMode = false; $pk->rainLevel = 0; //TODO: implement these properly $pk->lightningLevel = 0; diff --git a/src/player/Player.php b/src/player/Player.php index ed8380d44..566118ea6 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -329,10 +329,10 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->networkSession->getIp(), $this->networkSession->getPort(), $this->id, - $this->world->getDisplayName(), - round($this->x, 4), - round($this->y, 4), - round($this->z, 4) + $this->getWorld()->getDisplayName(), + round($this->location->x, 4), + round($this->location->y, 4), + round($this->location->z, 4) ])); $this->server->addOnlinePlayer($this); @@ -368,7 +368,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, if(($world = $this->server->getWorldManager()->getWorldByName($nbt->getString("SpawnLevel", ""))) instanceof World){ $this->spawnPosition = new Position($nbt->getInt("SpawnX"), $nbt->getInt("SpawnY"), $nbt->getInt("SpawnZ"), $world); }else{ - $this->spawnPosition = $this->world->getSafeSpawn(); + $this->spawnPosition = $this->getWorld()->getSafeSpawn(); } } } @@ -514,7 +514,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * @param Player $player */ public function spawnTo(Player $player) : void{ - if($this->isAlive() and $player->isAlive() and $player->getWorld() === $this->world and $player->canSee($this) and !$this->isSpectator()){ + if($this->isAlive() and $player->isAlive() and $player->getWorld() === $this->getWorld() and $player->canSee($this) and !$this->isSpectator()){ parent::spawnTo($player); } } @@ -802,7 +802,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } protected function switchWorld(World $targetWorld) : bool{ - $oldWorld = $this->world; + $oldWorld = $this->getWorld(); if(parent::switchWorld($targetWorld)){ if($oldWorld !== null){ foreach($this->usedChunks as $index => $d){ @@ -813,8 +813,8 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->usedChunks = []; $this->loadQueue = []; - $this->world->sendTime($this); - $this->world->sendDifficulty($this); + $this->getWorld()->sendTime($this); + $this->getWorld()->sendDifficulty($this); return true; } @@ -823,7 +823,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } protected function unloadChunk(int $x, int $z, ?World $world = null){ - $world = $world ?? $this->world; + $world = $world ?? $this->getWorld(); $index = World::chunkHash($x, $z); if(isset($this->usedChunks[$index])){ foreach($world->getChunk($x, $z)->getEntities() as $entity){ @@ -840,7 +840,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } protected function spawnEntitiesOnChunk(int $chunkX, int $chunkZ) : void{ - foreach($this->world->getChunk($chunkX, $chunkZ)->getEntities() as $entity){ + foreach($this->getWorld()->getChunk($chunkX, $chunkZ)->getEntities() as $entity){ if($entity !== $this and !$entity->isFlaggedForDespawn()){ $entity->spawnTo($this); } @@ -868,10 +868,10 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, ++$count; $this->usedChunks[$index] = false; - $this->world->registerChunkLoader($this, $X, $Z, true); - $this->world->registerChunkListener($this, $X, $Z); + $this->getWorld()->registerChunkLoader($this, $X, $Z, true); + $this->getWorld()->registerChunkListener($this, $X, $Z); - if(!$this->world->populateChunk($X, $Z)){ + if(!$this->getWorld()->populateChunk($X, $Z)){ continue; } @@ -935,8 +935,8 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $radius = $this->server->getAllowedViewDistance($this->viewDistance); $radiusSquared = $radius ** 2; - $centerX = $this->getFloorX() >> 4; - $centerZ = $this->getFloorZ() >> 4; + $centerX = $this->location->getFloorX() >> 4; + $centerZ = $this->location->getFloorZ() >> 4; for($x = 0; $x < $radius; ++$x){ for($z = 0; $z <= $x; ++$z){ @@ -993,7 +993,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->loadQueue = $newOrder; if(!empty($this->loadQueue) or !empty($unloadChunks)){ - $this->networkSession->syncViewAreaCenterPoint($this, $this->viewDistance); + $this->networkSession->syncViewAreaCenterPoint($this->location, $this->viewDistance); } Timings::$playerChunkOrderTimer->stopTiming(); @@ -1042,7 +1042,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, */ public function setSpawn(Vector3 $pos){ if(!($pos instanceof Position)){ - $world = $this->world; + $world = $this->getWorld(); }else{ $world = $pos->getWorld(); } @@ -1064,7 +1064,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, */ public function sleepOn(Vector3 $pos) : bool{ $pos = $pos->floor(); - $b = $this->world->getBlock($pos); + $b = $this->getWorld()->getBlock($pos); $ev = new PlayerBedEnterEvent($this, $b); $ev->call(); @@ -1080,14 +1080,14 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->setSpawn($pos); - $this->world->setSleepTicks(60); + $this->getWorld()->setSleepTicks(60); return true; } public function stopSleep(){ if($this->sleeping instanceof Vector3){ - $b = $this->world->getBlock($this->sleeping); + $b = $this->getWorld()->getBlock($this->sleeping); if($b instanceof Bed){ $b->setOccupied(false); } @@ -1095,7 +1095,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->sleeping = null; - $this->world->setSleepTicks(0); + $this->getWorld()->setSleepTicks(0); $this->broadcastAnimation([$this], AnimatePacket::ACTION_STOP_SLEEP); } @@ -1225,10 +1225,10 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, protected function checkGroundState(float $movX, float $movY, float $movZ, float $dx, float $dy, float $dz) : void{ $bb = clone $this->boundingBox; - $bb->minY = $this->y - 0.2; - $bb->maxY = $this->y + 0.2; + $bb->minY = $this->location->y - 0.2; + $bb->maxY = $this->location->y + 0.2; - $this->onGround = $this->isCollided = count($this->world->getCollisionBlocks($bb, true)) > 0; + $this->onGround = $this->isCollided = count($this->getWorld()->getCollisionBlocks($bb, true)) > 0; } public function canBeMovedByCurrents() : bool{ @@ -1236,7 +1236,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } protected function checkNearEntities(){ - foreach($this->world->getNearbyEntities($this->boundingBox->expandedCopy(1, 0.5, 1), $this) as $entity){ + foreach($this->getWorld()->getNearbyEntities($this->boundingBox->expandedCopy(1, 0.5, 1), $this) as $entity){ $entity->scheduleUpdate(); if(!$entity->isAlive() or $entity->isFlaggedForDespawn()){ @@ -1254,7 +1254,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * @return Vector3 */ public function getNextPosition() : Vector3{ - return $this->newPosition !== null ? clone $this->newPosition : $this->asVector3(); + return $this->newPosition !== null ? clone $this->newPosition : $this->location->asVector3(); } /** @@ -1271,9 +1271,9 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, //TODO: teleport acks are a network specific thing and shouldn't be here $newPos = $newPos->asVector3(); - if($this->isTeleporting and $newPos->distanceSquared($this) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks - $this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET); - $this->logger->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $this->asVector3()); + if($this->isTeleporting and $newPos->distanceSquared($this->location) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks + $this->sendPosition($this->location, null, null, MovePlayerPacket::MODE_RESET); + $this->logger->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $this->location->asVector3()); //Still getting movements from before teleport, ignore them return false; } @@ -1296,11 +1296,10 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, return; } - assert($this->x !== null and $this->y !== null and $this->z !== null); assert($this->newPosition->x !== null and $this->newPosition->y !== null and $this->newPosition->z !== null); $newPos = $this->newPosition; - $distanceSquared = $newPos->distanceSquared($this); + $distanceSquared = $newPos->distanceSquared($this->location); $revert = false; @@ -1316,23 +1315,23 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * asking for help if you suffer the consequences of messing with this. */ $this->logger->debug("Moved too fast, reverting movement"); - $this->logger->debug("Old position: " . $this->asVector3() . ", new position: " . $this->newPosition); + $this->logger->debug("Old position: " . $this->location->asVector3() . ", new position: " . $this->newPosition); $revert = true; - }elseif(!$this->world->isInLoadedTerrain($newPos) or !$this->world->isChunkGenerated($newPos->getFloorX() >> 4, $newPos->getFloorZ() >> 4)){ + }elseif(!$this->getWorld()->isInLoadedTerrain($newPos) or !$this->getWorld()->isChunkGenerated($newPos->getFloorX() >> 4, $newPos->getFloorZ() >> 4)){ $revert = true; $this->nextChunkOrderRun = 0; } if(!$revert and $distanceSquared != 0){ - $dx = $newPos->x - $this->x; - $dy = $newPos->y - $this->y; - $dz = $newPos->z - $this->z; + $dx = $newPos->x - $this->location->x; + $dy = $newPos->y - $this->location->y; + $dz = $newPos->z - $this->location->z; $this->move($dx, $dy, $dz); } $from = clone $this->lastLocation; - $to = $this->asLocation(); + $to = clone $this->location; $delta = $to->distanceSquared($from); $deltaAngle = abs($this->lastLocation->yaw - $to->yaw) + abs($this->lastLocation->pitch - $to->pitch); @@ -1631,7 +1630,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } public function pickBlock(Vector3 $pos, bool $addTileNBT) : bool{ - $block = $this->world->getBlock($pos); + $block = $this->getWorld()->getBlock($pos); if($block instanceof UnknownBlock){ return true; } @@ -1678,11 +1677,11 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * @return bool if an action took place successfully */ public function attackBlock(Vector3 $pos, int $face) : bool{ - if($pos->distanceSquared($this) > 10000){ + if($pos->distanceSquared($this->location) > 10000){ return false; //TODO: maybe this should throw an exception instead? } - $target = $this->world->getBlock($pos); + $target = $this->getWorld()->getBlock($pos); $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $face, PlayerInteractEvent::LEFT_CLICK_BLOCK); $ev->call(); @@ -1696,7 +1695,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $block = $target->getSide($face); if($block->getId() === BlockLegacyIds::FIRE){ - $this->world->setBlock($block->getPos(), VanillaBlocks::AIR()); + $this->getWorld()->setBlock($block->getPos(), VanillaBlocks::AIR()); return true; } @@ -1704,7 +1703,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, //TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211) $breakTime = ceil($target->getBreakInfo()->getBreakTime($this->inventory->getItemInHand()) * 20); if($breakTime > 0){ - $this->world->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime)); + $this->getWorld()->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime)); } } @@ -1712,15 +1711,15 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } public function continueBreakBlock(Vector3 $pos, int $face) : void{ - $block = $this->world->getBlock($pos); - $this->world->addParticle($pos, new PunchBlockParticle($block, $face)); + $block = $this->getWorld()->getBlock($pos); + $this->getWorld()->addParticle($pos, new PunchBlockParticle($block, $face)); $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); //TODO: destroy-progress level event } public function stopBreakBlock(Vector3 $pos) : void{ - $this->world->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK); + $this->getWorld()->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK); } /** @@ -1737,7 +1736,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); $item = $this->inventory->getItemInHand(); $oldItem = clone $item; - if($this->world->useBreakOn($pos, $item, $this, true)){ + if($this->getWorld()->useBreakOn($pos, $item, $this, true)){ if($this->hasFiniteResources() and !$item->equalsExact($oldItem)){ $this->inventory->setItemInHand($item); } @@ -1765,7 +1764,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); $item = $this->inventory->getItemInHand(); //this is a copy of the real item $oldItem = clone $item; - if($this->world->useItemOn($pos, $item, $face, $clickOffset, $this, true)){ + if($this->getWorld()->useItemOn($pos, $item, $face, $clickOffset, $this, true)){ if($this->hasFiniteResources() and !$item->equalsExact($oldItem)){ $this->inventory->setItemInHand($item); } @@ -1797,7 +1796,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $heldItem = $this->inventory->getItemInHand(); $ev = new EntityDamageByEntityEvent($this, $entity, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $heldItem->getAttackPoints()); - if(!$this->canInteract($entity, 8) or ($entity instanceof Player and !$this->server->getConfigBool("pvp"))){ + if(!$this->canInteract($entity->getLocation(), 8) or ($entity instanceof Player and !$this->server->getConfigBool("pvp"))){ $ev->setCancelled(); } @@ -1900,7 +1899,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, */ public function dropItem(Item $item) : void{ $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); - $this->world->dropItem($this->add(0, 1.3, 0), $item, $this->getDirectionVector()->multiply(0.4), 40); + $this->getWorld()->dropItem($this->location->add(0, 1.3, 0), $item, $this->getDirectionVector()->multiply(0.4), 40); } /** @@ -2159,7 +2158,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } $this->hiddenPlayers = []; - if($this->isValid()){ + if($this->location->isValid()){ foreach($this->usedChunks as $index => $d){ World::getXZ($index, $chunkX, $chunkZ); $this->unloadChunk($chunkX, $chunkZ); @@ -2221,8 +2220,8 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $nbt = $this->saveNBT(); - if($this->isValid()){ - $nbt->setString("Level", $this->world->getFolderName()); + if($this->location->isValid()){ + $nbt->setString("Level", $this->getWorld()->getFolderName()); } if($this->hasValidSpawnPosition()){ @@ -2261,7 +2260,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, if(!$ev->getKeepInventory()){ foreach($ev->getDrops() as $item){ - $this->world->dropItem($this, $item); + $this->getWorld()->dropItem($this->location, $item); } if($this->inventory !== null){ @@ -2273,7 +2272,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, } } - $this->world->dropExperience($this, $ev->getXpDropAmount()); + $this->getWorld()->dropExperience($this->location, $ev->getXpDropAmount()); $this->xpManager->setXpAndProgress(0, 0.0); if($ev->getDeathMessage() != ""){ @@ -2400,7 +2399,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->removeCurrentWindow(); - $this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_TELEPORT); + $this->sendPosition($this->location, $this->location->yaw, $this->location->pitch, MovePlayerPacket::MODE_TELEPORT); $this->broadcastMovement(true); $this->spawnToAll(); @@ -2543,4 +2542,22 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->nextChunkOrderRun = 0; } } + + /** + * @see ChunkLoader::getX() + * @return float + */ + public function getX(){ + return $this->location->getX(); + } + + /** + * @see ChunkLoader::getZ() + * @return float + */ + public function getZ(){ + return $this->location->getZ(); + } + + } diff --git a/src/world/Explosion.php b/src/world/Explosion.php index aa7df40b2..8a9f57ba9 100644 --- a/src/world/Explosion.php +++ b/src/world/Explosion.php @@ -174,12 +174,14 @@ class Explosion{ $explosionBB = new AxisAlignedBB($minX, $minY, $minZ, $maxX, $maxY, $maxZ); + /** @var Entity[] $list */ $list = $this->world->getNearbyEntities($explosionBB, $this->what instanceof Entity ? $this->what : null); foreach($list as $entity){ - $distance = $entity->distance($this->source) / $explosionSize; + $entityPos = $entity->getPosition(); + $distance = $entityPos->distance($this->source) / $explosionSize; if($distance <= 1){ - $motion = $entity->subtract($this->source)->normalize(); + $motion = $entityPos->subtract($this->source)->normalize(); $impact = (1 - $distance) * ($exposure = 1);