first look at separating Entity and Location

This commit is contained in:
Dylan K. Taylor 2019-08-19 17:20:34 +01:00
parent 591d35889e
commit 2d4a32fc77
36 changed files with 302 additions and 257 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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");

View File

@ -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)]));

View File

@ -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++];

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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{

View File

@ -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()));
}
}
}

View File

@ -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));
}

View File

@ -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));
}
}

View File

@ -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();

View File

@ -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());
}
}
}

View File

@ -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());
}
}
}

View File

@ -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();
}

View File

@ -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());

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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();
}
}
);

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);