Entity: replace separate height/width/eyeHeight fields with an EntitySizeInfo structure

this will make it easier to implement stuff like sleeping (properly), swimming and gliding without needing to duplicate all the fields.
This commit is contained in:
Dylan K. Taylor 2021-01-08 00:10:11 +00:00
parent 574b615b4c
commit e53b57732b
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
15 changed files with 103 additions and 60 deletions

View File

@ -118,13 +118,8 @@ abstract class Entity{
/** @var bool */
public $onGround = false;
/** @var float */
public $eyeHeight = null;
/** @var float */
public $height;
/** @var float */
public $width;
/** @var EntitySizeInfo */
public $size;
/** @var float */
private $health = 20.0;
@ -218,9 +213,7 @@ abstract class Entity{
public function __construct(Location $location, ?CompoundTag $nbt = null){
$this->timings = Timings::getEntityTimings($this);
if($this->eyeHeight === null){
$this->eyeHeight = $this->height / 2 + 0.1;
}
$this->size = $this->getInitialSizeInfo();
$this->id = self::nextRuntimeId();
$this->server = $location->getWorld()->getServer();
@ -259,6 +252,8 @@ abstract class Entity{
}
abstract protected function getInitialSizeInfo() : EntitySizeInfo;
public function getNameTag() : string{
return $this->nameTag;
}
@ -299,11 +294,7 @@ abstract class Entity{
if($value <= 0){
throw new \InvalidArgumentException("Scale must be greater than 0");
}
$multiplier = $value / $this->getScale();
$this->width *= $multiplier;
$this->height *= $multiplier;
$this->eyeHeight *= $multiplier;
$this->size = $this->getInitialSizeInfo()->scale($value);
$this->scale = $value;
@ -315,14 +306,14 @@ abstract class Entity{
}
protected function recalculateBoundingBox() : void{
$halfWidth = $this->width / 2;
$halfWidth = $this->size->getWidth() / 2;
$this->boundingBox = new AxisAlignedBB(
$this->location->x - $halfWidth,
$this->location->y + $this->ySize,
$this->location->z - $halfWidth,
$this->location->x + $halfWidth,
$this->location->y + $this->height + $this->ySize,
$this->location->y + $this->size->getHeight() + $this->ySize,
$this->location->z + $halfWidth
);
}
@ -1042,7 +1033,7 @@ abstract class Entity{
}
public function getEyeHeight() : float{
return $this->eyeHeight;
return $this->size->getEyeHeight();
}
public function getEyePos() : Vector3{
@ -1585,8 +1576,8 @@ abstract class Entity{
protected function syncNetworkData(EntityMetadataCollection $properties) : void{
$properties->setByte(EntityMetadataProperties::ALWAYS_SHOW_NAMETAG, $this->alwaysShowNameTag ? 1 : 0);
$properties->setFloat(EntityMetadataProperties::BOUNDING_BOX_HEIGHT, $this->height);
$properties->setFloat(EntityMetadataProperties::BOUNDING_BOX_WIDTH, $this->width);
$properties->setFloat(EntityMetadataProperties::BOUNDING_BOX_HEIGHT, $this->size->getHeight());
$properties->setFloat(EntityMetadataProperties::BOUNDING_BOX_WIDTH, $this->size->getWidth());
$properties->setFloat(EntityMetadataProperties::SCALE, $this->scale);
$properties->setLong(EntityMetadataProperties::LEAD_HOLDER_EID, -1);
$properties->setLong(EntityMetadataProperties::OWNER_EID, $this->ownerId ?? -1);

View File

@ -0,0 +1,53 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\entity;
final class EntitySizeInfo{
/** @var float */
private $height;
/** @var float */
private $width;
/** @var float */
private $eyeHeight;
public function __construct(float $height, float $width, ?float $eyeHeight = null){
$this->height = $height;
$this->width = $width;
$this->eyeHeight = $eyeHeight ?? min($this->height / 2 + 0.1, $this->height);
}
public function getHeight() : float{ return $this->height; }
public function getWidth() : float{ return $this->width; }
public function getEyeHeight() : float{ return $this->eyeHeight; }
public function scale(float $newScale) : self{
return new self(
$this->height * $newScale,
$this->width * $newScale,
$this->eyeHeight * $newScale
);
}
}

View File

@ -74,10 +74,6 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
/** @var UUID */
protected $uuid;
public $width = 0.6;
public $height = 1.8;
public $eyeHeight = 1.62;
/** @var Skin */
protected $skin;
@ -94,6 +90,8 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
parent::__construct($location, $nbt);
}
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(1.8, 0.6, 1.62); }
/**
* @throws InvalidSkinException
* @throws \UnexpectedValueException

View File

@ -715,7 +715,7 @@ abstract class Living extends Entity{
$blocks = [];
$nextIndex = 0;
foreach(VoxelRayTrace::inDirection($this->location->add(0, $this->eyeHeight, 0), $this->getDirectionVector(), $maxDistance) as $vector3){
foreach(VoxelRayTrace::inDirection($this->location->add(0, $this->size->getEyeHeight(), 0), $this->getDirectionVector(), $maxDistance) as $vector3){
$block = $this->getWorld()->getBlockAt($vector3->x, $vector3->y, $vector3->z);
$blocks[$nextIndex++] = $block;

View File

@ -39,9 +39,6 @@ class Squid extends WaterAnimal{
public static function getNetworkTypeId() : string{ return EntityIds::SQUID; }
public $width = 0.95;
public $height = 0.95;
/** @var Vector3|null */
public $swimDirection = null;
/** @var float */
@ -50,6 +47,8 @@ class Squid extends WaterAnimal{
/** @var int */
private $switchDirectionTicker = 0;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.95, 0.95); }
public function initEntity(CompoundTag $nbt) : void{
$this->setMaxHealth(10);
parent::initEntity($nbt);

View File

@ -38,14 +38,15 @@ class Villager extends Living implements Ageable{
public static function getNetworkTypeId() : string{ return EntityIds::VILLAGER; }
public $width = 0.6;
public $height = 1.8;
/** @var bool */
private $baby = false;
/** @var int */
private $profession = self::PROFESSION_FARMER;
protected function getInitialSizeInfo() : EntitySizeInfo{
return new EntitySizeInfo(1.8, 0.6); //TODO: eye height??
}
public function getName() : string{
return "Villager";
}

View File

@ -31,8 +31,9 @@ class Zombie extends Living{
public static function getNetworkTypeId() : string{ return EntityIds::ZOMBIE; }
public $width = 0.6;
public $height = 1.8;
protected function getInitialSizeInfo() : EntitySizeInfo{
return new EntitySizeInfo(1.8, 0.6); //TODO: eye height ??
}
public function getName() : string{
return "Zombie";

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\entity\object;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Human;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
@ -78,9 +79,6 @@ class ExperienceOrb extends Entity{
return $result;
}
public $height = 0.25;
public $width = 0.25;
public $gravity = 0.04;
public $drag = 0.02;
@ -102,6 +100,8 @@ class ExperienceOrb extends Entity{
/** @var int */
protected $xpValue = 1;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -27,6 +27,7 @@ use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\block\utils\Fallable;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Location;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageEvent;
@ -44,9 +45,6 @@ class FallingBlock extends Entity{
public static function getNetworkTypeId() : string{ return EntityIds::FALLING_BLOCK; }
public $width = 0.98;
public $height = 0.98;
protected $gravity = 0.04;
protected $drag = 0.02;
@ -60,6 +58,8 @@ class FallingBlock extends Entity{
parent::__construct($location, $nbt);
}
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.98, 0.98); }
public static function parseBlockNBT(BlockFactory $factory, CompoundTag $nbt) : Block{
$blockId = 0;
@ -102,7 +102,7 @@ class FallingBlock extends Entity{
if(!$this->isFlaggedForDespawn()){
$world = $this->getWorld();
$pos = $this->location->add(-$this->width / 2, $this->height, -$this->width / 2)->floor();
$pos = $this->location->add(-$this->size->getWidth() / 2, $this->size->getHeight(), -$this->size->getWidth() / 2)->floor();
$this->block->position($world, $pos->x, $pos->y, $pos->z);

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\entity\object;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Location;
use pocketmine\event\entity\ItemDespawnEvent;
use pocketmine\event\entity\ItemSpawnEvent;
@ -54,9 +55,6 @@ class ItemEntity extends Entity{
/** @var Item */
protected $item;
public $width = 0.25;
public $height = 0.25;
protected $gravity = 0.04;
protected $drag = 0.02;
@ -73,6 +71,8 @@ class ItemEntity extends Entity{
parent::__construct($location, $nbt);
}
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -25,6 +25,7 @@ namespace pocketmine\entity\object;
use pocketmine\block\VanillaBlocks;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Location;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\item\VanillaItems;
@ -60,12 +61,6 @@ class Painting extends Entity{
/** @var float */
protected $drag = 1.0;
//these aren't accurate, but it doesn't matter since they aren't used (vanilla PC does something similar)
/** @var float */
public $height = 0.5;
/** @var float */
public $width = 0.5;
/** @var Vector3 */
protected $blockIn;
/** @var int */
@ -80,6 +75,11 @@ class Painting extends Entity{
parent::__construct($location, $nbt);
}
protected function getInitialSizeInfo() : EntitySizeInfo{
//these aren't accurate, but it doesn't matter since they aren't used (vanilla PC does something similar)
return new EntitySizeInfo(0.5, 0.5);
}
protected function initEntity(CompoundTag $nbt) : void{
$this->setMaxHealth(1);
$this->setHealth(1);

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\entity\object;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Explosive;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\ExplosionPrimeEvent;
@ -40,9 +41,6 @@ class PrimedTNT extends Entity implements Explosive{
public static function getNetworkTypeId() : string{ return EntityIds::TNT; }
public $width = 0.98;
public $height = 0.98;
protected $gravity = 0.04;
protected $drag = 0.02;
@ -51,6 +49,8 @@ class PrimedTNT extends Entity implements Explosive{
public $canCollide = false;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.98, 0.98); }
public function getFuse() : int{
return $this->fuse;
}
@ -108,7 +108,7 @@ class PrimedTNT extends Entity implements Explosive{
$ev = new ExplosionPrimeEvent($this, 4);
$ev->call();
if(!$ev->isCancelled()){
$explosion = new Explosion(Position::fromObject($this->location->add(0, $this->height / 2, 0), $this->getWorld()), $ev->getForce(), $this);
$explosion = new Explosion(Position::fromObject($this->location->add(0, $this->size->getHeight() / 2, 0), $this->getWorld()), $ev->getForce(), $this);
if($ev->isBlockBreaking()){
$explosion->explodeA();
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\entity\projectile;
use pocketmine\block\Block;
use pocketmine\entity\animation\ArrowShakeAnimation;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Location;
use pocketmine\event\entity\ProjectileHitEvent;
use pocketmine\event\inventory\InventoryPickupArrowEvent;
@ -50,9 +51,6 @@ class Arrow extends Projectile{
private const TAG_PICKUP = "pickup"; //TAG_Byte
public $width = 0.25;
public $height = 0.25;
protected $gravity = 0.05;
protected $drag = 0.01;
@ -76,6 +74,8 @@ class Arrow extends Projectile{
$this->setCritical($critical);
}
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -24,16 +24,16 @@ declare(strict_types=1);
namespace pocketmine\entity\projectile;
use pocketmine\block\Block;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\math\RayTraceResult;
abstract class Throwable extends Projectile{
public $width = 0.25;
public $height = 0.25;
protected $gravity = 0.03;
protected $drag = 0.01;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
parent::onHitBlock($blockHit, $hitResult);
$this->flagForDespawn();

View File

@ -1657,7 +1657,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$entity->attack($ev);
$soundPos = $entity->getPosition()->add(0, $entity->height / 2, 0);
$soundPos = $entity->getPosition()->add(0, $entity->size->getHeight() / 2, 0);
if($ev->isCancelled()){
$this->getWorld()->addSound($soundPos, new EntityAttackNoDamageSound());
return false;