mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 16:51:42 +00:00
Added basic support for blocks with multiple AABBs, fixed stairs (#1303)
This commit is contained in:
parent
0c092a7ceb
commit
15d6fd86e2
@ -71,6 +71,10 @@ class Air extends Transparent{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getCollisionBoxes() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
@ -69,6 +69,10 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/** @var AxisAlignedBB */
|
||||
public $boundingBox = null;
|
||||
|
||||
|
||||
/** @var AxisAlignedBB[]|null */
|
||||
protected $collisionBoxes = null;
|
||||
|
||||
/**
|
||||
* @param int $id The block type's ID, 0-255
|
||||
* @param int $meta Meta value of the block type
|
||||
@ -489,9 +493,15 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return bool
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||
$bb2 = $this->getBoundingBox();
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
|
||||
return $bb2 !== null and $bb->intersectsWith($bb2);
|
||||
foreach($bbs as $bb2){
|
||||
if($bb->intersectsWith($bb2)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,6 +511,28 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
public function getCollisionBoxes() : array{
|
||||
if($this->collisionBoxes === null){
|
||||
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
||||
}
|
||||
|
||||
return $this->collisionBoxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
if($bb = $this->recalculateBoundingBox()){
|
||||
return [$bb];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB|null
|
||||
*/
|
||||
@ -532,19 +564,36 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return MovingObjectPosition|null
|
||||
*/
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?MovingObjectPosition{
|
||||
$bb = $this->getBoundingBox();
|
||||
if($bb === null){
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
if(empty($bbs)){
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = $bb->calculateIntercept($pos1, $pos2);
|
||||
if($result !== null){
|
||||
$result->blockX = $this->x;
|
||||
$result->blockY = $this->y;
|
||||
$result->blockZ = $this->z;
|
||||
/** @var MovingObjectPosition|null $currentHit */
|
||||
$currentHit = null;
|
||||
/** @var int|float $currentDistance */
|
||||
$currentDistance = PHP_INT_MAX;
|
||||
|
||||
foreach($bbs as $bb){
|
||||
$nextHit = $bb->calculateIntercept($pos1, $pos2);
|
||||
if($nextHit === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextDistance = $nextHit->hitVector->distanceSquared($pos1);
|
||||
if($nextDistance < $currentDistance){
|
||||
$currentHit = $nextHit;
|
||||
$currentDistance = $nextDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
if($currentHit !== null){
|
||||
$currentHit->blockX = $this->x;
|
||||
$currentHit->blockY = $this->y;
|
||||
$currentHit->blockZ = $this->z;
|
||||
}
|
||||
|
||||
return $currentHit;
|
||||
}
|
||||
|
||||
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){
|
||||
|
@ -31,103 +31,56 @@ use pocketmine\Player;
|
||||
|
||||
abstract class Stair extends Transparent{
|
||||
|
||||
/*
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
|
||||
$damage = $this->getDamage();
|
||||
$j = $damage & 0x03;
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
//TODO: handle corners
|
||||
|
||||
$f = 0;
|
||||
$f1 = 0.5;
|
||||
$f2 = 0.5;
|
||||
$f3 = 1;
|
||||
$minYSlab = ($this->meta & 0x04) === 0 ? 0 : 0.5;
|
||||
$maxYSlab = $minYSlab + 0.5;
|
||||
|
||||
if(($damage & 0x04) > 0){
|
||||
$f = 0.5;
|
||||
$f1 = 1;
|
||||
$f2 = 0;
|
||||
$f3 = 0.5;
|
||||
$bbs = [
|
||||
new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $minYSlab,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $maxYSlab,
|
||||
$this->z + 1
|
||||
)
|
||||
];
|
||||
|
||||
$minY = ($this->meta & 0x04) === 0 ? 0.5 : 0;
|
||||
$maxY = $minY + 0.5;
|
||||
|
||||
$rotationMeta = $this->meta & 0x03;
|
||||
|
||||
$minX = $minZ = 0;
|
||||
$maxX = $maxZ = 1;
|
||||
|
||||
switch($rotationMeta){
|
||||
case 0:
|
||||
$minX = 0.5;
|
||||
break;
|
||||
case 1:
|
||||
$maxX = 0.5;
|
||||
break;
|
||||
case 2:
|
||||
$minZ = 0.5;
|
||||
break;
|
||||
case 3:
|
||||
$maxZ = 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f1,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
$bbs[] = new AxisAlignedBB(
|
||||
$this->x + $minX,
|
||||
$this->y + $minY,
|
||||
$this->z + $minZ,
|
||||
$this->x + $maxX,
|
||||
$this->y + $maxY,
|
||||
$this->z + $maxZ
|
||||
);
|
||||
|
||||
if($j === 0){
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x + 0.5,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 0.5,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z + 0.5,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 0.5
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.5,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
return $bbs;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
|
||||
|
@ -1497,9 +1497,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public function isInsideOfSolid() : bool{
|
||||
$block = $this->level->getBlock($this->temporalVector->setComponents(Math::floorFloat($this->x), Math::floorFloat($y = ($this->y + $this->getEyeHeight())), Math::floorFloat($this->z)));
|
||||
|
||||
$bb = $block->getBoundingBox();
|
||||
|
||||
return $bb !== null and $block->isSolid() and !$block->isTransparent() and $bb->intersectsWith($this->getBoundingBox());
|
||||
return $block->isSolid() and !$block->isTransparent() and $block->collidesWithBB($this->getBoundingBox());
|
||||
}
|
||||
|
||||
public function fastMove(float $dx, float $dy, float $dz) : bool{
|
||||
|
@ -1188,7 +1188,9 @@ class Level implements ChunkManager, Metadatable{
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$block = $this->getBlock($this->temporalVector->setComponents($x, $y, $z));
|
||||
if(!$block->canPassThrough() and $block->collidesWithBB($bb)){
|
||||
$collides[] = $block->getBoundingBox();
|
||||
foreach($block->getCollisionBoxes() as $blockBB){
|
||||
$collides[] = $blockBB;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1789,21 +1791,23 @@ class Level implements ChunkManager, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($hand->isSolid() === true and $hand->getBoundingBox() !== null){
|
||||
$entities = $this->getCollidingEntities($hand->getBoundingBox());
|
||||
foreach($entities as $e){
|
||||
if($e instanceof Arrow or $e instanceof DroppedItem or ($e instanceof Player and $e->isSpectator())){
|
||||
continue;
|
||||
if($hand->isSolid()){
|
||||
foreach($hand->getCollisionBoxes() as $collisionBox){
|
||||
$entities = $this->getCollidingEntities($collisionBox);
|
||||
foreach($entities as $e){
|
||||
if($e instanceof Arrow or $e instanceof DroppedItem or ($e instanceof Player and $e->isSpectator())){
|
||||
continue;
|
||||
}
|
||||
|
||||
return false; //Entity in block
|
||||
}
|
||||
|
||||
return false; //Entity in block
|
||||
}
|
||||
|
||||
if($player !== null){
|
||||
if(($diff = $player->getNextPosition()->subtract($player->getPosition())) and $diff->lengthSquared() > 0.00001){
|
||||
$bb = $player->getBoundingBox()->getOffsetBoundingBox($diff->x, $diff->y, $diff->z);
|
||||
if($hand->getBoundingBox()->intersectsWith($bb)){
|
||||
return false; //Inside player BB
|
||||
if($player !== null){
|
||||
if(($diff = $player->getNextPosition()->subtract($player->getPosition())) and $diff->lengthSquared() > 0.00001){
|
||||
$bb = $player->getBoundingBox()->getOffsetBoundingBox($diff->x, $diff->y, $diff->z);
|
||||
if($collisionBox->intersectsWith($bb)){
|
||||
return false; //Inside player BB
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user