Skip to content

Commit

Permalink
Fixed entity move performance issue and a ton of entity movement bugs
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
dktapps committed Aug 20, 2017
1 parent 02f42eb commit 2f3c77c
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 162 deletions.
4 changes: 4 additions & 0 deletions src/pocketmine/Player.php
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,10 @@ protected function updateMovement(){

}

protected function tryChangeMovement(){

}

public function sendAttributes(bool $sendAll = false){
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
if(count($entries) > 0){
Expand Down
8 changes: 2 additions & 6 deletions src/pocketmine/entity/Arrow.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,12 @@ public function getResultDamage() : int{
}
}

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);
Expand All @@ -80,8 +78,6 @@ public function onUpdate(int $currentTick) : bool{
$hasUpdate = true;
}

$this->timings->stopTiming();

return $hasUpdate;
}

Expand Down
80 changes: 78 additions & 2 deletions src/pocketmine/entity/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@

abstract class Entity extends Location implements Metadatable{

const MOTION_THRESHOLD = 0.00001;

const NETWORK_ID = -1;

const DATA_TYPE_BYTE = 0;
Expand Down Expand Up @@ -270,6 +272,8 @@ public static function init(){
public $lastMotionY;
/** @var float */
public $lastMotionZ;
/** @var bool */
protected $forceMovementUpdate = false;

/** @var float */
public $lastYaw;
Expand Down Expand Up @@ -1198,6 +1202,35 @@ protected function updateMovement(){
}
}

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
*/
Expand Down Expand Up @@ -1240,23 +1273,66 @@ public function onUpdate(int $currentTick) : bool{

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

final public function scheduleUpdate(){
$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;
}
Expand Down
28 changes: 3 additions & 25 deletions src/pocketmine/entity/FallingSand.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,34 +80,14 @@ public function attack($damage, EntityDamageEvent $source){
}
}

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){
Expand All @@ -124,11 +104,9 @@ public function onUpdate(int $currentTick) : bool{
}
$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(){
Expand Down
49 changes: 11 additions & 38 deletions src/pocketmine/entity/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,55 +98,21 @@ public function attack($damage, EntityDamageEvent $source){
}
}

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){
$this->pickupDelay = 0;
}
}

$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()){
Expand All @@ -159,9 +125,16 @@ public function onUpdate(int $currentTick) : bool{

}

$this->timings->stopTiming();
return $hasUpdate;
}

protected function tryChangeMovement(){
$this->checkObstruction($this->x, $this->y, $this->z);
parent::tryChangeMovement();
}

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 applyDragBeforeGravity() : bool{
return true;
}

public function saveNBT(){
Expand Down
37 changes: 3 additions & 34 deletions src/pocketmine/entity/PrimedTNT.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,58 +79,27 @@ public function saveNBT(){
$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(){
Expand Down

0 comments on commit 2f3c77c

Please sign in to comment.