mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-19 15:35:52 +00:00
Fixed entity move performance issue and a ton of entity movement bugs
- fixed zombies and villagers movement not updating - fixed dropped items "movement" lagging the living **** out of the server when not actually moving - fixed arrows not falling when the supporting block is removed - fixed knockback - fixed zombies + villagers being un-attackable after hitting them ... the list goes on
This commit is contained in:
parent
02f42eba48
commit
2f3c77c68a
@ -1619,6 +1619,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
}
|
||||
|
||||
protected function tryChangeMovement(){
|
||||
|
||||
}
|
||||
|
||||
public function sendAttributes(bool $sendAll = false){
|
||||
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
|
||||
if(count($entries) > 0){
|
||||
|
@ -62,14 +62,12 @@ class Arrow extends Projectile{
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$hasUpdate = parent::onUpdate($currentTick);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->onGround or $this->hadCollision){
|
||||
$this->setCritical(false);
|
||||
@ -80,8 +78,6 @@ class Arrow extends Projectile{
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@ use pocketmine\Server;
|
||||
|
||||
abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
const MOTION_THRESHOLD = 0.00001;
|
||||
|
||||
const NETWORK_ID = -1;
|
||||
|
||||
const DATA_TYPE_BYTE = 0;
|
||||
@ -270,6 +272,8 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public $lastMotionY;
|
||||
/** @var float */
|
||||
public $lastMotionZ;
|
||||
/** @var bool */
|
||||
protected $forceMovementUpdate = false;
|
||||
|
||||
/** @var float */
|
||||
public $lastYaw;
|
||||
@ -1198,6 +1202,35 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
protected function applyDragBeforeGravity() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function applyGravity(){
|
||||
$this->motionY -= $this->gravity;
|
||||
}
|
||||
|
||||
protected function tryChangeMovement(){
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if(!$this->onGround){
|
||||
if($this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
|
||||
$this->applyGravity();
|
||||
|
||||
if(!$this->applyDragBeforeGravity()){
|
||||
$this->motionY *= $friction;
|
||||
}
|
||||
}else{
|
||||
$friction = $this->level->getBlock($this->floor()->subtract(0, 1, 0))->getFrictionFactor();
|
||||
}
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionZ *= $friction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vector3
|
||||
*/
|
||||
@ -1240,16 +1273,34 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
if($this->hasMovementUpdate()){
|
||||
$this->tryChangeMovement();
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
if(abs($this->motionX) <= self::MOTION_THRESHOLD){
|
||||
$this->motionX = 0;
|
||||
}
|
||||
if(abs($this->motionY) <= self::MOTION_THRESHOLD){
|
||||
$this->motionY = 0;
|
||||
}
|
||||
if(abs($this->motionZ) <= self::MOTION_THRESHOLD){
|
||||
$this->motionZ = 0;
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
$this->forceMovementUpdate = false;
|
||||
}
|
||||
|
||||
Timings::$timerEntityBaseTick->startTiming();
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
Timings::$timerEntityBaseTick->stopTiming();
|
||||
|
||||
$this->updateMovement();
|
||||
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
//if($this->isStatic())
|
||||
return $hasUpdate;
|
||||
return ($hasUpdate or $this->hasMovementUpdate());
|
||||
//return !($this instanceof Player);
|
||||
}
|
||||
|
||||
@ -1257,6 +1308,31 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$this->level->updateEntities[$this->id] = $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags the entity as needing a movement update on the next tick. Setting this forces a movement update even if the
|
||||
* entity's motion is zero. Used to trigger movement updates when blocks change near entities.
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
final public function setForceMovementUpdate(bool $value = true){
|
||||
$this->forceMovementUpdate = $value;
|
||||
$this->onGround = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the entity needs a movement update on the next tick.
|
||||
* @return bool
|
||||
*/
|
||||
final public function hasMovementUpdate() : bool{
|
||||
return (
|
||||
$this->forceMovementUpdate or
|
||||
abs($this->motionX) > self::MOTION_THRESHOLD or
|
||||
abs($this->motionY) > self::MOTION_THRESHOLD or
|
||||
abs($this->motionZ) > self::MOTION_THRESHOLD or
|
||||
!$this->onGround
|
||||
);
|
||||
}
|
||||
|
||||
public function isOnFire() : bool{
|
||||
return $this->fireTicks > 0;
|
||||
}
|
||||
|
@ -80,34 +80,14 @@ class FallingSand extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$tickDiff = $currentTick - $this->lastUpdate;
|
||||
if($tickDiff <= 0 and !$this->justCreated){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->isAlive()){
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
$pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor();
|
||||
|
||||
if($this->onGround){
|
||||
@ -124,11 +104,9 @@ class FallingSand extends Entity{
|
||||
}
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
}
|
||||
|
||||
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
public function getBlock(){
|
||||
|
@ -98,24 +98,14 @@ class Item extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$tickDiff = $currentTick - $this->lastUpdate;
|
||||
if($tickDiff <= 0 and !$this->justCreated){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->isAlive()){
|
||||
|
||||
if($this->pickupDelay > 0 and $this->pickupDelay < 32767){ //Infinite delay
|
||||
$this->pickupDelay -= $tickDiff;
|
||||
if($this->pickupDelay < 0){
|
||||
@ -123,30 +113,6 @@ class Item extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
if($this->checkObstruction($this->x, $this->y, $this->z)){
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if($this->onGround and (abs($this->motionX) > 0.00001 or abs($this->motionZ) > 0.00001)){
|
||||
$friction = $this->getLevel()->getBlock($this->temporalVector->setComponents((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z) - 1))->getFrictionFactor() * $friction;
|
||||
}
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
if($this->onGround){
|
||||
$this->motionY *= -0.5;
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
|
||||
if($this->age > 6000){
|
||||
$this->server->getPluginManager()->callEvent($ev = new ItemDespawnEvent($this));
|
||||
if($ev->isCancelled()){
|
||||
@ -159,9 +125,16 @@ class Item extends Entity{
|
||||
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
protected function tryChangeMovement(){
|
||||
$this->checkObstruction($this->x, $this->y, $this->z);
|
||||
parent::tryChangeMovement();
|
||||
}
|
||||
|
||||
protected function applyDragBeforeGravity() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
|
@ -79,58 +79,27 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
$this->namedtag->Fuse = new ByteTag("Fuse", $this->fuse);
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$tickDiff = $currentTick - $this->lastUpdate;
|
||||
if($tickDiff <= 0 and !$this->justCreated){
|
||||
return true;
|
||||
}
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->fuse % 5 === 0){ //don't spam it every tick, it's not necessary
|
||||
$this->setDataProperty(self::DATA_FUSE_LENGTH, self::DATA_TYPE_INT, $this->fuse);
|
||||
}
|
||||
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
|
||||
if($this->isAlive()){
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= $friction;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
$this->updateMovement();
|
||||
|
||||
if($this->onGround){
|
||||
$this->motionY *= -0.5;
|
||||
$this->motionX *= 0.7;
|
||||
$this->motionZ *= 0.7;
|
||||
}
|
||||
|
||||
$this->fuse -= $tickDiff;
|
||||
|
||||
if($this->fuse <= 0){
|
||||
$this->kill();
|
||||
$this->explode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return $hasUpdate or $this->fuse >= 0 or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
return $hasUpdate or $this->fuse >= 0;
|
||||
}
|
||||
|
||||
public function explode(){
|
||||
|
@ -108,28 +108,20 @@ abstract class Projectile extends Entity{
|
||||
$this->namedtag->Age = new ShortTag("Age", $this->age);
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
protected function applyDragBeforeGravity() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$tickDiff = $currentTick - $this->lastUpdate;
|
||||
if($tickDiff <= 0 and !$this->justCreated){
|
||||
return true;
|
||||
}
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->isAlive()){
|
||||
|
||||
$movingObjectPosition = null;
|
||||
|
||||
if(!$this->isCollided){
|
||||
$this->motionY -= $this->gravity;
|
||||
}
|
||||
|
||||
$moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
|
||||
|
||||
$list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this);
|
||||
@ -170,8 +162,6 @@ abstract class Projectile extends Entity{
|
||||
}
|
||||
}
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
if($this->isCollided and !$this->hadCollision){ //Collided with a block
|
||||
$this->hadCollision = true;
|
||||
|
||||
@ -181,20 +171,16 @@ abstract class Projectile extends Entity{
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
|
||||
return false;
|
||||
}elseif(!$this->isCollided and $this->hadCollision){ //Collided with block, but block later removed
|
||||
//This currently doesn't work because the arrow's motion is all zeros when it's hit a block, so move() doesn't do any collision checks.
|
||||
//TODO: fix this
|
||||
}elseif(!$this->isCollided and $this->hadCollision){ //Previously collided with block, but block later removed
|
||||
$this->hadCollision = false;
|
||||
}
|
||||
|
||||
if(!$this->hadCollision or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001){
|
||||
if(!$this->hadCollision or abs($this->motionX) > self::MOTION_THRESHOLD or abs($this->motionY) > self::MOTION_THRESHOLD or abs($this->motionZ) > self::MOTION_THRESHOLD){
|
||||
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
|
||||
$this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI);
|
||||
$this->pitch = (atan2($this->motionY, $f) * 180 / M_PI);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
}
|
||||
|
||||
return $hasUpdate;
|
||||
|
@ -42,22 +42,18 @@ class Snowball extends Projectile{
|
||||
parent::__construct($level, $nbt, $shootingEntity);
|
||||
}
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$hasUpdate = parent::onUpdate($currentTick);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->age > 1200 or $this->isCollided){
|
||||
$this->kill();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
|
@ -78,21 +78,19 @@ class Squid extends WaterAnimal{
|
||||
}
|
||||
|
||||
|
||||
public function onUpdate(int $currentTick) : bool{
|
||||
public function entityBaseTick(int $tickDiff = 1) : bool{
|
||||
if($this->closed !== false){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(++$this->switchDirectionTicker === 100){
|
||||
if(++$this->switchDirectionTicker === 100 or $this->isCollided){
|
||||
$this->switchDirectionTicker = 0;
|
||||
if(mt_rand(0, 100) < 50){
|
||||
$this->swimDirection = null;
|
||||
}
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$hasUpdate = parent::onUpdate($currentTick);
|
||||
$hasUpdate = parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->isAlive()){
|
||||
|
||||
@ -102,7 +100,6 @@ class Squid extends WaterAnimal{
|
||||
|
||||
$inWater = $this->isInsideOfWater();
|
||||
if(!$inWater){
|
||||
$this->motionY -= $this->gravity;
|
||||
$this->swimDirection = null;
|
||||
}elseif($this->swimDirection !== null){
|
||||
if($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2 <= $this->swimDirection->lengthSquared()){
|
||||
@ -115,34 +112,18 @@ class Squid extends WaterAnimal{
|
||||
$this->swimSpeed = mt_rand(50, 100) / 2000;
|
||||
}
|
||||
|
||||
$expectedPos = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
if($expectedPos->distanceSquared($this) > 0){
|
||||
$this->swimDirection = $this->generateRandomDirection();
|
||||
$this->swimSpeed = mt_rand(50, 100) / 2000;
|
||||
}
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
|
||||
$this->yaw = (-atan2($this->motionX, $this->motionZ) * 180 / M_PI);
|
||||
$this->pitch = (-atan2($f, $this->motionY) * 180 / M_PI);
|
||||
|
||||
if($this->onGround){
|
||||
$this->motionY *= -0.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
protected function applyGravity(){
|
||||
if(!$this->isInsideOfWater()){
|
||||
parent::applyGravity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1512,7 +1512,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new BlockUpdateEvent($block));
|
||||
if(!$ev->isCancelled()){
|
||||
foreach($this->getNearbyEntities(new AxisAlignedBB($block->x - 1, $block->y - 1, $block->z - 1, $block->x + 1, $block->y + 1, $block->z + 1)) as $entity){
|
||||
foreach($this->getNearbyEntities(new AxisAlignedBB($block->x - 1, $block->y - 1, $block->z - 1, $block->x + 2, $block->y + 2, $block->z + 2)) as $entity){
|
||||
$entity->setForceMovementUpdate();
|
||||
$entity->scheduleUpdate();
|
||||
}
|
||||
$ev->getBlock()->onUpdate(self::BLOCK_UPDATE_NORMAL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user