From 9fb46d8fe8041859e0d788e062bfc1cfc97a4614 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Thu, 28 Aug 2014 18:26:37 +0200 Subject: [PATCH] Fixed entity physics --- src/pocketmine/Player.php | 2 +- src/pocketmine/entity/Entity.php | 284 +++++++++++++++----------- src/pocketmine/math/AxisAlignedBB.php | 53 +++-- 3 files changed, 202 insertions(+), 137 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 5d20038f1..512c0e779 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1517,7 +1517,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ case 5: //Shot arrow //if($this->entity->inAction === true){ if($this->inventory->getItemInHand()->getID() === Item::BOW){ - $f = 1 * 2 * 1.5; + $f = 1.5; $nbt = new Compound("", [ "Pos" => new Enum("Pos", [ new Double("", $this->x), diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index a71b5dd1a..9431fbbd6 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -169,13 +169,10 @@ abstract class Entity extends Position implements Metadatable{ $this->namedtag["Pos"][2] ), $this->namedtag->Rotation[0], - $this->namedtag->Rotation[1] - ); - $this->setMotion(new Vector3( - $this->namedtag["Motion"][0], - $this->namedtag["Motion"][1], - $this->namedtag["Motion"][2]) + $this->namedtag->Rotation[1], + true ); + $this->setMotion(new Vector3($this->namedtag["Motion"][0], $this->namedtag["Motion"][1], $this->namedtag["Motion"][2])); if(!isset($this->namedtag->FallDistance)){ $this->namedtag->FallDistance = new Float("FallDistance", 0); @@ -206,8 +203,9 @@ abstract class Entity extends Position implements Metadatable{ $this->getLevel()->addEntity($this); $this->initEntity(); $this->lastUpdate = $this->spawnTime = microtime(true); - $this->justCreated = false; $this->server->getPluginManager()->callEvent(new EntitySpawnEvent($this)); + $this->onUpdate(); + $this->justCreated = false; $this->scheduleUpdate(); } @@ -360,7 +358,7 @@ abstract class Entity extends Position implements Metadatable{ } public function canCollideWith(Entity $entity){ - return true; + return !$this->justCreated; } protected function checkObstruction($x, $y, $z){ @@ -715,91 +713,66 @@ abstract class Entity extends Position implements Metadatable{ } public function move($dx, $dy, $dz){ - //$collision = []; - //$this->checkBlockCollision($collision); - if($dx == 0 and $dz == 0 and $dy == 0){ - return; - } + if($this->inBlock){ + $this->boundingBox->offset($dx, $dy, $dz); + $this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; + $this->y = $this->boundingBox->minY + $this->height; + $this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; + }else{ + //$collision = []; + //$this->checkBlockCollision($collision); + if($dx == 0 and $dz == 0 and $dy == 0){ + return; + } - Timings::$entityMoveTimer->startTiming(); + Timings::$entityMoveTimer->startTiming(); - $ox = $this->x; - $oy = $this->y; - $oz = $this->z; + $ox = $this->x; + $oy = $this->y; + $oz = $this->z; - if($this->isColliding){ //With an entity - $this->isColliding = false; - $dx *= 0.25; - $dy *= 0.05; - $dz *= 0.25; - $this->motionX = 0; - $this->motionY = 0; - $this->motionZ = 0; - } + if($this->isColliding){ //With an entity + $this->isColliding = false; + $dx *= 0.25; + $dy *= 0.05; + $dz *= 0.25; + $this->motionX = 0; + $this->motionY = 0; + $this->motionZ = 0; + } - $movX = $dx; - $movY = $dy; - $movZ = $dz; + $movX = $dx; + $movY = $dy; + $movZ = $dz; - /*$sneakFlag = $this->onGround and $this instanceof Player; + $axisalignedbb = clone $this->boundingBox; - if($sneakFlag){ - for($mov = 0.05; $dx != 0.0 and count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, -1, 0))) === 0; $movX = $dx){ - if($dx < $mov and $dx >= -$mov){ - $dx = 0; - }elseif($dx > 0){ - $dx -= $mov; - }else{ - $dx += $mov; + /*$sneakFlag = $this->onGround and $this instanceof Player; + + if($sneakFlag){ + for($mov = 0.05; $dx != 0.0 and count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, -1, 0))) === 0; $movX = $dx){ + if($dx < $mov and $dx >= -$mov){ + $dx = 0; + }elseif($dx > 0){ + $dx -= $mov; + }else{ + $dx += $mov; + } } - } - for(; $dz != 0.0 and count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox(0, -1, $dz))) === 0; $movZ = $dz){ - if($dz < $mov and $dz >= -$mov){ - $dz = 0; - }elseif($dz > 0){ - $dz -= $mov; - }else{ - $dz += $mov; + for(; $dz != 0.0 and count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox(0, -1, $dz))) === 0; $movZ = $dz){ + if($dz < $mov and $dz >= -$mov){ + $dz = 0; + }elseif($dz > 0){ + $dz -= $mov; + }else{ + $dz += $mov; + } } - } - //TODO: big messy loop - }*/ + //TODO: big messy loop + }*/ - if(count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox(0, $dy, 0))) > 0){ - $dy = 0; - $dx = 0; - $dz = 0; - } - - $fallingFlag = $this->onGround or ($dy != $movY and $movY < 0); - - if($dx != 0){ - if(count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, 0, 0))) > 0){ - $dy = 0; - $dx = 0; - $dz = 0; - } - } - - if($dz != 0){ - if(count($this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox(0, 0, $dz))) > 0){ - $dy = 0; - $dx = 0; - $dz = 0; - } - } - - if($movX != $dx or $movZ != $dz or $fallingFlag){ - - $cx = $dx; - $cy = $dy; - $cz = $dz; - $dx = $movX; - $dy = 0; - $dz = $movZ; - $oldBB = clone $this->boundingBox; $list = $this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($movX, $dy, $movZ)); @@ -807,7 +780,7 @@ abstract class Entity extends Position implements Metadatable{ $dy = $bb->calculateYOffset($this->boundingBox, $dy); } - $this->boundingBox->addCoord(0, $dy, 0); + $this->boundingBox->offset(0, $dy, 0); if($movY != $dy){ $dx = 0; @@ -815,11 +788,13 @@ abstract class Entity extends Position implements Metadatable{ $dz = 0; } + $fallingFlag = $this->onGround or ($dy != $movY and $movY < 0); + foreach($list as $bb){ $dx = $bb->calculateXOffset($this->boundingBox, $dx); } - $this->boundingBox->addCoord($dx, 0, 0); + $this->boundingBox->offset($dx, 0, 0); if($movX != $dx){ $dx = 0; @@ -831,7 +806,7 @@ abstract class Entity extends Position implements Metadatable{ $dz = $bb->calculateZOffset($this->boundingBox, $dz); } - $this->boundingBox->addCoord(0, 0, $dz); + $this->boundingBox->offset(0, 0, $dz); if($movZ != $dz){ $dx = 0; @@ -845,49 +820,110 @@ abstract class Entity extends Position implements Metadatable{ $dy = $bb->calculateYOffset($this->boundingBox, $dy); } - $this->boundingBox->addCoord(0, $dy, 0); + $this->boundingBox->offset(0, $dy, 0); } - if($cx * $cx + $cz * $cz > $dx * $dx + $dz * $dz){ - $dx = $cx; - $dy = $cy; - $dz = $cz; - $this->boundingBox->setBB($oldBB); + + if($this->gravity > 0 and $fallingFlag and $this->onGround and ($movX != $dx or $movZ != $dz)){ + $cx = $dx; + $cy = $dy; + $cz = $dz; + $dx = $movX; + $dy = $this->gravity; + $dz = $movZ; + + $axisalignedbb1 = clone $this->boundingBox; + + $this->boundingBox->setBB($axisalignedbb); + + $list = $this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($movX, $dy, $movZ)); + + foreach($list as $bb){ + $dy = $bb->calculateYOffset($this->boundingBox, $dy); + } + + if($movY != $dy){ + $dx = 0; + $dy = 0; + $dz = 0; + } + + foreach($list as $bb){ + $dx = $bb->calculateXOffset($this->boundingBox, $dx); + } + + $this->boundingBox->offset($dx, 0, 0); + if($movX != $dx){ + $dx = 0; + $dy = 0; + $dz = 0; + } + + foreach($list as $bb){ + $dz = $bb->calculateZOffset($this->boundingBox, $dz); + } + + $this->boundingBox->offset(0, 0, $dz); + if($movZ != $dz){ + $dx = 0; + $dy = 0; + $dz = 0; + } + + if($movY != $dy){ + $dx = 0; + $dy = 0; + $dz = 0; + }else{ + $dy = -$this->gravity; + foreach($list as $bb){ + $dy = $bb->calculateYOffset($this->boundingBox, $dy); + } + $this->boundingBox->offset(0, $dy, 0); + } + + if($cx * $cx + $cz * $cz > $dx * $dx + $dz * $dz){ + $dx = $cx; + $dy = $cy; + $dz = $cz; + $this->boundingBox->setBB($axisalignedbb1); + } + + } + + $this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; + $this->y = $this->boundingBox->minY + $this->height; + $this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; + + $this->onGround = $movY != $dy and $movY < 0; + $this->updateFallState($dy, $this->onGround); + + if($movX != $dx){ + $this->motionX = 0; + } + + if($movY != $dy){ + $this->motionY = 0; + } + + if($movZ != $dz){ + $this->motionZ = 0; + } + + $this->boundingBox->offset($dx, $dy, $dz); + $this->x += $dx; + $this->y += $dy; + $this->z += $dz; + + $cx = $this->x - $ox; + $cy = $this->y - $oy; + $cz = $this->z - $oz; + + //TODO: vehicle collision events (first we need to spawn them!) + + Timings::$entityMoveTimer->stopTiming(); } - - $this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; - $this->y = $this->boundingBox->minY + $this->height; - $this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; - - $this->onGround = $movY != $dy and $movY < 0; - $this->updateFallState($dy, $this->onGround); - - if($movX != $dx){ - $this->motionX = 0; - } - - if($movY != $dy){ - $this->motionY = 0; - } - - if($movZ != $dz){ - $this->motionZ = 0; - } - - $this->boundingBox->addCoord($dx, $dy, $dz); - $this->x += $dx; - $this->y += $dy; - $this->z += $dz; - - $cx = $this->x - $ox; - $cy = $this->y - $oy; - $cz = $this->z - $oz; - - //TODO: vehicle collision events (first we need to spawn them!) - - Timings::$entityMoveTimer->stopTiming(); - } /** diff --git a/src/pocketmine/math/AxisAlignedBB.php b/src/pocketmine/math/AxisAlignedBB.php index f85c88af1..401167442 100644 --- a/src/pocketmine/math/AxisAlignedBB.php +++ b/src/pocketmine/math/AxisAlignedBB.php @@ -75,7 +75,7 @@ class AxisAlignedBB{ return $this; } - public function expand($x, $y, $z){ + public function grow($x, $y, $z){ $vec = clone $this; $vec->minX -= $x; $vec->minY -= $y; @@ -87,19 +87,29 @@ class AxisAlignedBB{ return $vec; } - public function offset($x, $y, $z){ - $vec = clone $this; - $vec->minX += $x; - $vec->minY += $y; - $vec->minZ += $z; - $vec->maxX += $x; - $vec->maxY += $y; - $vec->maxZ += $z; + public function expand($x, $y, $z){ + $this->minX -= $x; + $this->minY -= $y; + $this->minZ -= $z; + $this->maxX += $x; + $this->maxY += $y; + $this->maxZ += $z; - return $vec; + return $this; } - public function contract($x, $y, $z){ + public function offset($x, $y, $z){ + $this->minX += $x; + $this->minY += $y; + $this->minZ += $z; + $this->maxX += $x; + $this->maxY += $y; + $this->maxZ += $z; + + return $this; + } + + public function shrink($x, $y, $z){ $vec = clone $this; $vec->minX += $x; $vec->minY += $y; @@ -111,6 +121,17 @@ class AxisAlignedBB{ return $vec; } + public function contract($x, $y, $z){ + $this->minX += $x; + $this->minY += $y; + $this->minZ += $z; + $this->maxX -= $x; + $this->maxY -= $y; + $this->maxZ -= $z; + + return $this; + } + public function setBB(AxisAlignedBB $bb){ return new AxisAlignedBB( min($this->minX, $bb->minX), @@ -123,7 +144,15 @@ class AxisAlignedBB{ } public function getOffsetBoundingBox($x, $y, $z){ - return new AxisAlignedBB($this->minX + $x, $this->minY + $y, $this->minZ + $z, $this->maxX + $x, $this->maxY + $y, $this->maxZ + $z); + $vec = clone $this; + $vec->minX += $x; + $vec->minY += $y; + $vec->minZ += $z; + $vec->maxX += $x; + $vec->maxY += $y; + $vec->maxZ += $z; + + return $vec; } public function calculateXOffset(AxisAlignedBB $bb, $x){