diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index b37d0b6c7..06a984300 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1192,16 +1192,18 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->spawned === false or $this->dead === true){ return true; } $this->timings->startTiming(); + $this->lastUpdate = $currentTick; + $this->processMovement(); - $this->entityBaseTick(); + $this->entityBaseTick(1); if($this->onGround){ $this->inAirTicks = 0; @@ -1215,6 +1217,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } foreach($this->level->getNearbyEntities($this->boundingBox->grow(1, 1, 1), $this) as $entity){ + if(($currentTick - $entity->lastUpdate) > 1){ + $entity->scheduleUpdate(); + } + if($entity instanceof Arrow and $entity->onGround and $this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0){ if($entity->dead !== true){ $item = Item::get(Item::ARROW, 0, 1); diff --git a/src/pocketmine/entity/Arrow.php b/src/pocketmine/entity/Arrow.php index 98cee73b5..2b4712782 100644 --- a/src/pocketmine/entity/Arrow.php +++ b/src/pocketmine/entity/Arrow.php @@ -67,14 +67,17 @@ class Arrow extends Projectile{ } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->closed){ return false; } $this->timings->startTiming(); - $this->entityBaseTick(); + $tickDiff = max(1, $currentTick - $this->lastUpdate); + $this->lastUpdate = $currentTick; + + $hasUpdate = $this->entityBaseTick($tickDiff); if(!$this->dead){ @@ -143,6 +146,7 @@ class Arrow extends Projectile{ } $this->kill(); + return true; } } @@ -156,14 +160,16 @@ class Arrow extends Projectile{ $this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this)); } - if($this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){ + if(!$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){ $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; } if($this->age > 1200){ $this->kill(); + $hasUpdate = true; } $this->updateMovement(); @@ -171,7 +177,7 @@ class Arrow extends Projectile{ $this->timings->stopTiming(); - return !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); + return $hasUpdate; } public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){ diff --git a/src/pocketmine/entity/DroppedItem.php b/src/pocketmine/entity/DroppedItem.php index 94468caca..93e99366b 100644 --- a/src/pocketmine/entity/DroppedItem.php +++ b/src/pocketmine/entity/DroppedItem.php @@ -73,19 +73,22 @@ class DroppedItem extends Entity{ $this->server->getPluginManager()->callEvent(new ItemSpawnEvent($this)); } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->closed !== false){ return false; } + $tickDiff = max(1, $currentTick - $this->lastUpdate); + $this->lastUpdate = $currentTick; + $this->timings->startTiming(); - $this->entityBaseTick(); + $hasUpdate = $this->entityBaseTick($tickDiff); if(!$this->dead){ if($this->pickupDelay > 0 and $this->pickupDelay < 32767){ //Infinite delay - --$this->pickupDelay; + $this->pickupDelay -= $tickDiff; } $this->motionY -= $this->gravity; @@ -115,6 +118,7 @@ class DroppedItem extends Entity{ $this->age = 0; }else{ $this->kill(); + $hasUpdate = true; } } @@ -122,7 +126,7 @@ class DroppedItem extends Entity{ $this->timings->stopTiming(); - return !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); + return $hasUpdate or !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); } public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 1a001363d..a2ca413f5 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -142,8 +142,6 @@ abstract class Entity extends Location implements Metadatable{ protected $fireProof; private $invulnerable; - protected $spawnTime; - protected $gravity; protected $drag; @@ -215,7 +213,7 @@ abstract class Entity extends Location implements Metadatable{ $this->chunk->addEntity($this); $this->getLevel()->addEntity($this); $this->initEntity(); - $this->lastUpdate = $this->spawnTime = microtime(true); + $this->lastUpdate = $this->server->getTick(); $this->server->getPluginManager()->callEvent(new EntitySpawnEvent($this)); $this->scheduleUpdate(); @@ -462,7 +460,7 @@ abstract class Entity extends Location implements Metadatable{ } } - public function entityBaseTick(){ + public function entityBaseTick($tickDiff = 1){ Timings::$tickEntityTimer->startTiming(); //TODO: check vehicles @@ -476,7 +474,7 @@ abstract class Entity extends Location implements Metadatable{ $this->close(); } Timings::$tickEntityTimer->stopTiming(); - return false; + return $isPlayer; } $hasUpdate = false; @@ -488,36 +486,39 @@ abstract class Entity extends Location implements Metadatable{ if(!$ev->isCancelled()){ $this->attack($ev->getFinalDamage(), $ev); } + $hasUpdate = true; } if($this->fireTicks > 0){ if($this->fireProof){ - $this->fireTicks -= 4; + $this->fireTicks -= 4 * $tickDiff; if($this->fireTicks < 0){ $this->fireTicks = 0; } }else{ - if(($this->fireTicks % 20) === 0){ + if(($this->fireTicks % 20) === 0 or $tickDiff > 20){ $ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FIRE_TICK, 1); $this->server->getPluginManager()->callEvent($ev); if(!$ev->isCancelled()){ $this->attack($ev->getFinalDamage(), $ev); } } - --$this->fireTicks; + $this->fireTicks -= $tickDiff; } if($this->fireTicks <= 0){ $this->extinguish(); + }else{ + $hasUpdate = true; } - - $hasUpdate = true; } - ++$this->age; - ++$this->ticksLived; + $this->age += $tickDiff; + $this->ticksLived += $tickDiff; Timings::$tickEntityTimer->stopTiming(); + + return $hasUpdate; } public function updateMovement(){ @@ -587,20 +588,24 @@ abstract class Entity extends Location implements Metadatable{ return new Vector3($x, $y, $z); } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->closed){ return false; } + + $tickDiff = max(1, $currentTick - $this->lastUpdate); + $this->lastUpdate = $currentTick; + $this->timings->startTiming(); - $hasUpdate = $this->entityBaseTick(); + $hasUpdate = $this->entityBaseTick($tickDiff); $this->updateMovement(); $this->timings->stopTiming(); //if($this->isStatic()) - return true; + return $hasUpdate; //return !($this instanceof Player); } diff --git a/src/pocketmine/entity/FallingBlock.php b/src/pocketmine/entity/FallingBlock.php index fac159185..ac83fe800 100644 --- a/src/pocketmine/entity/FallingBlock.php +++ b/src/pocketmine/entity/FallingBlock.php @@ -66,7 +66,7 @@ class FallingBlock extends Entity{ return []; } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->closed){ return false; @@ -74,7 +74,10 @@ class FallingBlock extends Entity{ $this->timings->startTiming(); - $this->entityBaseTick(); + $tickDiff = max(1, $currentTick - $this->lastUpdate); + $this->lastUpdate = $currentTick; + + $hasUpdate = $this->entityBaseTick($tickDiff); if(!$this->dead){ if($this->ticksLived === 1){ @@ -110,13 +113,13 @@ class FallingBlock extends Entity{ $this->getLevel()->setBlock($pos, $ev->getTo(), true); } } + $hasUpdate = true; } $this->updateMovement(); } - - return !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); + return $hasUpdate or !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); } public function getBlock(){ diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index d3b4f7fdc..837a925a6 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -130,7 +130,7 @@ abstract class Living extends Entity implements Damageable{ } } - public function entityBaseTick(){ + public function entityBaseTick($tickDiff = 1){ Timings::$timerEntityBaseTick->startTiming(); parent::entityBaseTick(); @@ -142,7 +142,7 @@ abstract class Living extends Entity implements Damageable{ } if($this->dead !== true and $this->isInsideOfWater()){ - --$this->airTicks; + $this->airTicks -= $tickDiff; if($this->airTicks <= -20){ $this->airTicks = 0; @@ -156,7 +156,7 @@ abstract class Living extends Entity implements Damageable{ } if($this->attackTime > 0){ - --$this->attackTime; + $this->attackTime -= $tickDiff; } Timings::$timerEntityBaseTick->stopTiming(); diff --git a/src/pocketmine/entity/PrimedTNT.php b/src/pocketmine/entity/PrimedTNT.php index 9f9a93c46..160da00bc 100644 --- a/src/pocketmine/entity/PrimedTNT.php +++ b/src/pocketmine/entity/PrimedTNT.php @@ -71,7 +71,7 @@ class PrimedTNT extends Entity implements Explosive{ $this->namedtag->Fuse = new Byte("Fuse", $this->fuse); } - public function onUpdate(){ + public function onUpdate($currentTick){ if($this->closed){ return false; @@ -79,7 +79,10 @@ class PrimedTNT extends Entity implements Explosive{ $this->timings->startTiming(); - $this->entityBaseTick(); + $tickDiff = max(1, $currentTick - $this->lastUpdate); + $this->lastUpdate = $currentTick; + + $hasUpdate = $this->entityBaseTick($tickDiff); if(!$this->dead){ @@ -101,7 +104,9 @@ class PrimedTNT extends Entity implements Explosive{ $this->motionZ *= 0.7; } - if($this->fuse-- <= 0){ + $this->fuse -= $tickDiff; + + if($this->fuse <= 0){ $this->kill(); $this->explode(); }else{ @@ -111,7 +116,7 @@ class PrimedTNT extends Entity implements Explosive{ } - return !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); + return $hasUpdate or $this->fuse > 0 or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); } public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){ diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 4f278c14b..88c16043b 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -264,6 +264,7 @@ class Level implements ChunkManager, Metadatable{ $this->chunksPerTick = (int) $this->server->getProperty("chunk-ticking.per-tick", 80); $this->chunkTickList = []; $this->clearChunksOnTick = (bool) $this->server->getProperty("chunk-ticking.clear-tick-list", false); + $this->timings = new LevelTimings($this); } @@ -472,15 +473,13 @@ class Level implements ChunkManager, Metadatable{ $this->timings->entityTick->startTiming(); //Update entities that need update - //if(count($this->updateEntities) > 0){ - Timings::$tickEntityTimer->startTiming(); - foreach($this->entities as $id => $entity){ - if(!$entity->closed){ - $entity->onUpdate(); - } + Timings::$tickEntityTimer->startTiming(); + foreach($this->updateEntities as $id => $entity){ + if(!$entity->closed or !$entity->onUpdate($currentTick)){ + unset($this->updateEntities[$id]); } - Timings::$tickEntityTimer->stopTiming(); - //} + } + Timings::$tickEntityTimer->stopTiming(); $this->timings->entityTick->stopTiming(); $this->timings->tileEntityTick->startTiming(); @@ -593,6 +592,10 @@ class Level implements ChunkManager, Metadatable{ } $chunk = $this->getChunk($chunkX, $chunkZ, true); + foreach($chunk->getEntities() as $entity){ + $entity->scheduleUpdate(); + } + if($this->useSections){ foreach($chunk->getSections() as $section){ @@ -965,6 +968,9 @@ class Level implements ChunkManager, Metadatable{ if($update === true){ $this->updateAround($pos, self::BLOCK_UPDATE_NORMAL); $block->onUpdate(self::BLOCK_UPDATE_NORMAL); + 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->scheduleUpdate(); + } } } } @@ -1730,6 +1736,7 @@ class Level implements ChunkManager, Metadatable{ } unset($this->entities[$entity->getID()]); + unset($this->updateEntities[$entity->getID()]); } /** @@ -1770,6 +1777,7 @@ class Level implements ChunkManager, Metadatable{ } unset($this->tiles[$tile->getID()]); + unset($this->updateTiles[$tile->getID()]); } /**