Skip to content

Commit 2f3c77c

Browse files
committed
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
1 parent 02f42eb commit 2f3c77c

10 files changed

Lines changed: 122 additions & 162 deletions

File tree

src/pocketmine/Player.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,10 @@ protected function updateMovement(){
16191619

16201620
}
16211621

1622+
protected function tryChangeMovement(){
1623+
1624+
}
1625+
16221626
public function sendAttributes(bool $sendAll = false){
16231627
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
16241628
if(count($entries) > 0){

src/pocketmine/entity/Arrow.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,12 @@ public function getResultDamage() : int{
6262
}
6363
}
6464

65-
public function onUpdate(int $currentTick) : bool{
65+
public function entityBaseTick(int $tickDiff = 1) : bool{
6666
if($this->closed){
6767
return false;
6868
}
6969

70-
$this->timings->startTiming();
71-
72-
$hasUpdate = parent::onUpdate($currentTick);
70+
$hasUpdate = parent::entityBaseTick($tickDiff);
7371

7472
if($this->onGround or $this->hadCollision){
7573
$this->setCritical(false);
@@ -80,8 +78,6 @@ public function onUpdate(int $currentTick) : bool{
8078
$hasUpdate = true;
8179
}
8280

83-
$this->timings->stopTiming();
84-
8581
return $hasUpdate;
8682
}
8783

src/pocketmine/entity/Entity.php

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363

6464
abstract class Entity extends Location implements Metadatable{
6565

66+
const MOTION_THRESHOLD = 0.00001;
67+
6668
const NETWORK_ID = -1;
6769

6870
const DATA_TYPE_BYTE = 0;
@@ -270,6 +272,8 @@ public static function init(){
270272
public $lastMotionY;
271273
/** @var float */
272274
public $lastMotionZ;
275+
/** @var bool */
276+
protected $forceMovementUpdate = false;
273277

274278
/** @var float */
275279
public $lastYaw;
@@ -1198,6 +1202,35 @@ protected function updateMovement(){
11981202
}
11991203
}
12001204

1205+
protected function applyDragBeforeGravity() : bool{
1206+
return false;
1207+
}
1208+
1209+
protected function applyGravity(){
1210+
$this->motionY -= $this->gravity;
1211+
}
1212+
1213+
protected function tryChangeMovement(){
1214+
$friction = 1 - $this->drag;
1215+
1216+
if(!$this->onGround){
1217+
if($this->applyDragBeforeGravity()){
1218+
$this->motionY *= $friction;
1219+
}
1220+
1221+
$this->applyGravity();
1222+
1223+
if(!$this->applyDragBeforeGravity()){
1224+
$this->motionY *= $friction;
1225+
}
1226+
}else{
1227+
$friction = $this->level->getBlock($this->floor()->subtract(0, 1, 0))->getFrictionFactor();
1228+
}
1229+
1230+
$this->motionX *= $friction;
1231+
$this->motionZ *= $friction;
1232+
}
1233+
12011234
/**
12021235
* @return Vector3
12031236
*/
@@ -1240,23 +1273,66 @@ public function onUpdate(int $currentTick) : bool{
12401273

12411274
$this->timings->startTiming();
12421275

1276+
if($this->hasMovementUpdate()){
1277+
$this->tryChangeMovement();
1278+
$this->move($this->motionX, $this->motionY, $this->motionZ);
1279+
1280+
if(abs($this->motionX) <= self::MOTION_THRESHOLD){
1281+
$this->motionX = 0;
1282+
}
1283+
if(abs($this->motionY) <= self::MOTION_THRESHOLD){
1284+
$this->motionY = 0;
1285+
}
1286+
if(abs($this->motionZ) <= self::MOTION_THRESHOLD){
1287+
$this->motionZ = 0;
1288+
}
1289+
1290+
$this->updateMovement();
1291+
$this->forceMovementUpdate = false;
1292+
}
1293+
12431294
Timings::$timerEntityBaseTick->startTiming();
12441295
$hasUpdate = $this->entityBaseTick($tickDiff);
12451296
Timings::$timerEntityBaseTick->stopTiming();
12461297

1247-
$this->updateMovement();
1298+
12481299

12491300
$this->timings->stopTiming();
12501301

12511302
//if($this->isStatic())
1252-
return $hasUpdate;
1303+
return ($hasUpdate or $this->hasMovementUpdate());
12531304
//return !($this instanceof Player);
12541305
}
12551306

12561307
final public function scheduleUpdate(){
12571308
$this->level->updateEntities[$this->id] = $this;
12581309
}
12591310

1311+
/**
1312+
* Flags the entity as needing a movement update on the next tick. Setting this forces a movement update even if the
1313+
* entity's motion is zero. Used to trigger movement updates when blocks change near entities.
1314+
*
1315+
* @param bool $value
1316+
*/
1317+
final public function setForceMovementUpdate(bool $value = true){
1318+
$this->forceMovementUpdate = $value;
1319+
$this->onGround = false;
1320+
}
1321+
1322+
/**
1323+
* Returns whether the entity needs a movement update on the next tick.
1324+
* @return bool
1325+
*/
1326+
final public function hasMovementUpdate() : bool{
1327+
return (
1328+
$this->forceMovementUpdate or
1329+
abs($this->motionX) > self::MOTION_THRESHOLD or
1330+
abs($this->motionY) > self::MOTION_THRESHOLD or
1331+
abs($this->motionZ) > self::MOTION_THRESHOLD or
1332+
!$this->onGround
1333+
);
1334+
}
1335+
12601336
public function isOnFire() : bool{
12611337
return $this->fireTicks > 0;
12621338
}

src/pocketmine/entity/FallingSand.php

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -80,34 +80,14 @@ public function attack($damage, EntityDamageEvent $source){
8080
}
8181
}
8282

83-
public function onUpdate(int $currentTick) : bool{
84-
83+
public function entityBaseTick(int $tickDiff = 1) : bool{
8584
if($this->closed){
8685
return false;
8786
}
8887

89-
$this->timings->startTiming();
90-
91-
$tickDiff = $currentTick - $this->lastUpdate;
92-
if($tickDiff <= 0 and !$this->justCreated){
93-
return true;
94-
}
95-
96-
$this->lastUpdate = $currentTick;
97-
98-
$hasUpdate = $this->entityBaseTick($tickDiff);
88+
$hasUpdate = parent::entityBaseTick($tickDiff);
9989

10090
if($this->isAlive()){
101-
$this->motionY -= $this->gravity;
102-
103-
$this->move($this->motionX, $this->motionY, $this->motionZ);
104-
105-
$friction = 1 - $this->drag;
106-
107-
$this->motionX *= $friction;
108-
$this->motionY *= 1 - $this->drag;
109-
$this->motionZ *= $friction;
110-
11191
$pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor();
11292

11393
if($this->onGround){
@@ -124,11 +104,9 @@ public function onUpdate(int $currentTick) : bool{
124104
}
125105
$hasUpdate = true;
126106
}
127-
128-
$this->updateMovement();
129107
}
130108

131-
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
109+
return $hasUpdate;
132110
}
133111

134112
public function getBlock(){

src/pocketmine/entity/Item.php

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -98,55 +98,21 @@ public function attack($damage, EntityDamageEvent $source){
9898
}
9999
}
100100

101-
public function onUpdate(int $currentTick) : bool{
101+
public function entityBaseTick(int $tickDiff = 1) : bool{
102102
if($this->closed){
103103
return false;
104104
}
105105

106-
$tickDiff = $currentTick - $this->lastUpdate;
107-
if($tickDiff <= 0 and !$this->justCreated){
108-
return true;
109-
}
110-
111-
$this->lastUpdate = $currentTick;
112-
113-
$this->timings->startTiming();
114-
115-
$hasUpdate = $this->entityBaseTick($tickDiff);
106+
$hasUpdate = parent::entityBaseTick($tickDiff);
116107

117108
if($this->isAlive()){
118-
119109
if($this->pickupDelay > 0 and $this->pickupDelay < 32767){ //Infinite delay
120110
$this->pickupDelay -= $tickDiff;
121111
if($this->pickupDelay < 0){
122112
$this->pickupDelay = 0;
123113
}
124114
}
125115

126-
$this->motionY -= $this->gravity;
127-
128-
if($this->checkObstruction($this->x, $this->y, $this->z)){
129-
$hasUpdate = true;
130-
}
131-
132-
$this->move($this->motionX, $this->motionY, $this->motionZ);
133-
134-
$friction = 1 - $this->drag;
135-
136-
if($this->onGround and (abs($this->motionX) > 0.00001 or abs($this->motionZ) > 0.00001)){
137-
$friction = $this->getLevel()->getBlock($this->temporalVector->setComponents((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z) - 1))->getFrictionFactor() * $friction;
138-
}
139-
140-
$this->motionX *= $friction;
141-
$this->motionY *= 1 - $this->drag;
142-
$this->motionZ *= $friction;
143-
144-
if($this->onGround){
145-
$this->motionY *= -0.5;
146-
}
147-
148-
$this->updateMovement();
149-
150116
if($this->age > 6000){
151117
$this->server->getPluginManager()->callEvent($ev = new ItemDespawnEvent($this));
152118
if($ev->isCancelled()){
@@ -159,9 +125,16 @@ public function onUpdate(int $currentTick) : bool{
159125

160126
}
161127

162-
$this->timings->stopTiming();
128+
return $hasUpdate;
129+
}
130+
131+
protected function tryChangeMovement(){
132+
$this->checkObstruction($this->x, $this->y, $this->z);
133+
parent::tryChangeMovement();
134+
}
163135

164-
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
136+
protected function applyDragBeforeGravity() : bool{
137+
return true;
165138
}
166139

167140
public function saveNBT(){

src/pocketmine/entity/PrimedTNT.php

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -79,58 +79,27 @@ public function saveNBT(){
7979
$this->namedtag->Fuse = new ByteTag("Fuse", $this->fuse);
8080
}
8181

82-
public function onUpdate(int $currentTick) : bool{
83-
82+
public function entityBaseTick(int $tickDiff = 1) : bool{
8483
if($this->closed){
8584
return false;
8685
}
8786

88-
$this->timings->startTiming();
89-
90-
$tickDiff = $currentTick - $this->lastUpdate;
91-
if($tickDiff <= 0 and !$this->justCreated){
92-
return true;
93-
}
87+
$hasUpdate = parent::entityBaseTick($tickDiff);
9488

9589
if($this->fuse % 5 === 0){ //don't spam it every tick, it's not necessary
9690
$this->setDataProperty(self::DATA_FUSE_LENGTH, self::DATA_TYPE_INT, $this->fuse);
9791
}
9892

99-
$this->lastUpdate = $currentTick;
100-
101-
$hasUpdate = $this->entityBaseTick($tickDiff);
102-
10393
if($this->isAlive()){
104-
105-
$this->motionY -= $this->gravity;
106-
107-
$this->move($this->motionX, $this->motionY, $this->motionZ);
108-
109-
$friction = 1 - $this->drag;
110-
111-
$this->motionX *= $friction;
112-
$this->motionY *= $friction;
113-
$this->motionZ *= $friction;
114-
115-
$this->updateMovement();
116-
117-
if($this->onGround){
118-
$this->motionY *= -0.5;
119-
$this->motionX *= 0.7;
120-
$this->motionZ *= 0.7;
121-
}
122-
12394
$this->fuse -= $tickDiff;
12495

12596
if($this->fuse <= 0){
12697
$this->kill();
12798
$this->explode();
12899
}
129-
130100
}
131101

132-
133-
return $hasUpdate or $this->fuse >= 0 or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
102+
return $hasUpdate or $this->fuse >= 0;
134103
}
135104

136105
public function explode(){

0 commit comments

Comments
 (0)