|
63 | 63 |
|
64 | 64 | abstract class Entity extends Location implements Metadatable{ |
65 | 65 |
|
| 66 | + const MOTION_THRESHOLD = 0.00001; |
| 67 | + |
66 | 68 | const NETWORK_ID = -1; |
67 | 69 |
|
68 | 70 | const DATA_TYPE_BYTE = 0; |
@@ -270,6 +272,8 @@ public static function init(){ |
270 | 272 | public $lastMotionY; |
271 | 273 | /** @var float */ |
272 | 274 | public $lastMotionZ; |
| 275 | + /** @var bool */ |
| 276 | + protected $forceMovementUpdate = false; |
273 | 277 |
|
274 | 278 | /** @var float */ |
275 | 279 | public $lastYaw; |
@@ -1198,6 +1202,35 @@ protected function updateMovement(){ |
1198 | 1202 | } |
1199 | 1203 | } |
1200 | 1204 |
|
| 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 | + |
1201 | 1234 | /** |
1202 | 1235 | * @return Vector3 |
1203 | 1236 | */ |
@@ -1240,23 +1273,66 @@ public function onUpdate(int $currentTick) : bool{ |
1240 | 1273 |
|
1241 | 1274 | $this->timings->startTiming(); |
1242 | 1275 |
|
| 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 | + |
1243 | 1294 | Timings::$timerEntityBaseTick->startTiming(); |
1244 | 1295 | $hasUpdate = $this->entityBaseTick($tickDiff); |
1245 | 1296 | Timings::$timerEntityBaseTick->stopTiming(); |
1246 | 1297 |
|
1247 | | - $this->updateMovement(); |
| 1298 | + |
1248 | 1299 |
|
1249 | 1300 | $this->timings->stopTiming(); |
1250 | 1301 |
|
1251 | 1302 | //if($this->isStatic()) |
1252 | | - return $hasUpdate; |
| 1303 | + return ($hasUpdate or $this->hasMovementUpdate()); |
1253 | 1304 | //return !($this instanceof Player); |
1254 | 1305 | } |
1255 | 1306 |
|
1256 | 1307 | final public function scheduleUpdate(){ |
1257 | 1308 | $this->level->updateEntities[$this->id] = $this; |
1258 | 1309 | } |
1259 | 1310 |
|
| 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 | + |
1260 | 1336 | public function isOnFire() : bool{ |
1261 | 1337 | return $this->fireTicks > 0; |
1262 | 1338 | } |
|
0 commit comments